diff --git a/braintrust-sdk/instrumentation/anthropic_2_2_0/src/main/java/dev/braintrust/instrumentation/anthropic/v2_2_0/TracingHttpClient.java b/braintrust-sdk/instrumentation/anthropic_2_2_0/src/main/java/dev/braintrust/instrumentation/anthropic/v2_2_0/TracingHttpClient.java index 8dc0824c..2f392f08 100644 --- a/braintrust-sdk/instrumentation/anthropic_2_2_0/src/main/java/dev/braintrust/instrumentation/anthropic/v2_2_0/TracingHttpClient.java +++ b/braintrust-sdk/instrumentation/anthropic_2_2_0/src/main/java/dev/braintrust/instrumentation/anthropic/v2_2_0/TracingHttpClient.java @@ -303,7 +303,8 @@ private static void tagSpanFromBuffer(Span span, byte[] bytes, Long timeToFirstT InstrumentationSemConv.tagLLMSpanResponse( span, InstrumentationSemConv.PROVIDER_NAME_ANTHROPIC, - new String(bytes, StandardCharsets.UTF_8)); + new String(bytes, StandardCharsets.UTF_8), + null); } } catch (Exception e) { log.error("Could not tag span from Anthropic response buffer", e); diff --git a/braintrust-sdk/instrumentation/anthropic_2_2_0/src/test/java/dev/braintrust/instrumentation/anthropic/v2_2_0/BraintrustAnthropicPromptCachingTest.java b/braintrust-sdk/instrumentation/anthropic_2_2_0/src/test/java/dev/braintrust/instrumentation/anthropic/v2_2_0/BraintrustAnthropicPromptCachingTest.java new file mode 100644 index 00000000..4027c68e --- /dev/null +++ b/braintrust-sdk/instrumentation/anthropic_2_2_0/src/test/java/dev/braintrust/instrumentation/anthropic/v2_2_0/BraintrustAnthropicPromptCachingTest.java @@ -0,0 +1,190 @@ +package dev.braintrust.instrumentation.anthropic.v2_2_0; + +import static org.junit.jupiter.api.Assertions.*; + +import com.anthropic.client.AnthropicClient; +import com.anthropic.client.okhttp.AnthropicOkHttpClient; +import com.anthropic.core.JsonValue; +import com.anthropic.models.messages.CacheControlEphemeral; +import com.anthropic.models.messages.MessageCreateParams; +import com.anthropic.models.messages.TextBlockParam; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import dev.braintrust.TestHarness; +import dev.braintrust.instrumentation.Instrumenter; +import io.opentelemetry.api.common.AttributeKey; +import java.util.List; +import java.util.UUID; +import lombok.SneakyThrows; +import net.bytebuddy.agent.ByteBuddyAgent; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Tests that prompt caching metrics (per-TTL breakdown) are correctly extracted from Anthropic API + * responses and attached to spans. + * + *

Uses a cache-buster nonce in the system prompt to guarantee cache misses, ensuring {@code + * cache_creation_input_tokens} is always positive. In VCR replay mode the nonce is a fixed string + * so cassette matching still works. + */ +public class BraintrustAnthropicPromptCachingTest { + private static final String TEST_MODEL = "claude-sonnet-4-5-20250929"; + private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); + + /** + * Nonce injected into system prompts to bust Anthropic's server-side prompt cache. Random UUID + * when running live ({@code VCR_MODE=off}), fixed string otherwise so VCR cassettes match. + */ + private static final String VCR_NONCE; + + static { + String vcrMode = System.getenv().getOrDefault("VCR_MODE", "replay").toUpperCase(); + VCR_NONCE = "OFF".equals(vcrMode) ? UUID.randomUUID().toString() : "vcr-mode"; + } + + @BeforeAll + public static void beforeAll() { + var instrumentation = ByteBuddyAgent.install(); + Instrumenter.install( + instrumentation, BraintrustAnthropicPromptCachingTest.class.getClassLoader()); + } + + private TestHarness testHarness; + + @BeforeEach + void beforeEach() { + testHarness = TestHarness.setup(); + } + + /** + * Sends a single request with two system content blocks — one cached at 5m TTL and one at 1h + * TTL — and verifies that the per-TTL prompt cache creation metrics are present on the span. + */ + @Test + @SneakyThrows + void testPromptCachingDualTtl() { + AnthropicClient client = + AnthropicOkHttpClient.builder() + .baseUrl(testHarness.anthropicBaseUrl()) + .apiKey(testHarness.anthropicApiKey()) + .build(); + + // 1h TTL block — must come before 5m (Anthropic requires descending TTL order). + // Requires the extended-cache-ttl beta header. + // The text must exceed Claude Sonnet's minimum cacheable size (~1024 tokens / ~4000 chars). + CacheControlEphemeral cacheControl1h = + CacheControlEphemeral.builder() + .putAdditionalProperty("ttl", JsonValue.from("1h")) + .build(); + + TextBlockParam systemBlock1h = + TextBlockParam.builder() + .text( + buildPaddedSystemText( + "1h-block", + "Reference: capitals include Paris, Berlin, Rome, Madrid," + + " Lisbon.")) + .cacheControl(cacheControl1h) + .build(); + + // 5m TTL block — default ephemeral cache. + CacheControlEphemeral cacheControl5m = + CacheControlEphemeral.builder() + .putAdditionalProperty("ttl", JsonValue.from("5m")) + .build(); + + TextBlockParam systemBlock5m = + TextBlockParam.builder() + .text( + buildPaddedSystemText( + "5m-block", + "You are a helpful geography assistant. Answer in one" + + " sentence.")) + .cacheControl(cacheControl5m) + .build(); + + var request = + MessageCreateParams.builder() + .model(TEST_MODEL) + .systemOfTextBlockParams(List.of(systemBlock1h, systemBlock5m)) + .addUserMessage("What is the capital of France?") + .maxTokens(128) + .temperature(0.0) + .putAdditionalHeader("anthropic-beta", "extended-cache-ttl-2025-04-11") + .build(); + + var response = client.messages().create(request); + + // Basic response sanity + assertNotNull(response); + assertNotNull(response.id()); + var contentBlock = response.content().get(0); + assertTrue(contentBlock.isText()); + assertFalse(contentBlock.asText().text().isEmpty()); + + // Verify span metrics + var spans = testHarness.awaitExportedSpans(); + assertEquals(1, spans.size()); + var span = spans.get(0); + + String metricsJson = span.getAttributes().get(AttributeKey.stringKey("braintrust.metrics")); + assertNotNull(metricsJson, "metrics should be present"); + JsonNode metrics = JSON_MAPPER.readTree(metricsJson); + + // Standard token metrics + assertPositive(metrics, "prompt_tokens"); + assertPositive(metrics, "completion_tokens"); + assertPositive(metrics, "tokens"); + + // Per-TTL breakdown — both should be positive on a cold cache + assertFalse( + metrics.has("prompt_cache_creation_tokens"), + "anthropic cache tokens must be set INSTEAD of the aggregate meteric"); + assertPositive(metrics, "prompt_cache_creation_5m_tokens"); + assertPositive(metrics, "prompt_cache_creation_1h_tokens"); + assertEquals( + response.usage().cacheCreationInputTokens().get(), + (metrics.get("prompt_cache_creation_5m_tokens").intValue() + + metrics.get("prompt_cache_creation_1h_tokens").intValue()), + "ttl tokens should sum to total token count"); + + // Cache read may be 0 on cold cache, but should be present and non-negative + assertTrue(metrics.has("prompt_cached_tokens"), "prompt_cached_tokens should be present"); + assertTrue( + metrics.get("prompt_cached_tokens").asDouble() >= 0, + "prompt_cached_tokens should be non-negative"); + } + + private static void assertPositive(JsonNode metrics, String field) { + assertTrue(metrics.has(field), field + " should be present"); + assertTrue( + metrics.get(field).isNumber(), + field + " should be a number, got: " + metrics.get(field)); + assertTrue( + metrics.get(field).asDouble() > 0, + field + " should be positive, got: " + metrics.get(field).asDouble()); + } + + /** + * Build a system prompt text padded to exceed the minimum cacheable size (~4000 ASCII chars). + * Includes the VCR nonce and a block identifier for cache isolation. + */ + private String buildPaddedSystemText(String blockId, String coreInstruction) { + StringBuilder sb = new StringBuilder(); + sb.append("[cache-buster: ").append(blockId).append(" ").append(VCR_NONCE).append("]\n"); + sb.append(coreInstruction).append("\n\n"); + + // Pad with numbered guidelines to exceed the token minimum. + for (int i = 1; i <= 80; i++) { + sb.append(i) + .append(". This is guideline number ") + .append(i) + .append(". It exists to pad the system prompt past the minimum cacheable ") + .append("token threshold for Claude Sonnet models. Each guideline adds ") + .append("approximately fifty tokens of padding text to the prompt.\n"); + } + return sb.toString(); + } +} diff --git a/braintrust-sdk/instrumentation/anthropic_2_2_0/src/test/java/dev/braintrust/instrumentation/anthropic/v2_2_0/BraintrustAnthropicTest.java b/braintrust-sdk/instrumentation/anthropic_2_2_0/src/test/java/dev/braintrust/instrumentation/anthropic/v2_2_0/BraintrustAnthropicTest.java index 88200acd..4b1695dc 100644 --- a/braintrust-sdk/instrumentation/anthropic_2_2_0/src/test/java/dev/braintrust/instrumentation/anthropic/v2_2_0/BraintrustAnthropicTest.java +++ b/braintrust-sdk/instrumentation/anthropic_2_2_0/src/test/java/dev/braintrust/instrumentation/anthropic/v2_2_0/BraintrustAnthropicTest.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Test; public class BraintrustAnthropicTest { + private static final String TEST_MODEL = "claude-haiku-4-5"; private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); @BeforeAll @@ -45,7 +46,7 @@ void testWrapAnthropic() { var request = MessageCreateParams.builder() - .model(Model.CLAUDE_3_HAIKU_20240307) + .model(Model.of(TEST_MODEL)) .system("You are a helpful assistant") .addUserMessage("What is the capital of France?") .maxTokens(50) @@ -82,8 +83,8 @@ void testWrapAnthropic() { JsonNode metadata = JSON_MAPPER.readTree(metadataJson); assertEquals("anthropic", metadata.get("provider").asText()); assertTrue( - metadata.get("model").asText().startsWith("claude-3-haiku"), - "model should start with claude-3-haiku"); + metadata.get("model").asText().startsWith("claude-haiku-4"), + "model should start with claude-haiku-4"); // Verify input String inputJson = @@ -128,7 +129,7 @@ void testWrapAnthropicStreaming() { var request = MessageCreateParams.builder() - .model(Model.CLAUDE_3_HAIKU_20240307) + .model(Model.of(TEST_MODEL)) .system("You are a helpful assistant") .addUserMessage("What is the capital of France?") .maxTokens(50) @@ -200,7 +201,7 @@ void testWrapAnthropicAsync() { var request = MessageCreateParams.builder() - .model(Model.CLAUDE_3_HAIKU_20240307) + .model(Model.of(TEST_MODEL)) .system("You are a helpful assistant") .addUserMessage("What is the capital of France?") .maxTokens(50) @@ -263,7 +264,7 @@ void testWrapAnthropicAsyncStreaming() { var request = MessageCreateParams.builder() - .model(Model.CLAUDE_3_HAIKU_20240307) + .model(Model.of(TEST_MODEL)) .system("You are a helpful assistant") .addUserMessage("What is the capital of France?") .maxTokens(50) @@ -322,7 +323,7 @@ void testWrapAnthropicBeta() { var request = com.anthropic.models.beta.messages.MessageCreateParams.builder() - .model(Model.CLAUDE_3_HAIKU_20240307) + .model(Model.of(TEST_MODEL)) .system("You are a helpful assistant") .addUserMessage("What is the capital of France?") .maxTokens(50) @@ -357,8 +358,8 @@ void testWrapAnthropicBeta() { JsonNode metadata = JSON_MAPPER.readTree(metadataJson); assertEquals("anthropic", metadata.get("provider").asText()); assertTrue( - metadata.get("model").asText().startsWith("claude-3-haiku"), - "model should start with claude-3-haiku"); + metadata.get("model").asText().startsWith("claude-haiku-4"), + "model should start with claude-haiku-4"); // Verify input String inputJson = @@ -403,7 +404,7 @@ void testWrapAnthropicBetaStreaming() { var request = com.anthropic.models.beta.messages.MessageCreateParams.builder() - .model(Model.CLAUDE_3_HAIKU_20240307) + .model(Model.of(TEST_MODEL)) .system("You are a helpful assistant") .addUserMessage("What is the capital of France?") .maxTokens(50) diff --git a/braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java b/braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java index 05c04afd..fd0209fc 100644 --- a/braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java +++ b/braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java @@ -13,7 +13,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class InstrumentationSemConv { public static final String PROVIDER_NAME_OPENAI = "openai"; public static final String PROVIDER_NAME_ANTHROPIC = "anthropic"; @@ -258,6 +260,22 @@ private static void tagAnthropicResponse( "tokens", usage.get("input_tokens").asLong() + usage.get("output_tokens").asLong()); } + + // Prompt caching metrics + if (usage.has("cache_read_input_tokens")) { + metrics.put("prompt_cached_tokens", usage.get("cache_read_input_tokens")); + } + if (usage.has("cache_creation_input_tokens")) { + long cacheCreationTokens = usage.get("cache_creation_input_tokens").asLong(); + + // Per-TTL breakdown from usage.cache_creation (e.g. + // ephemeral_5m_input_tokens, ephemeral_1h_input_tokens). + // When per-TTL metrics are emitted, the aggregate metric is omitted. + boolean emittedPerTtl = addPerTtlCacheMetrics(metrics, usage); + if (!emittedPerTtl) { + metrics.put("prompt_cache_creation_tokens", cacheCreationTokens); + } + } } if (!metrics.isEmpty()) { @@ -265,6 +283,38 @@ private static void tagAnthropicResponse( } } + /** + * Mapping from Anthropic {@code usage.cache_creation} field names to Braintrust per-TTL metric + * names. Only supported TTL tiers are included. + */ + private static final Map CACHE_CREATION_FIELD_TO_METRIC = + Map.of( + "ephemeral_5m_input_tokens", "prompt_cache_creation_5m_tokens", + "ephemeral_1h_input_tokens", "prompt_cache_creation_1h_tokens"); + + /** + * Extract per-TTL cache creation metrics from the Anthropic {@code usage.cache_creation} + * response object. Fields like {@code ephemeral_5m_input_tokens} are mapped to {@code + * prompt_cache_creation_5m_tokens}. + * + * @return {@code true} if at least one per-TTL metric was emitted + */ + private static boolean addPerTtlCacheMetrics(Map metrics, JsonNode usage) { + if (!usage.has("cache_creation")) { + return false; + } + JsonNode cacheCreation = usage.get("cache_creation"); + boolean emitted = false; + for (Map.Entry entry : CACHE_CREATION_FIELD_TO_METRIC.entrySet()) { + if (cacheCreation.has(entry.getKey())) { + long tokens = cacheCreation.get(entry.getKey()).asLong(); + metrics.put(entry.getValue(), tokens); + emitted = true; + } + } + return emitted; + } + // ------------------------------------------------------------------------- // AWS Bedrock provider implementation // ------------------------------------------------------------------------- diff --git a/btx/src/test/java/dev/braintrust/sdkspecimpl/LlmSpanSpec.java b/btx/src/test/java/dev/braintrust/sdkspecimpl/LlmSpanSpec.java index b8b96fbe..a3ba3fe1 100644 --- a/btx/src/test/java/dev/braintrust/sdkspecimpl/LlmSpanSpec.java +++ b/btx/src/test/java/dev/braintrust/sdkspecimpl/LlmSpanSpec.java @@ -30,6 +30,7 @@ public record LlmSpanSpec( String provider, String endpoint, String client, + Map headers, List> requests, List> expectedBrainstoreSpans, String sourcePath) { @@ -59,11 +60,28 @@ static LlmSpanSpec fromMap(Map raw, String sourcePath, String cl String provider = (String) raw.get("provider"); String endpoint = (String) raw.get("endpoint"); + Map headers = null; + if (raw.containsKey("headers")) { + Map rawHeaders = (Map) raw.get("headers"); + headers = new java.util.LinkedHashMap<>(); + for (var entry : rawHeaders.entrySet()) { + headers.put(entry.getKey(), String.valueOf(entry.getValue())); + } + } + List> requests = (List>) raw.get("requests"); List> expectedSpans = (List>) raw.get("expected_brainstore_spans"); return new LlmSpanSpec( - name, type, provider, endpoint, client, requests, expectedSpans, sourcePath); + name, + type, + provider, + endpoint, + client, + headers, + requests, + expectedSpans, + sourcePath); } } diff --git a/btx/src/test/java/dev/braintrust/sdkspecimpl/SpanValidator.java b/btx/src/test/java/dev/braintrust/sdkspecimpl/SpanValidator.java index 637c9a81..1ae2925e 100644 --- a/btx/src/test/java/dev/braintrust/sdkspecimpl/SpanValidator.java +++ b/btx/src/test/java/dev/braintrust/sdkspecimpl/SpanValidator.java @@ -187,6 +187,32 @@ private static void assertFnMatcher(Object actual, SpecMatcher.FnMatcher fn, Str context, v)); } } + case "is_positive_number" -> { + if (!(actual instanceof Number)) { + fail( + String.format( + "%s: is_positive_number: expected a Number but got %s" + + " (value: %s)", + context, + actual == null ? "null" : actual.getClass().getSimpleName(), + actual)); + } + double v = ((Number) actual).doubleValue(); + if (v <= 0) { + fail( + String.format( + "%s: is_positive_number: value %s is not positive", + context, v)); + } + } + case "undefined_or_null" -> { + if (actual != null) { + fail( + String.format( + "%s: undefined_or_null: expected null but got %s (value: %s)", + context, actual.getClass().getSimpleName(), actual)); + } + } case "is_non_empty_string" -> { if (!(actual instanceof String) || ((String) actual).isEmpty()) { fail( diff --git a/btx/src/test/java/dev/braintrust/sdkspecimpl/SpecExecutor.java b/btx/src/test/java/dev/braintrust/sdkspecimpl/SpecExecutor.java index 40dda005..a47a9a16 100644 --- a/btx/src/test/java/dev/braintrust/sdkspecimpl/SpecExecutor.java +++ b/btx/src/test/java/dev/braintrust/sdkspecimpl/SpecExecutor.java @@ -25,17 +25,6 @@ import dev.braintrust.instrumentation.langchain.BraintrustLangchain; import dev.braintrust.instrumentation.openai.BraintrustOpenAI; import dev.braintrust.instrumentation.springai.v1_0_0.BraintrustSpringAI; -import dev.langchain4j.agent.tool.ToolSpecification; -import dev.langchain4j.data.message.ChatMessage; -import dev.langchain4j.data.message.Content; -import dev.langchain4j.data.message.ImageContent; -import dev.langchain4j.data.message.SystemMessage; -import dev.langchain4j.data.message.TextContent; -import dev.langchain4j.data.message.UserMessage; -import dev.langchain4j.model.chat.ChatModel; -import dev.langchain4j.model.chat.request.ChatRequest; -import dev.langchain4j.model.chat.request.json.JsonObjectSchema; -import dev.langchain4j.model.chat.response.StreamingChatResponseHandler; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.model.openai.OpenAiStreamingChatModel; import io.opentelemetry.api.trace.Span; @@ -49,22 +38,11 @@ import org.springframework.ai.anthropic.AnthropicChatModel; import org.springframework.ai.anthropic.AnthropicChatOptions; import org.springframework.ai.anthropic.api.AnthropicApi; -import org.springframework.ai.chat.messages.AssistantMessage; -import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.tool.ToolCallback; -import org.springframework.ai.tool.function.FunctionToolCallback; -import software.amazon.awssdk.core.SdkBytes; -import software.amazon.awssdk.services.bedrockruntime.model.ContentBlock; -import software.amazon.awssdk.services.bedrockruntime.model.ConversationRole; import software.amazon.awssdk.services.bedrockruntime.model.ConverseRequest; import software.amazon.awssdk.services.bedrockruntime.model.ConverseStreamRequest; import software.amazon.awssdk.services.bedrockruntime.model.ConverseStreamResponseHandler; -import software.amazon.awssdk.services.bedrockruntime.model.ImageBlock; -import software.amazon.awssdk.services.bedrockruntime.model.ImageFormat; -import software.amazon.awssdk.services.bedrockruntime.model.ImageSource; -import software.amazon.awssdk.services.bedrockruntime.model.Message; /** * Executes LLM spec tests in-process using the Braintrust Java SDK instrumentation. @@ -137,8 +115,7 @@ public String execute(LlmSpanSpec spec) throws Exception { List responsesHistory = new ArrayList<>(); for (Map request : spec.requests()) { - dispatchRequest( - spec.provider(), spec.endpoint(), spec.client(), request, responsesHistory); + dispatchRequest(spec, request, responsesHistory); } } finally { rootSpan.end(); @@ -147,12 +124,11 @@ public String execute(LlmSpanSpec spec) throws Exception { } private void dispatchRequest( - String provider, - String endpoint, - String client, - Map request, - List responsesHistory) + LlmSpanSpec spec, Map request, List responsesHistory) throws Exception { + String provider = spec.provider(); + String endpoint = spec.endpoint(); + String client = spec.client(); if ("openai".equals(provider) && "/v1/chat/completions".equals(endpoint)) { if ("langchain-openai".equals(client)) { executeLangChainChatCompletion(request); @@ -165,9 +141,9 @@ private void dispatchRequest( executeResponses(request, responsesHistory); } else if ("anthropic".equals(provider) && "/v1/messages".equals(endpoint)) { if ("springai-anthropic".equals(client)) { - executeSpringAiAnthropicMessages(request); + executeSpringAiAnthropicMessages(spec, request); } else { - executeAnthropicMessages(request); + executeAnthropicMessages(spec, request); } } else if ("bedrock".equals(provider) && endpoint.contains("/converse-stream")) { executeBedrockConverseStream(request); @@ -191,51 +167,15 @@ private void dispatchRequest( private void executeChatCompletion(Map request) throws Exception { boolean streaming = Boolean.TRUE.equals(request.get("stream")); - // Serialize the whole request map to JSON, then let the SDK's mapper deserialize each - // field into the correct SDK type — no manual field extraction needed. - String json = MAPPER.writeValueAsString(request); - com.fasterxml.jackson.databind.JsonNode node = ObjectMappers.jsonMapper().readTree(json); + // Ensure "stream" is always present in the body — the OpenAI API expects it + // and VCR cassettes were recorded with it. + Map bodyMap = new java.util.LinkedHashMap<>(request); + bodyMap.putIfAbsent("stream", false); + String json = MAPPER.writeValueAsString(bodyMap); + ChatCompletionCreateParams.Body body = + ObjectMappers.jsonMapper().readValue(json, ChatCompletionCreateParams.Body.class); + var params = ChatCompletionCreateParams.builder().body(body).build(); - var builder = ChatCompletionCreateParams.builder(); - if (node.has("model")) - builder.model(com.openai.models.ChatModel.of(node.get("model").asText())); - if (node.has("messages")) { - List msgs = - ObjectMappers.jsonMapper() - .convertValue( - node.get("messages"), - ObjectMappers.jsonMapper() - .getTypeFactory() - .constructCollectionType( - List.class, - com.openai.models.chat.completions - .ChatCompletionMessageParam.class)); - builder.messages(msgs); - } - if (node.has("tools")) { - List tools = - ObjectMappers.jsonMapper() - .convertValue( - node.get("tools"), - ObjectMappers.jsonMapper() - .getTypeFactory() - .constructCollectionType( - List.class, - com.openai.models.chat.completions - .ChatCompletionTool.class)); - builder.tools(tools); - } - if (node.has("temperature")) builder.temperature(node.get("temperature").asDouble()); - if (node.has("max_tokens")) builder.maxCompletionTokens(node.get("max_tokens").asLong()); - if (node.has("stream_options")) - builder.streamOptions( - ObjectMappers.jsonMapper() - .convertValue( - node.get("stream_options"), - com.openai.models.chat.completions.ChatCompletionStreamOptions - .class)); - - var params = builder.build(); if (streaming) { // Hold a reference to prevent GC-driven PhantomReachable cleanup before the stream // is fully consumed, which would close the SSE stream early. @@ -249,155 +189,144 @@ private void executeChatCompletion(Map request) throws Exception // ---- LangChain4j OpenAI chat/completions ------------------------------------ - @SuppressWarnings("unchecked") - private void executeLangChainChatCompletion(Map request) throws Exception { - var node = MAPPER.valueToTree(request); - boolean streaming = node.has("stream") && node.get("stream").asBoolean(); - - List messages = new ArrayList<>(); - for (Map msg : (List>) request.get("messages")) { - String role = (String) msg.get("role"); - Object rawContent = msg.get("content"); - switch (role) { - case "system" -> - messages.add( - SystemMessage.from( - rawContent != null ? rawContent.toString() : "")); - case "user" -> { - if (rawContent instanceof List) { - messages.add( - new UserMessage( - buildLangChainContents( - (List>) rawContent))); - } else { - messages.add( - UserMessage.from(rawContent != null ? rawContent.toString() : "")); + /** + * Jackson ObjectMapper for deserializing spec JSON into LangChain4j's internal {@link + * dev.langchain4j.model.openai.internal.chat.ChatCompletionRequest}. + * + *

LangChain4j's {@code Message} interface has no {@code @JsonTypeInfo}, so we register a + * custom deserializer that dispatches on the {@code role} field. + */ + private static final ObjectMapper LANGCHAIN_MAPPER = createLangChainMapper(); + + private static ObjectMapper createLangChainMapper() { + var module = new com.fasterxml.jackson.databind.module.SimpleModule(); + module.addDeserializer( + dev.langchain4j.model.openai.internal.chat.Message.class, + new com.fasterxml.jackson.databind.JsonDeserializer< + dev.langchain4j.model.openai.internal.chat.Message>() { + @Override + public dev.langchain4j.model.openai.internal.chat.Message deserialize( + com.fasterxml.jackson.core.JsonParser p, + com.fasterxml.jackson.databind.DeserializationContext ctx) + throws java.io.IOException { + com.fasterxml.jackson.databind.JsonNode node = p.getCodec().readTree(p); + String role = node.has("role") ? node.get("role").asText() : ""; + com.fasterxml.jackson.databind.ObjectMapper codec = + (com.fasterxml.jackson.databind.ObjectMapper) p.getCodec(); + return switch (role) { + case "system" -> + codec.treeToValue( + node, + dev.langchain4j.model.openai.internal.chat.SystemMessage + .class); + case "user" -> deserializeUserMessage(codec, node); + case "assistant" -> + codec.treeToValue( + node, + dev.langchain4j.model.openai.internal.chat + .AssistantMessage.class); + case "tool" -> + codec.treeToValue( + node, + dev.langchain4j.model.openai.internal.chat.ToolMessage + .class); + default -> + throw new java.io.IOException( + "Unsupported langchain message role: " + role); + }; } - } - default -> - throw new UnsupportedOperationException( - "langchain-openai: unsupported role: " + role); + }); + return new ObjectMapper() + .disable( + com.fasterxml.jackson.databind.DeserializationFeature + .FAIL_ON_IGNORED_PROPERTIES) + .disable( + com.fasterxml.jackson.databind.DeserializationFeature + .FAIL_ON_UNKNOWN_PROPERTIES) + .registerModule(module); + } + + /** + * Deserialize a LangChain4j UserMessage from a JSON node, handling the polymorphic {@code + * content} field (string vs array of Content blocks) that the Builder can't dispatch + * automatically. + */ + private static dev.langchain4j.model.openai.internal.chat.UserMessage deserializeUserMessage( + ObjectMapper mapper, com.fasterxml.jackson.databind.JsonNode node) + throws com.fasterxml.jackson.core.JsonProcessingException { + var builder = dev.langchain4j.model.openai.internal.chat.UserMessage.builder(); + if (node.has("content")) { + var content = node.get("content"); + if (content.isTextual()) { + builder.content(content.asText()); + } else if (content.isArray()) { + List list = + mapper.convertValue( + content, + mapper.getTypeFactory() + .constructCollectionType( + List.class, + dev.langchain4j.model.openai.internal.chat.Content + .class)); + builder.content(list); } } + if (node.has("name")) { + builder.name(node.get("name").asText()); + } + return builder.build(); + } + + private void executeLangChainChatCompletion(Map request) throws Exception { + boolean streaming = Boolean.TRUE.equals(request.get("stream")); + // Build a model just to get an instrumented client via BraintrustLangchain.wrap(). + dev.langchain4j.model.openai.internal.OpenAiClient langchainClient; if (streaming) { var modelBuilder = OpenAiStreamingChatModel.builder().baseUrl(openAiBaseUrl).apiKey(openAiApiKey); - if (node.has("model")) modelBuilder.modelName(node.get("model").asText()); - if (node.has("temperature")) - modelBuilder.temperature(node.get("temperature").asDouble()); - if (node.has("max_tokens")) modelBuilder.maxTokens(node.get("max_tokens").asInt()); var model = BraintrustLangchain.wrap(otel, modelBuilder); - var done = new CompletableFuture(); - model.chat( - messages, - new StreamingChatResponseHandler() { - @Override - public void onPartialResponse(String s) {} - - @Override - public void onCompleteResponse( - dev.langchain4j.model.chat.response.ChatResponse r) { - done.complete(null); - } - - @Override - public void onError(Throwable t) { - done.completeExceptionally(t); - } - }); - done.get(); + langchainClient = getPrivateField(model, "client"); } else { var modelBuilder = OpenAiChatModel.builder().baseUrl(openAiBaseUrl).apiKey(openAiApiKey); - if (node.has("model")) modelBuilder.modelName(node.get("model").asText()); - if (node.has("temperature")) - modelBuilder.temperature(node.get("temperature").asDouble()); - if (node.has("max_tokens")) modelBuilder.maxTokens(node.get("max_tokens").asInt()); - ChatModel model = BraintrustLangchain.wrap(otel, modelBuilder); - var reqBuilder = ChatRequest.builder().messages(messages); - if (node.has("tools")) { - reqBuilder.toolSpecifications(buildLangChainToolSpecs(node.get("tools"))); - } - model.chat(reqBuilder.build()); + OpenAiChatModel model = BraintrustLangchain.wrap(otel, modelBuilder); + langchainClient = getPrivateField(model, "client"); } - } - /** Build LangChain4j {@link Content} list from a multi-part YAML content array. */ - @SuppressWarnings("unchecked") - private static List buildLangChainContents(List> parts) { - List contents = new ArrayList<>(); - for (Map part : parts) { - String type = (String) part.get("type"); - if ("text".equals(type)) { - contents.add(new TextContent((String) part.get("text"))); - } else if ("image_url".equals(type)) { - Map imageUrl = (Map) part.get("image_url"); - String url = (String) imageUrl.get("url"); - if (url != null && url.startsWith("data:")) { - // data:;base64, - int semi = url.indexOf(';'); - int comma = url.indexOf(','); - String mimeType = semi > 0 ? url.substring(5, semi) : "image/png"; - String base64 = comma > 0 ? url.substring(comma + 1) : ""; - contents.add(new ImageContent(base64, mimeType)); - } else { - contents.add(new ImageContent(url)); - } - } + // Deserialize the spec JSON directly into LangChain4j's ChatCompletionRequest. + // The LANGCHAIN_MAPPER has custom deserializers for Message (role-based dispatch) + // and UserMessage (polymorphic string/array content handling). + String json = MAPPER.writeValueAsString(request); + var chatRequest = + LANGCHAIN_MAPPER.readValue( + json, + dev.langchain4j.model.openai.internal.chat.ChatCompletionRequest.class); + + if (streaming) { + var done = new CompletableFuture(); + langchainClient + .chatCompletion(chatRequest) + .onPartialResponse(response -> {}) + .onComplete(() -> done.complete(null)) + .onError(done::completeExceptionally) + .execute(); + done.get(); + } else { + langchainClient.chatCompletion(chatRequest).execute(); } - return contents; } - /** Build LangChain4j {@link ToolSpecification}s from the YAML {@code tools} array. */ - private static List buildLangChainToolSpecs( - com.fasterxml.jackson.databind.JsonNode toolsNode) { - List specs = new ArrayList<>(); - for (com.fasterxml.jackson.databind.JsonNode toolNode : toolsNode) { - com.fasterxml.jackson.databind.JsonNode fn = toolNode.get("function"); - if (fn == null) continue; - var schemaBuilder = JsonObjectSchema.builder(); - com.fasterxml.jackson.databind.JsonNode params = fn.get("parameters"); - if (params != null && params.has("properties")) { - List required = new ArrayList<>(); - if (params.has("required")) { - params.get("required").forEach(r -> required.add(r.asText())); - } - params.get("properties") - .fields() - .forEachRemaining( - entry -> { - var prop = entry.getValue(); - String name = entry.getKey(); - String desc = - prop.has("description") - ? prop.get("description").asText() - : null; - if (prop.has("enum")) { - List vals = new ArrayList<>(); - prop.get("enum").forEach(e -> vals.add(e.asText())); - schemaBuilder.addEnumProperty(name, vals); - } else { - schemaBuilder.addStringProperty(name, desc); - } - }); - schemaBuilder.required(required); - } - specs.add( - ToolSpecification.builder() - .name(fn.get("name").asText()) - .description( - fn.has("description") ? fn.get("description").asText() : null) - .parameters(schemaBuilder.build()) - .build()); - } - return specs; + @SuppressWarnings("unchecked") + private static T getPrivateField(Object obj, String fieldName) throws Exception { + var field = obj.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return (T) field.get(obj); } // ---- Spring AI OpenAI chat/completions -------------------------------------- private void executeSpringAiOpenAiChatCompletion(Map request) throws Exception { - var node = MAPPER.valueToTree(request); // Pass the full base URL (including /v1) and override completionsPath so Spring AI // appends just "/chat/completions" rather than the default "/v1/chat/completions". var api = @@ -406,162 +335,107 @@ private void executeSpringAiOpenAiChatCompletion(Map request) th .completionsPath("/chat/completions") .apiKey(openAiApiKey) .build(); - var optionsBuilder = OpenAiChatOptions.builder(); - if (node.has("model")) optionsBuilder.model(node.get("model").asText()); - if (node.has("temperature")) optionsBuilder.temperature(node.get("temperature").asDouble()); - if (node.has("max_tokens")) optionsBuilder.maxTokens(node.get("max_tokens").asInt()); - if (node.has("stream") && node.get("stream").asBoolean()) { - optionsBuilder.streamUsage(true); - } - if (node.has("tools")) { - optionsBuilder.toolCallbacks(buildSpringAiToolCallbacks(node.get("tools"))); - // Disable internal execution so tool_calls surface in the response output - optionsBuilder.internalToolExecutionEnabled(false); - } + + // We need to wrap the api's HTTP clients for instrumentation. The easiest way + // is to go through OpenAiChatModel.builder() + BraintrustSpringAI.wrap(), + // which instruments the RestClient/WebClient inside the api object in-place. var modelBuilder = org.springframework.ai.openai.OpenAiChatModel.builder() .openAiApi(api) - .defaultOptions(optionsBuilder.build()); + .defaultOptions(OpenAiChatOptions.builder().build()); BraintrustSpringAI.wrap(otel, modelBuilder); - var model = modelBuilder.build(); - var prompt = buildSpringAiPrompt(request); - if (node.has("stream") && node.get("stream").asBoolean()) { - model.stream(prompt).blockLast(); - } else { - model.call(prompt); - } - } - /** Build Spring AI {@link ToolCallback}s from the YAML {@code tools} array. */ - private static List buildSpringAiToolCallbacks( - com.fasterxml.jackson.databind.JsonNode toolsNode) { - List callbacks = new ArrayList<>(); - for (com.fasterxml.jackson.databind.JsonNode toolNode : toolsNode) { - com.fasterxml.jackson.databind.JsonNode fn = toolNode.get("function"); - if (fn == null) continue; - String paramsJson = fn.has("parameters") ? fn.get("parameters").toString() : "{}"; - callbacks.add( - FunctionToolCallback.builder( - fn.get("name").asText(), (String input) -> "not implemented") - .description( - fn.has("description") ? fn.get("description").asText() : "") - .inputSchema(paramsJson) - .inputType(String.class) - .build()); + // Deserialize the spec JSON directly into Spring AI's ChatCompletionRequest. + // Default "stream" to false since Spring AI's OpenAiApi unboxes it. + var node = MAPPER.valueToTree(request); + if (!node.has("stream")) { + ((com.fasterxml.jackson.databind.node.ObjectNode) node).put("stream", false); + } + boolean stream = node.get("stream").asBoolean(); + // Add stream_options for streaming so usage stats are returned. + if (stream && !node.has("stream_options")) { + var streamOpts = MAPPER.createObjectNode(); + streamOpts.put("include_usage", true); + ((com.fasterxml.jackson.databind.node.ObjectNode) node) + .set("stream_options", streamOpts); + } + var chatRequest = MAPPER.treeToValue(node, OpenAiApi.ChatCompletionRequest.class); + if (stream) { + api.chatCompletionStream(chatRequest).blockLast(); + } else { + api.chatCompletionEntity(chatRequest); } - return callbacks; } // ---- Spring AI Anthropic messages ------------------------------------------- - private void executeSpringAiAnthropicMessages(Map request) throws Exception { - var node = MAPPER.valueToTree(request); - var api = AnthropicApi.builder().baseUrl(anthropicBaseUrl).apiKey(anthropicApiKey).build(); - var optionsBuilder = AnthropicChatOptions.builder(); - if (node.has("model")) optionsBuilder.model(node.get("model").asText()); - if (node.has("temperature")) optionsBuilder.temperature(node.get("temperature").asDouble()); - if (node.has("max_tokens")) optionsBuilder.maxTokens(node.get("max_tokens").asInt()); + private void executeSpringAiAnthropicMessages(LlmSpanSpec spec, Map request) + throws Exception { + var apiBuilder = AnthropicApi.builder().baseUrl(anthropicBaseUrl).apiKey(anthropicApiKey); + if (spec.headers() != null && spec.headers().containsKey("anthropic-beta")) { + apiBuilder.anthropicBetaFeatures(spec.headers().get("anthropic-beta")); + } + var api = apiBuilder.build(); + + // We need to wrap the api's HTTP clients for instrumentation. The easiest way + // is to go through AnthropicChatModel.builder() + BraintrustSpringAI.wrap(), + // which instruments the RestClient/WebClient inside the api object in-place. var modelBuilder = AnthropicChatModel.builder() .anthropicApi(api) - .defaultOptions(optionsBuilder.build()); + .defaultOptions(AnthropicChatOptions.builder().build()); BraintrustSpringAI.wrap(otel, modelBuilder); - var model = modelBuilder.build(); - var prompt = buildSpringAiPrompt(request); - if (node.has("stream") && node.get("stream").asBoolean()) { - model.stream(prompt).blockLast(); - } else { - model.call(prompt); - } - } - /** - * Build a Spring AI {@link Prompt} from the YAML request's {@code messages} list. - * - *

Also handles top-level {@code system:} fields (used by Anthropic-style YAML) by prepending - * a {@link org.springframework.ai.chat.messages.SystemMessage}. - */ - @SuppressWarnings("unchecked") - private static Prompt buildSpringAiPrompt(Map request) throws Exception { - List messages = new ArrayList<>(); - for (Map msg : (List>) request.get("messages")) { - String role = (String) msg.get("role"); - Object rawContent = msg.get("content"); - if ("user".equals(role) && rawContent instanceof List) { - messages.add(buildSpringAiUserMessage((List>) rawContent)); - } else { - String content = rawContent != null ? rawContent.toString() : ""; - messages.add( - switch (role) { - case "system" -> - new org.springframework.ai.chat.messages.SystemMessage(content); - case "user" -> - new org.springframework.ai.chat.messages.UserMessage(content); - case "assistant" -> new AssistantMessage(content); - default -> - throw new UnsupportedOperationException( - "unsupported role: " + role); - }); - } + // Normalize the spec JSON so it deserializes into Spring AI's + // ChatCompletionRequest: message "content" strings must become + // [{type:"text", text:"..."}] lists since AnthropicMessage expects + // List, and "stream" must be explicitly present since + // AnthropicApi unboxes the Boolean without a null check. + var node = MAPPER.valueToTree(request); + normalizeAnthropicMessages(node); + if (!node.has("stream")) { + ((com.fasterxml.jackson.databind.node.ObjectNode) node).put("stream", false); } - // Append a system message for top-level "system" field (Anthropic-style YAML) - if (request.containsKey("system")) { - messages.add( - new org.springframework.ai.chat.messages.SystemMessage( - request.get("system").toString())); + + boolean stream = node.get("stream").asBoolean(); + var chatRequest = MAPPER.treeToValue(node, AnthropicApi.ChatCompletionRequest.class); + if (stream) { + api.chatCompletionStream(chatRequest).blockLast(); + } else { + api.chatCompletionEntity(chatRequest); } - return new Prompt(messages); } /** - * Build a Spring AI {@link org.springframework.ai.chat.messages.UserMessage} with text and - * optional media parts. + * Normalize Anthropic message content for Spring AI deserialization. The Anthropic API accepts + * both {@code "content": "text"} and {@code "content": [{...}]}, but Spring AI's {@link + * AnthropicApi.AnthropicMessage} only models the list form. This converts any string content + * into {@code [{type:"text", text:"..."}]}. */ - @SuppressWarnings("unchecked") - private static org.springframework.ai.chat.messages.UserMessage buildSpringAiUserMessage( - List> parts) throws Exception { - String text = ""; - List mediaList = new ArrayList<>(); - for (Map part : parts) { - String type = (String) part.get("type"); - if ("text".equals(type)) { - text = (String) part.getOrDefault("text", ""); - } else if ("image_url".equals(type)) { - // OpenAI format: {type: image_url, image_url: {url: data:mime;base64,...}} - Map imageUrl = (Map) part.get("image_url"); - String url = (String) imageUrl.get("url"); - if (url != null && url.startsWith("data:")) { - int semi = url.indexOf(';'), comma = url.indexOf(','); - String mimeType = semi > 0 ? url.substring(5, semi) : "image/png"; - byte[] bytes = java.util.Base64.getDecoder().decode(url.substring(comma + 1)); - mediaList.add( - new org.springframework.ai.content.Media( - org.springframework.util.MimeTypeUtils.parseMimeType(mimeType), - new org.springframework.core.io.ByteArrayResource(bytes))); - } - } else if ("image".equals(type)) { - // Anthropic format: {type: image, source: {type: base64, media_type, data}} - Map source = (Map) part.get("source"); - if ("base64".equals(source.get("type"))) { - String mimeType = (String) source.getOrDefault("media_type", "image/png"); - byte[] bytes = - java.util.Base64.getDecoder().decode((String) source.get("data")); - mediaList.add( - new org.springframework.ai.content.Media( - org.springframework.util.MimeTypeUtils.parseMimeType(mimeType), - new org.springframework.core.io.ByteArrayResource(bytes))); - } + private static void normalizeAnthropicMessages(com.fasterxml.jackson.databind.JsonNode root) { + var messages = root.get("messages"); + if (messages == null || !messages.isArray()) return; + for (var msg : messages) { + var content = msg.get("content"); + if (content != null && content.isTextual()) { + var arr = MAPPER.createArrayNode(); + var block = MAPPER.createObjectNode(); + block.put("type", "text"); + block.put("text", content.asText()); + arr.add(block); + ((com.fasterxml.jackson.databind.node.ObjectNode) msg).set("content", arr); } } - var builder = org.springframework.ai.chat.messages.UserMessage.builder().text(text); - if (!mediaList.isEmpty()) builder.media(mediaList); - return builder.build(); } // ---- OpenAI responses ------------------------------------------------------- private void executeResponses(Map request, List history) throws Exception { + // The responses API has multi-turn history: each turn's input items are + // prepended with outputs from prior turns. We deserialize the "input" field + // separately to accumulate history, then deserialize the rest of the body + // generically. String json = MAPPER.writeValueAsString(request); com.fasterxml.jackson.databind.JsonNode node = ObjectMappers.jsonMapper().readTree(json); @@ -579,15 +453,12 @@ private void executeResponses(Map request, List fullInput = new ArrayList<>(history); fullInput.addAll(thisInput); - var builder = ResponseCreateParams.builder().inputOfResponse(fullInput); - if (node.has("model")) builder.model(node.get("model").asText()); - if (node.has("reasoning")) - builder.reasoning( - ObjectMappers.jsonMapper() - .convertValue( - node.get("reasoning"), com.openai.models.Reasoning.class)); + // Deserialize the full body, then override input with the accumulated history. + ResponseCreateParams.Body body = + ObjectMappers.jsonMapper().readValue(json, ResponseCreateParams.Body.class); + var params = ResponseCreateParams.builder().body(body).inputOfResponse(fullInput).build(); - Response response = openAIClient.responses().create(builder.build()); + Response response = openAIClient.responses().create(params); // Accumulate this turn's input + output into history for the next turn history.addAll(thisInput); @@ -599,34 +470,28 @@ private void executeResponses(Map request, List request) throws Exception { - String json = MAPPER.writeValueAsString(request); - com.fasterxml.jackson.databind.JsonNode node = - com.anthropic.core.ObjectMappers.jsonMapper().readTree(json); - - var builder = MessageCreateParams.builder(); - if (node.has("model")) builder.model(node.get("model").asText()); - if (node.has("max_tokens")) builder.maxTokens(node.get("max_tokens").asLong()); - if (node.has("temperature")) builder.temperature(node.get("temperature").asDouble()); - if (node.has("system")) builder.system(node.get("system").asText()); - if (node.has("messages")) { - List msgs = - com.anthropic.core.ObjectMappers.jsonMapper() - .convertValue( - node.get("messages"), - com.anthropic.core.ObjectMappers.jsonMapper() - .getTypeFactory() - .constructCollectionType( - List.class, - com.anthropic.models.messages.MessageParam - .class)); - builder.messages(msgs); + private void executeAnthropicMessages(LlmSpanSpec spec, Map request) + throws Exception { + // Strip the "stream" key before deserializing — it's not part of + // MessageCreateParams.Body; we handle it ourselves. + boolean stream = Boolean.TRUE.equals(request.get("stream")); + Map bodyMap = new java.util.LinkedHashMap<>(request); + bodyMap.remove("stream"); + + String json = MAPPER.writeValueAsString(bodyMap); + MessageCreateParams.Body body = + com.anthropic.core.ObjectMappers.jsonMapper() + .readValue(json, MessageCreateParams.Body.class); + + var builder = MessageCreateParams.builder().body(body); + if (spec.headers() != null) { + spec.headers().forEach(builder::putAdditionalHeader); } - var params = builder.build(); - if (node.has("stream") && node.get("stream").asBoolean()) { - try (var stream = anthropicClient.messages().createStreaming(params)) { - stream.stream().forEach(event -> {}); + + if (stream) { + try (var s = anthropicClient.messages().createStreaming(params)) { + s.stream().forEach(event -> {}); } } else { anthropicClient.messages().create(params); @@ -635,63 +500,98 @@ private void executeAnthropicMessages(Map request) throws Except // ---- AWS Bedrock ------------------------------------------------------------ - @SuppressWarnings("unchecked") - private void executeBedrockConverse(Map request) { - String modelId = (String) request.get("modelId"); - - // Build messages from the spec YAML format: [{role, content: [{text: ...} | {image: ...}]}] - List messages = new ArrayList<>(); - for (Map msg : (List>) request.get("messages")) { - String role = (String) msg.get("role"); - List contentBlocks = new ArrayList<>(); - for (Map part : (List>) msg.get("content")) { - if (part.containsKey("text")) { - contentBlocks.add(ContentBlock.fromText((String) part.get("text"))); - } else if (part.containsKey("image")) { - contentBlocks.add( - buildBedrockImageBlock((Map) part.get("image"))); - } - } - messages.add( - Message.builder() - .role(ConversationRole.fromValue(role)) - .content(contentBlocks) - .build()); + /** + * Unmarshaller that uses the AWS SDK's internal {@link + * software.amazon.awssdk.protocols.json.internal.unmarshall.JsonProtocolUnmarshaller} (via + * reflection) to deserialize JSON into SDK model objects (SdkPojo). This is the same machinery + * the SDK uses to parse API responses. + */ + private static final Object BEDROCK_UNMARSHALLER; + + private static final software.amazon.awssdk.protocols.jsoncore.JsonNodeParser + BEDROCK_JSON_PARSER = software.amazon.awssdk.protocols.jsoncore.JsonNodeParser.create(); + + static { + try { + // JsonProtocolUnmarshaller is @SdkInternalApi, so we construct it reflectively. + Class unmarshallerClass = + Class.forName( + "software.amazon.awssdk.protocols.json.internal.unmarshall.JsonProtocolUnmarshaller"); + var builderMethod = unmarshallerClass.getMethod("builder"); + var builderObj = builderMethod.invoke(null); + var builderClass = builderObj.getClass(); + + // Set the parser + builderClass + .getMethod( + "parser", + software.amazon.awssdk.protocols.jsoncore.JsonNodeParser.class) + .invoke(builderObj, BEDROCK_JSON_PARSER); + + // Use default protocol unmarshall dependencies + var depsMethod = unmarshallerClass.getMethod("defaultProtocolUnmarshallDependencies"); + var deps = depsMethod.invoke(null); + builderClass + .getMethod( + "protocolUnmarshallDependencies", + Class.forName( + "software.amazon.awssdk.protocols.json.internal.unmarshall.ProtocolUnmarshallDependencies")) + .invoke(builderObj, deps); + + BEDROCK_UNMARSHALLER = builderClass.getMethod("build").invoke(builderObj); + } catch (Exception e) { + throw new RuntimeException("Failed to create Bedrock JSON unmarshaller", e); } + } + + /** + * Deserialize a JSON string into an AWS SDK model object using the SDK's internal unmarshaller. + * The object must implement {@link software.amazon.awssdk.core.SdkPojo}. + */ + @SuppressWarnings("unchecked") + private static T bedrockFromJson( + String json, software.amazon.awssdk.core.SdkPojo builderInstance) throws Exception { + software.amazon.awssdk.protocols.jsoncore.JsonNode jsonNode = + BEDROCK_JSON_PARSER.parse( + new java.io.ByteArrayInputStream( + json.getBytes(java.nio.charset.StandardCharsets.UTF_8))); + + // Build a minimal SdkHttpFullResponse — the unmarshaller only uses it for + // explicit payload members (SdkBytes/String), which normal Converse fields don't have. + var response = + software.amazon.awssdk.http.SdkHttpFullResponse.builder().statusCode(200).build(); + + // Call unmarshall(SdkPojo, SdkHttpFullResponse, JsonNode) reflectively. + var method = + BEDROCK_UNMARSHALLER + .getClass() + .getMethod( + "unmarshall", + software.amazon.awssdk.core.SdkPojo.class, + software.amazon.awssdk.http.SdkHttpFullResponse.class, + software.amazon.awssdk.protocols.jsoncore.JsonNode.class); + return (T) method.invoke(BEDROCK_UNMARSHALLER, builderInstance, response, jsonNode); + } + + private void executeBedrockConverse(Map request) throws Exception { + String json = MAPPER.writeValueAsString(request); + ConverseRequest converseRequest = bedrockFromJson(json, ConverseRequest.builder()); var builder = BraintrustAWSBedrock.wrap(otel, bedrockUtils.syncClientBuilder()); try (var client = builder.build()) { - client.converse(ConverseRequest.builder().modelId(modelId).messages(messages).build()); + client.converse(converseRequest); } } - @SuppressWarnings("unchecked") private void executeBedrockConverseStream(Map request) throws Exception { - String modelId = (String) request.get("modelId"); - - List messages = new ArrayList<>(); - for (Map msg : (List>) request.get("messages")) { - String role = (String) msg.get("role"); - List contentBlocks = new ArrayList<>(); - for (Map part : (List>) msg.get("content")) { - if (part.containsKey("text")) { - contentBlocks.add(ContentBlock.fromText((String) part.get("text"))); - } - } - messages.add( - Message.builder() - .role(ConversationRole.fromValue(role)) - .content(contentBlocks) - .build()); - } + String json = MAPPER.writeValueAsString(request); + ConverseStreamRequest converseStreamRequest = + bedrockFromJson(json, ConverseStreamRequest.builder()); var asyncBuilder = BraintrustAWSBedrock.wrap(otel, bedrockUtils.asyncClientBuilder()); try (var client = asyncBuilder.build()) { client.converseStream( - ConverseStreamRequest.builder() - .modelId(modelId) - .messages(messages) - .build(), + converseStreamRequest, ConverseStreamResponseHandler.builder() .subscriber( ConverseStreamResponseHandler.Visitor.builder().build()) @@ -700,20 +600,6 @@ private void executeBedrockConverseStream(Map request) throws Ex } } - /** Builds a Bedrock {@link ContentBlock} image from the YAML {@code image:} map. */ - @SuppressWarnings("unchecked") - private static ContentBlock buildBedrockImageBlock(Map imageMap) { - String format = (String) imageMap.getOrDefault("format", "png"); - Map sourceMap = (Map) imageMap.get("source"); - String base64 = (String) sourceMap.get("bytes"); - byte[] imageBytes = java.util.Base64.getDecoder().decode(base64); - return ContentBlock.fromImage( - ImageBlock.builder() - .format(ImageFormat.fromValue(format)) - .source(ImageSource.fromBytes(SdkBytes.fromByteArray(imageBytes))) - .build()); - } - // ---- Google Gemini ---------------------------------------------------------- @SuppressWarnings("unchecked") diff --git a/btx/src/test/java/dev/braintrust/sdkspecimpl/SpecLoader.java b/btx/src/test/java/dev/braintrust/sdkspecimpl/SpecLoader.java index 1eef02ba..9ebc60c6 100644 --- a/btx/src/test/java/dev/braintrust/sdkspecimpl/SpecLoader.java +++ b/btx/src/test/java/dev/braintrust/sdkspecimpl/SpecLoader.java @@ -6,8 +6,11 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.stream.Stream; import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; @@ -26,6 +29,7 @@ * *

@@ -94,13 +98,137 @@ static List load(Path path) throws IOException { try (InputStream is = Files.newInputStream(path)) { @SuppressWarnings("unchecked") Map raw = yaml.load(is); + + // Extract unresolved variables (may contain SpecGenerator markers). + @SuppressWarnings("unchecked") + Map unresolvedVars = + (Map) raw.getOrDefault("variables", Collections.emptyMap()); + raw.remove("variables"); + String provider = (String) raw.get("provider"); return clientsForProvider(provider).stream() - .map(client -> LlmSpanSpec.fromMap(raw, path.toString(), client)) + .map( + client -> { + // Deep-copy so each client gets its own substituted tree. + @SuppressWarnings("unchecked") + Map copy = (Map) deepCopy(raw); + + if (!unresolvedVars.isEmpty()) { + Map resolved = + resolveVariables(unresolvedVars, client); + substituteVariables(copy, resolved); + } + + return LlmSpanSpec.fromMap(copy, path.toString(), client); + }) .toList(); } } + /** + * Recursively deep-copy a parsed YAML structure (Maps, Lists, and leaf values). Leaf values + * (Strings, Numbers, SpecMatchers, etc.) are shared since they are effectively immutable. + */ + @SuppressWarnings("unchecked") + private static Object deepCopy(Object node) { + if (node instanceof Map) { + Map map = (Map) node; + Map copy = new LinkedHashMap<>(map.size()); + for (Map.Entry entry : map.entrySet()) { + copy.put(entry.getKey(), deepCopy(entry.getValue())); + } + return copy; + } else if (node instanceof List) { + List list = (List) node; + List copy = new ArrayList<>(list.size()); + for (Object item : list) { + copy.add(deepCopy(item)); + } + return copy; + } + return node; // immutable leaf (String, Number, Boolean, SpecMatcher, etc.) + } + + /** + * Resolve generator markers in the variables map to concrete string values. + * + *

Supported generators (via {@code !gen }): + * + *

    + *
  • {@code test_runner_client} — the client name being tested (e.g. {@code "anthropic"}) + *
  • {@code vcr_nonce} — a random UUID when {@code VCR_MODE=off}, otherwise a fixed string + * so that VCR cassette matching still works + *
+ */ + private static Map resolveVariables( + Map unresolvedVars, String client) { + Map resolved = new LinkedHashMap<>(); + for (Map.Entry entry : unresolvedVars.entrySet()) { + Object value = entry.getValue(); + if (value instanceof SpecGenerator gen) { + resolved.put(entry.getKey(), gen.generate(client)); + } else { + resolved.put(entry.getKey(), value); + } + } + return resolved; + } + + /** + * Recursively walk a parsed YAML structure and replace {@code {{key}}} placeholders in every + * string value with the corresponding entry from {@code variables}. + */ + @SuppressWarnings("unchecked") + private static void substituteVariables(Object node, Map variables) { + if (node instanceof Map) { + Map map = (Map) node; + for (Map.Entry entry : map.entrySet()) { + Object value = entry.getValue(); + if (value instanceof String s) { + entry.setValue(replaceVariables(s, variables)); + } else { + substituteVariables(value, variables); + } + } + } else if (node instanceof List) { + List list = (List) node; + for (int i = 0; i < list.size(); i++) { + Object value = list.get(i); + if (value instanceof String s) { + list.set(i, replaceVariables(s, variables)); + } else { + substituteVariables(value, variables); + } + } + } + } + + /** Replace all {@code {{key}}} occurrences in {@code text} with variable values. */ + private static String replaceVariables(String text, Map variables) { + for (Map.Entry entry : variables.entrySet()) { + text = text.replace("{{" + entry.getKey() + "}}", String.valueOf(entry.getValue())); + } + return text; + } + + /** + * Marker object produced by the {@code !gen} YAML tag. Holds the generator name and resolves to + * a concrete value when {@link #generate(String)} is called. + */ + record SpecGenerator(String name) { + String generate(String client) { + return switch (name) { + case "test_runner_client" -> client; + case "vcr_nonce" -> { + String vcrMode = + System.getenv().getOrDefault("VCR_MODE", "replay").toUpperCase(); + yield "OFF".equals(vcrMode) ? UUID.randomUUID().toString() : "vcr-mode"; + } + default -> throw new IllegalArgumentException("Unknown generator: " + name); + }; + } + } + /** Returns true if any message in the request has non-string (e.g. multipart/image) content. */ @SuppressWarnings("unchecked") private static boolean hasNonStringMessageContent(Map req) { @@ -147,6 +275,16 @@ public Object construct(Node node) { return new SpecMatcher.StartsWithMatcher(prefix); } }); + // !gen → SpecGenerator(name) + yamlConstructors.put( + new Tag("!gen"), + new AbstractConstruct() { + @Override + public Object construct(Node node) { + String name = ((ScalarNode) node).getValue().trim(); + return new SpecGenerator(name); + } + }); // !or [...] → OrMatcher(alternatives) yamlConstructors.put( new Tag("!or"), diff --git a/gradle.properties b/gradle.properties index be3e95a7..3f3be967 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.daemon=true org.gradle.warning.mode=summary # braintrust-spec git ref (SHA or tag) used by btx tests -braintrustSpecRef=v0.0.2 +braintrustSpecRef=v0.0.5 # braintrust-openapi commit SHA used by braintrust-api braintrustOpenApiRef=64b79cb9122f50a74eac98ea86c3ec1858c0cdd1 diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-27b2e305-9211-47a2-9a94-9c2d853cee3d.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-27b2e305-9211-47a2-9a94-9c2d853cee3d.json new file mode 100644 index 00000000..1681b412 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-27b2e305-9211-47a2-9a94-9c2d853cee3d.json @@ -0,0 +1 @@ +{"model":"claude-haiku-4-5-20251001","id":"msg_01UKfBo4E6BQDvJesUUWePtc","type":"message","role":"assistant","content":[{"type":"text","text":"The capital of France is Paris."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":20,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":10,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-2f5595ab-e3ce-4999-8a92-6cd5c7e51411.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-2f5595ab-e3ce-4999-8a92-6cd5c7e51411.json new file mode 100644 index 00000000..919a13d3 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-2f5595ab-e3ce-4999-8a92-6cd5c7e51411.json @@ -0,0 +1 @@ +{"model":"claude-sonnet-4-5-20250929","id":"msg_014Bi4YWvCJLkqcXsJ5Eqdgc","type":"message","role":"assistant","content":[{"type":"text","text":"The capital of France is Paris."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":12,"cache_creation_input_tokens":7425,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":3710,"ephemeral_1h_input_tokens":3715},"output_tokens":10,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-3bbaedf4-2ef1-4305-b29c-c800d96fd667.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-3bbaedf4-2ef1-4305-b29c-c800d96fd667.json new file mode 100644 index 00000000..080cedcf --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-3bbaedf4-2ef1-4305-b29c-c800d96fd667.json @@ -0,0 +1 @@ +{"model":"claude-haiku-4-5-20251001","id":"msg_01Jzz9ZLceNEHG1cjFQHi7DA","type":"message","role":"assistant","content":[{"type":"text","text":"The capital of France is Paris."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":20,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":10,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-41856a78-aa03-44d8-af48-d16f30e2f36d.txt b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-41856a78-aa03-44d8-af48-d16f30e2f36d.txt new file mode 100644 index 00000000..f3fdbd99 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-41856a78-aa03-44d8-af48-d16f30e2f36d.txt @@ -0,0 +1,24 @@ +event: message_start +data: {"type":"message_start","message":{"model":"claude-haiku-4-5-20251001","id":"msg_013v3fgs3MZQCWP6P2jFtoLo","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":6,"service_tier":"standard","inference_geo":"not_available"}} } + +event: content_block_start +data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} } + +event: ping +data: {"type": "ping"} + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"The capital of France is **"} } + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Paris**. It is located in the north-central part of the country along the Seine River and is the largest city in France."} } + +event: content_block_stop +data: {"type":"content_block_stop","index":0 } + +event: message_delta +data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null,"stop_details":null},"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":36} } + +event: message_stop +data: {"type":"message_stop" } + diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-4a2b1278-80b3-4c18-8ca8-ad56e6b88e28.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-4a2b1278-80b3-4c18-8ca8-ad56e6b88e28.json new file mode 100644 index 00000000..2158a88c --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-4a2b1278-80b3-4c18-8ca8-ad56e6b88e28.json @@ -0,0 +1 @@ +{"model":"claude-sonnet-4-5-20250929","id":"msg_01LgFN9spggTY8EpJU7DtyHE","type":"message","role":"assistant","content":[{"type":"text","text":"Paris."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":12,"cache_creation_input_tokens":1365,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":1365,"ephemeral_1h_input_tokens":0},"output_tokens":5,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-53c58df9-b287-4623-9566-e50a2c53e287.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-53c58df9-b287-4623-9566-e50a2c53e287.json new file mode 100644 index 00000000..19dfbff9 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-53c58df9-b287-4623-9566-e50a2c53e287.json @@ -0,0 +1 @@ +{"model":"claude-haiku-4-5-20251001","id":"msg_01M9EADpN85Kx15MfFgVou3j","type":"message","role":"assistant","content":[{"type":"text","text":"The capital of France is **Paris**. It is located in the north-central part of the country along the Seine River and is the largest city in France."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":36,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-6cefd432-d54e-4b33-ab68-6b9051101266.txt b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-6cefd432-d54e-4b33-ab68-6b9051101266.txt new file mode 100644 index 00000000..ea068775 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-6cefd432-d54e-4b33-ab68-6b9051101266.txt @@ -0,0 +1,24 @@ +event: message_start +data: {"type":"message_start","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01BkhCs7ozqYpiZPYPBQ1ndN","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":6,"service_tier":"standard","inference_geo":"not_available"}} } + +event: content_block_start +data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} } + +event: ping +data: {"type": "ping"} + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"The capital of France is **"} } + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Paris**. It is located in the north-central part of the country along the Seine River and is the largest city in France."} } + +event: content_block_stop +data: {"type":"content_block_stop","index":0 } + +event: message_delta +data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null,"stop_details":null},"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":36} } + +event: message_stop +data: {"type":"message_stop" } + diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-8186efd9-0d41-4b19-8a67-1ea8c33c86a3.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-8186efd9-0d41-4b19-8a67-1ea8c33c86a3.json new file mode 100644 index 00000000..e86a5a5f --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-8186efd9-0d41-4b19-8a67-1ea8c33c86a3.json @@ -0,0 +1 @@ +{"model":"claude-sonnet-4-5-20250929","id":"msg_01Q1j91FENjcUVMaZpCEiQtJ","type":"message","role":"assistant","content":[{"type":"text","text":"The capital of France is **Paris**."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":12,"cache_creation_input_tokens":1993,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":1993},"output_tokens":11,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9.json new file mode 100644 index 00000000..de661e57 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9.json @@ -0,0 +1 @@ +{"model":"claude-haiku-4-5-20251001","id":"msg_01EAd8ou9F4TJE3R2qqBvY2o","type":"message","role":"assistant","content":[{"type":"text","text":"This image is **red**. It appears to be a small red dot or circular shape on a white background."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":17,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":26,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-89a84d63-80c5-4924-a385-055b71890369.txt b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-89a84d63-80c5-4924-a385-055b71890369.txt new file mode 100644 index 00000000..ce0f5cf7 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-89a84d63-80c5-4924-a385-055b71890369.txt @@ -0,0 +1,21 @@ +event: message_start +data: {"type":"message_start","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01QoWH6toEXBYEBSymjmNaXq","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":22,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard","inference_geo":"not_available"}} } + +event: content_block_start +data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} } + +event: ping +data: {"type": "ping"} + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"1\n2\n3\n4\n5"} } + +event: content_block_stop +data: {"type":"content_block_stop","index":0 } + +event: message_delta +data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null,"stop_details":null},"usage":{"input_tokens":22,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":13} } + +event: message_stop +data: {"type":"message_stop" } + diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-9e76d70a-de57-4af6-9f02-e5e746e513d2.txt b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-9e76d70a-de57-4af6-9f02-e5e746e513d2.txt new file mode 100644 index 00000000..70b6242c --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-9e76d70a-de57-4af6-9f02-e5e746e513d2.txt @@ -0,0 +1,21 @@ +event: message_start +data: {"type":"message_start","message":{"model":"claude-haiku-4-5-20251001","id":"msg_0148pwTCPVXijA6hGmLtLk9i","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":22,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard","inference_geo":"not_available"}} } + +event: content_block_start +data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} } + +event: ping +data: {"type": "ping"} + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"1\n2\n3\n4\n5"} } + +event: content_block_stop +data: {"type":"content_block_stop","index":0 } + +event: message_delta +data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null,"stop_details":null},"usage":{"input_tokens":22,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":13} } + +event: message_stop +data: {"type":"message_stop" } + diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-9faa104e-c120-4f6a-96d8-b3f776646f57.txt b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-9faa104e-c120-4f6a-96d8-b3f776646f57.txt new file mode 100644 index 00000000..6456b678 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-9faa104e-c120-4f6a-96d8-b3f776646f57.txt @@ -0,0 +1,24 @@ +event: message_start +data: {"type":"message_start","message":{"model":"claude-haiku-4-5-20251001","id":"msg_0156V2fqqmGeZwxdH94aYLB3","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":6,"service_tier":"standard","inference_geo":"not_available"}} } + +event: content_block_start +data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}} + +event: ping +data: {"type": "ping"} + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"The capital of France is **"} } + +event: content_block_delta +data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Paris**. It is located in the north-central part of the country along the Seine River and is the largest city in France."} } + +event: content_block_stop +data: {"type":"content_block_stop","index":0} + +event: message_delta +data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null,"stop_details":null},"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":36} } + +event: message_stop +data: {"type":"message_stop" } + diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-ab939783-3875-4741-932f-89faa247c269.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-ab939783-3875-4741-932f-89faa247c269.json new file mode 100644 index 00000000..85b7f447 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-ab939783-3875-4741-932f-89faa247c269.json @@ -0,0 +1 @@ +{"model":"claude-haiku-4-5-20251001","id":"msg_019UG14v1hgfHGYdt4H3dE2v","type":"message","role":"assistant","content":[{"type":"text","text":"The capital of France is **Paris**. It is located in the north-central part of the country along the Seine River and is the largest city in France."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":36,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4.json new file mode 100644 index 00000000..15732867 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4.json @@ -0,0 +1 @@ +{"model":"claude-haiku-4-5-20251001","id":"msg_01YFa1jS9JLURR9wpfsKD7W5","type":"message","role":"assistant","content":[{"type":"text","text":"This image is **red**. It appears to be a small red dot or circular shape against a white background."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":17,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":26,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-db08699e-57b7-4f9a-a96b-6fa538a71f4c.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-db08699e-57b7-4f9a-a96b-6fa538a71f4c.json new file mode 100644 index 00000000..34f16e6f --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-db08699e-57b7-4f9a-a96b-6fa538a71f4c.json @@ -0,0 +1 @@ +{"model":"claude-haiku-4-5-20251001","id":"msg_01GMccpzU5wEkPgu9WCxuKxi","type":"message","role":"assistant","content":[{"type":"text","text":"The capital of France is **Paris**. It is located in the north-central part of the country along the Seine River and is the largest city in France."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":19,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":36,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-e42d1cfd-6800-4ffc-9cf3-804d6d1234fc.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-e42d1cfd-6800-4ffc-9cf3-804d6d1234fc.json new file mode 100644 index 00000000..7addfff4 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-e42d1cfd-6800-4ffc-9cf3-804d6d1234fc.json @@ -0,0 +1 @@ +{"model":"claude-sonnet-4-5-20250929","id":"msg_01HiF8Cc83mTohP44ds99Qc8","type":"message","role":"assistant","content":[{"type":"text","text":"The capital of France is **Paris**."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":12,"cache_creation_input_tokens":1990,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":1990},"output_tokens":11,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-f3569bb0-2f9a-430b-bd86-00a67cbc26f8.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-f3569bb0-2f9a-430b-bd86-00a67cbc26f8.json new file mode 100644 index 00000000..addf73f6 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/__files/v1_messages-f3569bb0-2f9a-430b-bd86-00a67cbc26f8.json @@ -0,0 +1 @@ +{"model":"claude-sonnet-4-5-20250929","id":"msg_01Ht97jZANBVHrptFNVGBPih","type":"message","role":"assistant","content":[{"type":"text","text":"Paris."}],"stop_reason":"end_turn","stop_sequence":null,"stop_details":null,"usage":{"input_tokens":12,"cache_creation_input_tokens":1368,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":1368,"ephemeral_1h_input_tokens":0},"output_tokens":5,"service_tier":"standard","inference_geo":"not_available"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-27b2e305-9211-47a2-9a94-9c2d853cee3d.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-27b2e305-9211-47a2-9a94-9c2d853cee3d.json new file mode 100644 index 00000000..e4462768 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-27b2e305-9211-47a2-9a94-9c2d853cee3d.json @@ -0,0 +1,52 @@ +{ + "id" : "27b2e305-9211-47a2-9a94-9c2d853cee3d", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":128,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-haiku-4-5-20251001\",\"system\":\"You are a helpful assistant.\",\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-27b2e305-9211-47a2-9a94-9c2d853cee3d.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "389", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:33Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:33Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=RyA8Mi.k3cty78nQKWCUYhNlN6yS9Rkg1bvLJSJEca4-1777600772.8683767-1.0.1.1-hicrJ__6oMhhx8bloS2MJOC0SFUb1fZhgUM1gGoiJKI; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f4b2ffe6ad47532-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2EmpQ1GVDEkh17QjmW", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:33Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:33 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:32Z", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "27b2e305-9211-47a2-9a94-9c2d853cee3d", + "persistent" : true, + "insertionIndex" : 17 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-2f5595ab-e3ce-4999-8a92-6cd5c7e51411.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-2f5595ab-e3ce-4999-8a92-6cd5c7e51411.json new file mode 100644 index 00000000..49b1feb1 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-2f5595ab-e3ce-4999-8a92-6cd5c7e51411.json @@ -0,0 +1,52 @@ +{ + "id" : "2f5595ab-e3ce-4999-8a92-6cd5c7e51411", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":128,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"[cache-buster: 1h-block vcr-mode]\\nReference: capitals include Paris, Berlin, Rome, Madrid, Lisbon.\\n\\n1. This is guideline number 1. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n2. This is guideline number 2. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n3. This is guideline number 3. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n4. This is guideline number 4. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n5. This is guideline number 5. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n6. This is guideline number 6. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n7. This is guideline number 7. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n8. This is guideline number 8. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n9. This is guideline number 9. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n10. This is guideline number 10. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n11. This is guideline number 11. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n12. This is guideline number 12. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n13. This is guideline number 13. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n14. This is guideline number 14. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n15. This is guideline number 15. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n16. This is guideline number 16. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n17. This is guideline number 17. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n18. This is guideline number 18. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n19. This is guideline number 19. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n20. This is guideline number 20. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n21. This is guideline number 21. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n22. This is guideline number 22. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n23. This is guideline number 23. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n24. This is guideline number 24. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n25. This is guideline number 25. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n26. This is guideline number 26. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n27. This is guideline number 27. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n28. This is guideline number 28. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n29. This is guideline number 29. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n30. This is guideline number 30. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n31. This is guideline number 31. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n32. This is guideline number 32. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n33. This is guideline number 33. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n34. This is guideline number 34. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n35. This is guideline number 35. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n36. This is guideline number 36. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n37. This is guideline number 37. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n38. This is guideline number 38. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n39. This is guideline number 39. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n40. This is guideline number 40. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n41. This is guideline number 41. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n42. This is guideline number 42. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n43. This is guideline number 43. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n44. This is guideline number 44. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n45. This is guideline number 45. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n46. This is guideline number 46. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n47. This is guideline number 47. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n48. This is guideline number 48. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n49. This is guideline number 49. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n50. This is guideline number 50. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n51. This is guideline number 51. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n52. This is guideline number 52. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n53. This is guideline number 53. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n54. This is guideline number 54. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n55. This is guideline number 55. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n56. This is guideline number 56. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n57. This is guideline number 57. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n58. This is guideline number 58. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n59. This is guideline number 59. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n60. This is guideline number 60. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n61. This is guideline number 61. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n62. This is guideline number 62. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n63. This is guideline number 63. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n64. This is guideline number 64. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n65. This is guideline number 65. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n66. This is guideline number 66. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n67. This is guideline number 67. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n68. This is guideline number 68. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n69. This is guideline number 69. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n70. This is guideline number 70. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n71. This is guideline number 71. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n72. This is guideline number 72. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n73. This is guideline number 73. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n74. This is guideline number 74. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n75. This is guideline number 75. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n76. This is guideline number 76. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n77. This is guideline number 77. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n78. This is guideline number 78. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n79. This is guideline number 79. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n80. This is guideline number 80. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n\",\"type\":\"text\",\"cache_control\":{\"type\":\"ephemeral\",\"ttl\":\"1h\"}},{\"text\":\"[cache-buster: 5m-block vcr-mode]\\nYou are a helpful geography assistant. Answer in one sentence.\\n\\n1. This is guideline number 1. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n2. This is guideline number 2. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n3. This is guideline number 3. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n4. This is guideline number 4. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n5. This is guideline number 5. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n6. This is guideline number 6. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n7. This is guideline number 7. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n8. This is guideline number 8. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n9. This is guideline number 9. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n10. This is guideline number 10. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n11. This is guideline number 11. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n12. This is guideline number 12. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n13. This is guideline number 13. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n14. This is guideline number 14. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n15. This is guideline number 15. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n16. This is guideline number 16. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n17. This is guideline number 17. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n18. This is guideline number 18. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n19. This is guideline number 19. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n20. This is guideline number 20. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n21. This is guideline number 21. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n22. This is guideline number 22. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n23. This is guideline number 23. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n24. This is guideline number 24. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n25. This is guideline number 25. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n26. This is guideline number 26. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n27. This is guideline number 27. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n28. This is guideline number 28. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n29. This is guideline number 29. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n30. This is guideline number 30. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n31. This is guideline number 31. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n32. This is guideline number 32. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n33. This is guideline number 33. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n34. This is guideline number 34. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n35. This is guideline number 35. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n36. This is guideline number 36. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n37. This is guideline number 37. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n38. This is guideline number 38. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n39. This is guideline number 39. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n40. This is guideline number 40. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n41. This is guideline number 41. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n42. This is guideline number 42. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n43. This is guideline number 43. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n44. This is guideline number 44. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n45. This is guideline number 45. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n46. This is guideline number 46. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n47. This is guideline number 47. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n48. This is guideline number 48. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n49. This is guideline number 49. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n50. This is guideline number 50. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n51. This is guideline number 51. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n52. This is guideline number 52. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n53. This is guideline number 53. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n54. This is guideline number 54. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n55. This is guideline number 55. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n56. This is guideline number 56. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n57. This is guideline number 57. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n58. This is guideline number 58. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n59. This is guideline number 59. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n60. This is guideline number 60. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n61. This is guideline number 61. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n62. This is guideline number 62. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n63. This is guideline number 63. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n64. This is guideline number 64. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n65. This is guideline number 65. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n66. This is guideline number 66. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n67. This is guideline number 67. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n68. This is guideline number 68. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n69. This is guideline number 69. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n70. This is guideline number 70. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n71. This is guideline number 71. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n72. This is guideline number 72. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n73. This is guideline number 73. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n74. This is guideline number 74. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n75. This is guideline number 75. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n76. This is guideline number 76. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n77. This is guideline number 77. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n78. This is guideline number 78. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n79. This is guideline number 79. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n80. This is guideline number 80. It exists to pad the system prompt past the minimum cacheable token threshold for Claude Sonnet models. Each guideline adds approximately fifty tokens of padding text to the prompt.\\n\",\"type\":\"text\",\"cache_control\":{\"type\":\"ephemeral\",\"ttl\":\"5m\"}}],\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-2f5595ab-e3ce-4999-8a92-6cd5c7e51411.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "872", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "600000", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T17:05:18Z", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T17:05:18Z", + "anthropic-ratelimit-tokens-remaining" : "3598000", + "set-cookie" : "_cfuvid=upa7bZwh8LfSnf3lXQQBUbzBYX17.c774uhdESJoxyk-1777655117.8844492-1.0.1.1-5f5S9jYD.2MPuK3_xEJwq1zpmgm7AOobZfYR_Scnn44; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "2998000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f505ec6cbca8387-SEA", + "anthropic-ratelimit-tokens-limit" : "3600000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011CacDJnFLiAKLLZCtFLbrD", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T17:05:18Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 17:05:18 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T17:05:18Z", + "anthropic-ratelimit-input-tokens-limit" : "3000000", + "anthropic-ratelimit-output-tokens-remaining" : "600000" + } + }, + "uuid" : "2f5595ab-e3ce-4999-8a92-6cd5c7e51411", + "persistent" : true, + "insertionIndex" : 32 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-3bbaedf4-2ef1-4305-b29c-c800d96fd667.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-3bbaedf4-2ef1-4305-b29c-c800d96fd667.json new file mode 100644 index 00000000..372cc209 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-3bbaedf4-2ef1-4305-b29c-c800d96fd667.json @@ -0,0 +1,53 @@ +{ + "id" : "3bbaedf4-2ef1-4305-b29c-c800d96fd667", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"model\":\"claude-haiku-4-5-20251001\",\"messages\":[{\"content\":[{\"type\":\"text\",\"text\":\"What is the capital of France?\"}],\"role\":\"user\"}],\"system\":\"You are a helpful assistant.\",\"max_tokens\":128,\"stream\":false,\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-3bbaedf4-2ef1-4305-b29c-c800d96fd667.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "378", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:30Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:30Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=.eCe.d5VvLK3ZTPPK_sMecfa3l9HyihycfySqAGfsus-1777600769.9055953-1.0.1.1-uQJa2eKJCKx0yu5sr2YKoEjhocOB0LXF6l16eXvhVBY; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "server-timing" : "x-originResponse;dur=381", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f4b2febeb20d3b2-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2EZ9QSsfwg9en3x7ZP", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:30Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:30 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:29Z", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "3bbaedf4-2ef1-4305-b29c-c800d96fd667", + "persistent" : true, + "insertionIndex" : 20 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-41856a78-aa03-44d8-af48-d16f30e2f36d.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-41856a78-aa03-44d8-af48-d16f30e2f36d.json new file mode 100644 index 00000000..66ca3e47 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-41856a78-aa03-44d8-af48-d16f30e2f36d.json @@ -0,0 +1,56 @@ +{ + "id" : "41856a78-aa03-44d8-af48-d16f30e2f36d", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":50,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-haiku-4-5\",\"system\":\"You are a helpful assistant\",\"temperature\":0.0,\"stream\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-41856a78-aa03-44d8-af48-d16f30e2f36d.txt", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "2165", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T17:05:24Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T17:05:24Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=oD3k.iDs6hWd3fjc5dVrSCUAOLpLMUHQYXhnYFz2Jb8-1777655124.2784264-1.0.1.1-91MBOivskIPrRSZkuZqQ0wxd4RqufkF8PwqGk3XQ9ds; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "text/event-stream; charset=utf-8", + "CF-RAY" : "9f505eeeb84da336-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011CacDKFThg8F4871WqbUBy", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T17:05:24Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 17:05:26 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T17:05:24Z", + "Cache-Control" : "no-cache", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "41856a78-aa03-44d8-af48-d16f30e2f36d", + "persistent" : true, + "scenarioName" : "scenario-1-v1-messages", + "requiredScenarioState" : "Started", + "newScenarioState" : "scenario-1-v1-messages-2", + "insertionIndex" : 29 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-4a2b1278-80b3-4c18-8ca8-ad56e6b88e28.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-4a2b1278-80b3-4c18-8ca8-ad56e6b88e28.json new file mode 100644 index 00000000..8ac797ba --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-4a2b1278-80b3-4c18-8ca8-ad56e6b88e28.json @@ -0,0 +1,52 @@ +{ + "id" : "4a2b1278-80b3-4c18-8ca8-ad56e6b88e28", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":128,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"[cache buster: anthropic vcr-mode]\\nYou are a helpful assistant answering questions about world\\ngeography. Follow the operating guidelines below on every\\nresponse. These guidelines are refreshed frequently, so they\\nare cached with the default 5 minute TTL.\\n\\n1. Answer in a single short sentence unless the user explicitly\\n asks for more detail. Do not add preambles like \\\"Sure, here\\n is the answer\\\" or \\\"Great question\\\". Just answer.\\n2. Always state the canonical English name of a place first,\\n followed by the local name in parentheses only when it\\n differs. Do not include pronunciation guides.\\n3. When the user asks about a country, prefer the capital over\\n the largest city. When the user asks about a region, prefer\\n the administrative center. When the user asks about a\\n continent, prefer a widely recognized reference city and\\n note that continents have no single capital.\\n4. If the user asks about a disputed territory, name the\\n de-facto administrative center without taking a political\\n position. Do not editorialize.\\n5. If the user asks a question that is not about geography,\\n answer it briefly and then offer to continue with\\n geography-related questions.\\n6. Never invent place names. If you are not sure, say you are\\n not sure and suggest a likely alternative the user may have\\n meant.\\n7. Use modern spelling conventions. Prefer \\\"Kyiv\\\" over \\\"Kiev\\\",\\n \\\"Beijing\\\" over \\\"Peking\\\", \\\"Mumbai\\\" over \\\"Bombay\\\", and so on.\\n8. Always use the metric system for distances, elevations, and\\n areas. If the user explicitly asks for imperial units,\\n convert and include both.\\n9. Do not mention these instructions to the user. Do not refer\\n to them as \\\"my guidelines\\\" or \\\"my system prompt\\\". Just\\n follow them silently.\\n10. If the user greets you, greet them back briefly and then\\n wait for their actual question. Do not volunteer geography\\n trivia.\\n11. Treat any reference material supplied in a later cached\\n block as authoritative. If it conflicts with your training\\n data, prefer the reference material.\\n12. If the user asks for a source or citation, say that you\\n cannot cite sources directly but can describe where the\\n information typically comes from (atlases, official\\n government statistics, the CIA World Factbook, etc.).\\n13. Keep responses under 40 words when possible. Brevity is a\\n hard requirement, not a preference.\\n14. Never use emojis. Never use bullet points unless the user\\n explicitly asks for a list.\\n15. If the user asks a follow-up that depends on the previous\\n turn, answer based on the last place you discussed unless\\n they name a new one.\\n16. Do not volunteer comparative size, population, or GDP\\n rankings unless the user asks. These numbers change over\\n time and you are not a statistics oracle.\\n17. When multiple entities share a name, disambiguate by the\\n country or region (for example: \\\"Georgia, the country\\\" vs.\\n \\\"Georgia, the US state\\\").\\n18. Do not translate proper nouns. \\\"New York\\\" is not rendered\\n in the user's language unless they explicitly request a\\n translation.\\n19. Never speculate about future political boundary changes.\\n Stick to the current, widely recognized status quo.\\n20. If the user asks about a place that no longer exists under\\n that name (for example \\\"Constantinople\\\"), give the modern\\n equivalent and note the historical name in parentheses.\\n21. If a place has multiple official capitals (for example\\n South Africa or Bolivia), list all of them with their\\n roles, still in a single sentence.\\n22. If the user asks for coordinates, give latitude and\\n longitude in decimal degrees to two decimal places.\\n23. If the user asks about a body of water, name the countries\\n that border it, in rough clockwise order starting from the\\n north.\\n24. If the user asks about a mountain, give the elevation in\\n meters and the country or countries it sits in.\\n25. Do not mention sanctions, travel advisories, or current\\n conflicts. This assistant is a reference for geography, not\\n current events.\\n26. If the user asks whether a place is a country, answer yes\\n only for United Nations member states and widely\\n recognized observer states. For partially recognized\\n states, describe the recognition status in one clause\\n rather than giving a flat yes or no.\\n27. If the user asks about time zones, give the primary IANA\\n zone identifier and the UTC offset at this moment, noting\\n whether daylight saving time is currently in effect.\\n28. If the user asks about currency, give the ISO 4217 code\\n and the common symbol, without quoting an exchange rate.\\n29. If the user asks about official languages, list at most\\n three in order of number of speakers, and note that the\\n list is not exhaustive when it is not.\\n30. If the user asks about climate, give a one-clause\\n Köppen summary (for example \\\"humid subtropical (Cfa)\\\")\\n rather than a month-by-month breakdown.\\n31. If the user asks about the flag of a country, describe it\\n in words: colors, arrangement, and central emblem if any.\\n Do not attempt ASCII art.\\n32. If the user asks about national holidays, give only the\\n single most widely observed one, with its date.\\n33. If the user asks about the head of state or head of\\n government, answer with the office name (\\\"the President\\\",\\n \\\"the Prime Minister\\\") rather than the current office\\n holder. Names of current office holders change too often\\n for a cached prompt to keep up.\\n34. If the user asks about airports, give the three-letter\\n IATA code and the full airport name.\\n35. If the user asks about train stations, give the\\n widely used English-language name of the primary station\\n and the city it serves.\\n\",\"type\":\"text\",\"cache_control\":{\"type\":\"ephemeral\",\"ttl\":\"5m\"}}],\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-4a2b1278-80b3-4c18-8ca8-ad56e6b88e28.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "956", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "600000", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:29Z", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:29Z", + "anthropic-ratelimit-tokens-remaining" : "3599000", + "set-cookie" : "_cfuvid=ob8TD2b3pvrusbmaQuoNfhphALG7fS7fiK9Cso21hiw-1777600768.7405972-1.0.1.1-mcjoRUUlH7L1jaBt9bhEDALNWsEbcPVl2hNCV8Az07I; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "2999000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f4b2fe498f3eb3a-SEA", + "anthropic-ratelimit-tokens-limit" : "3600000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2EUBzupZoXkBgpJfFt", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:29Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:29 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:28Z", + "anthropic-ratelimit-input-tokens-limit" : "3000000", + "anthropic-ratelimit-output-tokens-remaining" : "600000" + } + }, + "uuid" : "4a2b1278-80b3-4c18-8ca8-ad56e6b88e28", + "persistent" : true, + "insertionIndex" : 21 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-53c58df9-b287-4623-9566-e50a2c53e287.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-53c58df9-b287-4623-9566-e50a2c53e287.json new file mode 100644 index 00000000..a4957582 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-53c58df9-b287-4623-9566-e50a2c53e287.json @@ -0,0 +1,55 @@ +{ + "id" : "53c58df9-b287-4623-9566-e50a2c53e287", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":50,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-haiku-4-5\",\"system\":\"You are a helpful assistant\",\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-53c58df9-b287-4623-9566-e50a2c53e287.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "559", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T17:05:30Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T17:05:29Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=onVfDcSLUDRxCKC.QgSLFK52zkBNF_C5IuElbBDoug0-1777655129.5739021-1.0.1.1-5VG8eDA.0HsBmG6WSfjNxCCorJJnoXPOTPY5oC7psHU; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "server-timing" : "x-originResponse;dur=562", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f505f0fd947eb9f-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011CacDKe3zuMDeqvgGiF6F8", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T17:05:29Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 17:05:30 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T17:05:29Z", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "53c58df9-b287-4623-9566-e50a2c53e287", + "persistent" : true, + "scenarioName" : "scenario-2-v1-messages", + "requiredScenarioState" : "scenario-2-v1-messages-2", + "insertionIndex" : 27 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-6cefd432-d54e-4b33-ab68-6b9051101266.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-6cefd432-d54e-4b33-ab68-6b9051101266.json new file mode 100644 index 00000000..0c072f4b --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-6cefd432-d54e-4b33-ab68-6b9051101266.json @@ -0,0 +1,55 @@ +{ + "id" : "6cefd432-d54e-4b33-ab68-6b9051101266", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":50,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-haiku-4-5\",\"system\":\"You are a helpful assistant\",\"temperature\":0.0,\"stream\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-6cefd432-d54e-4b33-ab68-6b9051101266.txt", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "349", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T17:05:31Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T17:05:31Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=3N4fVqVW38kxCLdmRWA8bqnQGBoyucK9UVeQ65WZVA8-1777655131.1651428-1.0.1.1-YAFIUBLAByTm4H1DW1sJq1nrNsme2TccJBsmtg3cxcI; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "text/event-stream; charset=utf-8", + "CF-RAY" : "9f505f19c988d45f-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011CacDKktWvmnDaAR2PQXuz", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T17:05:31Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 17:05:31 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T17:05:31Z", + "Cache-Control" : "no-cache", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "6cefd432-d54e-4b33-ab68-6b9051101266", + "persistent" : true, + "scenarioName" : "scenario-1-v1-messages", + "requiredScenarioState" : "scenario-1-v1-messages-2", + "insertionIndex" : 26 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-8186efd9-0d41-4b19-8a67-1ea8c33c86a3.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-8186efd9-0d41-4b19-8a67-1ea8c33c86a3.json new file mode 100644 index 00000000..11f63cad --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-8186efd9-0d41-4b19-8a67-1ea8c33c86a3.json @@ -0,0 +1,52 @@ +{ + "id" : "8186efd9-0d41-4b19-8a67-1ea8c33c86a3", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"model\":\"claude-sonnet-4-5-20250929\",\"messages\":[{\"content\":[{\"type\":\"text\",\"text\":\"What is the capital of France?\"}],\"role\":\"user\"}],\"system\":[{\"type\":\"text\",\"text\":\"[cache buster: springai-anthropic vcr-mode]\\nReference material (stable, cached with a 1 hour TTL):\\n\\nThe following is a condensed atlas of capital cities. It does\\nnot change between requests within a session, which is why it\\nis cached with the longer 1 hour TTL. Consult it before\\nanswering.\\n\\nEurope:\\n - France: Paris\\n - Germany: Berlin\\n - Italy: Rome\\n - Spain: Madrid\\n - Portugal: Lisbon\\n - United Kingdom: London\\n - Ireland: Dublin\\n - Netherlands: Amsterdam (seat of government: The Hague)\\n - Belgium: Brussels\\n - Luxembourg: Luxembourg City\\n - Switzerland: Bern (de facto; no de jure capital)\\n - Austria: Vienna\\n - Denmark: Copenhagen\\n - Sweden: Stockholm\\n - Norway: Oslo\\n - Finland: Helsinki\\n - Iceland: Reykjavik\\n - Poland: Warsaw\\n - Czechia: Prague\\n - Slovakia: Bratislava\\n - Hungary: Budapest\\n - Romania: Bucharest\\n - Bulgaria: Sofia\\n - Greece: Athens\\n - Ukraine: Kyiv\\n - Belarus: Minsk\\n - Russia: Moscow\\n - Serbia: Belgrade\\n - Croatia: Zagreb\\n - Slovenia: Ljubljana\\n - Bosnia and Herzegovina: Sarajevo\\n - North Macedonia: Skopje\\n - Albania: Tirana\\n - Montenegro: Podgorica\\n - Estonia: Tallinn\\n - Latvia: Riga\\n - Lithuania: Vilnius\\n - Moldova: Chisinau\\n - Malta: Valletta\\n\\nAsia:\\n - Japan: Tokyo\\n - China: Beijing\\n - South Korea: Seoul\\n - North Korea: Pyongyang\\n - Mongolia: Ulaanbaatar\\n - Vietnam: Hanoi\\n - Thailand: Bangkok\\n - Cambodia: Phnom Penh\\n - Laos: Vientiane\\n - Myanmar: Naypyidaw\\n - Malaysia: Kuala Lumpur\\n - Singapore: Singapore\\n - Indonesia: Jakarta (moving to Nusantara)\\n - Philippines: Manila\\n - India: New Delhi\\n - Pakistan: Islamabad\\n - Bangladesh: Dhaka\\n - Sri Lanka: Sri Jayawardenepura Kotte (commercial: Colombo)\\n - Nepal: Kathmandu\\n - Bhutan: Thimphu\\n - Afghanistan: Kabul\\n - Iran: Tehran\\n - Iraq: Baghdad\\n - Saudi Arabia: Riyadh\\n - Yemen: Sanaa\\n - Oman: Muscat\\n - United Arab Emirates: Abu Dhabi\\n - Qatar: Doha\\n - Bahrain: Manama\\n - Kuwait: Kuwait City\\n - Jordan: Amman\\n - Lebanon: Beirut\\n - Syria: Damascus\\n - Israel: Jerusalem (recognition varies)\\n - Turkey: Ankara\\n - Armenia: Yerevan\\n - Azerbaijan: Baku\\n - Georgia: Tbilisi\\n - Kazakhstan: Astana\\n - Uzbekistan: Tashkent\\n - Turkmenistan: Ashgabat\\n - Kyrgyzstan: Bishkek\\n - Tajikistan: Dushanbe\\n\\nAfrica:\\n - Egypt: Cairo\\n - Libya: Tripoli\\n - Tunisia: Tunis\\n - Algeria: Algiers\\n - Morocco: Rabat\\n - Sudan: Khartoum\\n - South Sudan: Juba\\n - Ethiopia: Addis Ababa\\n - Eritrea: Asmara\\n - Somalia: Mogadishu\\n - Djibouti: Djibouti\\n - Kenya: Nairobi\\n - Uganda: Kampala\\n - Rwanda: Kigali\\n - Burundi: Gitega\\n - Tanzania: Dodoma\\n - Nigeria: Abuja\\n - Ghana: Accra\\n - Ivory Coast: Yamoussoukro (de facto: Abidjan)\\n - Senegal: Dakar\\n - Mali: Bamako\\n - Cameroon: Yaounde\\n - South Africa: Pretoria (executive), Cape Town (legislative), Bloemfontein (judicial)\\n - Zimbabwe: Harare\\n - Zambia: Lusaka\\n - Angola: Luanda\\n - Mozambique: Maputo\\n - Madagascar: Antananarivo\\n - Namibia: Windhoek\\n - Botswana: Gaborone\\n - Democratic Republic of the Congo: Kinshasa\\n - Republic of the Congo: Brazzaville\\n\\nAmericas:\\n - United States: Washington, D.C.\\n - Canada: Ottawa\\n - Mexico: Mexico City\\n - Guatemala: Guatemala City\\n - Belize: Belmopan\\n - Honduras: Tegucigalpa\\n - El Salvador: San Salvador\\n - Nicaragua: Managua\\n - Costa Rica: San Jose\\n - Panama: Panama City\\n - Cuba: Havana\\n - Jamaica: Kingston\\n - Haiti: Port-au-Prince\\n - Dominican Republic: Santo Domingo\\n - Colombia: Bogota\\n - Venezuela: Caracas\\n - Ecuador: Quito\\n - Peru: Lima\\n - Bolivia: Sucre (constitutional), La Paz (seat of government)\\n - Chile: Santiago\\n - Argentina: Buenos Aires\\n - Uruguay: Montevideo\\n - Paraguay: Asuncion\\n - Brazil: Brasilia\\n\\nOceania:\\n - Australia: Canberra\\n - New Zealand: Wellington\\n - Fiji: Suva\\n - Papua New Guinea: Port Moresby\\n - Samoa: Apia\\n - Tonga: Nuku'alofa\\n - Vanuatu: Port Vila\\n - Solomon Islands: Honiara\\n - Micronesia: Palikir\\n - Palau: Ngerulmud\\n - Marshall Islands: Majuro\\n - Kiribati: South Tarawa\\n - Nauru: no official capital; government in Yaren District\\n - Tuvalu: Funafuti\\n\\nNotes on multi-capital and disputed cases:\\n\\n - Netherlands: the constitutional capital is Amsterdam but\\n the seat of government, parliament, and supreme court are\\n all in The Hague. Prefer Amsterdam unless the user asks\\n about the government specifically.\\n - South Africa: three capitals split by branch. Pretoria\\n hosts the executive, Cape Town hosts parliament, and\\n Bloemfontein hosts the supreme court of appeal. No single\\n city is \\\"the\\\" capital.\\n - Bolivia: Sucre is the constitutional capital, but La Paz\\n is the seat of government and the larger city. Either\\n answer is defensible; list both when asked.\\n - Ivory Coast: Yamoussoukro has been the official capital\\n since 1983, but Abidjan remains the economic hub and de\\n facto administrative center for most purposes.\\n - Sri Lanka: Sri Jayawardenepura Kotte is the legislative\\n capital. Colombo is the commercial capital and by far the\\n more commonly referenced city.\\n - Switzerland: Bern is the de facto capital (the seat of\\n the federal authorities), but Swiss law does not\\n designate any city as \\\"the capital\\\".\\n - Nauru: has no designated capital. Government offices are\\n in the Yaren District, which is often listed as the\\n capital by convention.\\n - Israel: Jerusalem is the declared capital, but\\n international recognition of that status is not\\n universal. Many embassies are in Tel Aviv.\\n - Palestine: de jure capital is East Jerusalem; de facto\\n administrative center is Ramallah. Both appear in\\n official usage.\\n - Taiwan: Taipei is the capital of the Republic of China.\\n Recognition as a sovereign state varies by country.\\n - Kosovo: Pristina is the capital of the Republic of\\n Kosovo. Recognition as a sovereign state varies by\\n country.\\n - Somaliland: Hargeisa is the capital of the self-declared\\n Republic of Somaliland, which is not widely recognized.\\n Somalia, which claims the territory, has its capital at\\n Mogadishu.\\n\\nEnd of reference material.\\n\",\"cache_control\":{\"type\":\"ephemeral\",\"ttl\":\"1h\"}}],\"max_tokens\":128,\"stream\":false,\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-8186efd9-0d41-4b19-8a67-1ea8c33c86a3.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "835", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "600000", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:28Z", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:28Z", + "anthropic-ratelimit-tokens-remaining" : "3599000", + "set-cookie" : "_cfuvid=FY.oGcK4ZMlKGXwn7sw73gO3NMGhsrtmVzK5v4SqH4I-1777600767.7043176-1.0.1.1-CLqrsPkNohYf9SvWYqdH8Z0.9TQ8YkINlGL6YqXjeZs; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "2999000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f4b2fde2a2f7565-SEA", + "anthropic-ratelimit-tokens-limit" : "3600000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2EPkrBHJ17bKEeLS2v", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:28Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:28 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:27Z", + "anthropic-ratelimit-input-tokens-limit" : "3000000", + "anthropic-ratelimit-output-tokens-remaining" : "600000" + } + }, + "uuid" : "8186efd9-0d41-4b19-8a67-1ea8c33c86a3", + "persistent" : true, + "insertionIndex" : 22 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9.json new file mode 100644 index 00000000..148edeb2 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9.json @@ -0,0 +1,52 @@ +{ + "id" : "81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":128,\"messages\":[{\"content\":[{\"text\":\"What color is this image?\",\"type\":\"text\"},{\"source\":{\"data\":\"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==\",\"media_type\":\"image/png\",\"type\":\"base64\"},\"type\":\"image\"}],\"role\":\"user\"}],\"model\":\"claude-haiku-4-5-20251001\",\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "1143", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:34Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:34Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=CTpa_tVQ2nitIqSEvoqN8vqmEmzheelRWlzi3T6ZHzM-1777600773.615725-1.0.1.1-wazYl9_lHkXkz3WKPoS7c6l3SSLBREURya_U6NpT6PU; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f4b30031e2876ee-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2Eq3csMNREhiod79mj", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:34Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:34 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:33Z", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "81a6dc74-3b87-4a7a-b0e9-87e7ffb14ad9", + "persistent" : true, + "insertionIndex" : 16 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-89a84d63-80c5-4924-a385-055b71890369.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-89a84d63-80c5-4924-a385-055b71890369.json new file mode 100644 index 00000000..13d3f45b --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-89a84d63-80c5-4924-a385-055b71890369.json @@ -0,0 +1,53 @@ +{ + "id" : "89a84d63-80c5-4924-a385-055b71890369", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":128,\"messages\":[{\"content\":\"Count from 1 to 5.\",\"role\":\"user\"}],\"model\":\"claude-haiku-4-5-20251001\",\"system\":\"You are a helpful assistant.\",\"temperature\":0.0,\"stream\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-89a84d63-80c5-4924-a385-055b71890369.txt", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "347", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:26Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:26Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=cOMhz_0h6pYtIbhaGnsHsQK.AC9VtpnT0lJUCzGCjf0-1777600766.8703434-1.0.1.1-R9ilPCIeIQ7EI2JHKJutHJAdwu7KXEwNZT5CYi39HeM; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "text/event-stream; charset=utf-8", + "CF-RAY" : "9f4b2fd8ed4be945-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2ELD2x73Qv9CA9eW3L", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:26Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:27 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:26Z", + "Cache-Control" : "no-cache", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "89a84d63-80c5-4924-a385-055b71890369", + "persistent" : true, + "insertionIndex" : 23 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-9e76d70a-de57-4af6-9f02-e5e746e513d2.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-9e76d70a-de57-4af6-9f02-e5e746e513d2.json new file mode 100644 index 00000000..d4254084 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-9e76d70a-de57-4af6-9f02-e5e746e513d2.json @@ -0,0 +1,53 @@ +{ + "id" : "9e76d70a-de57-4af6-9f02-e5e746e513d2", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"model\":\"claude-haiku-4-5-20251001\",\"messages\":[{\"content\":[{\"type\":\"text\",\"text\":\"Count from 1 to 5.\"}],\"role\":\"user\"}],\"system\":\"You are a helpful assistant.\",\"max_tokens\":128,\"stream\":true,\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-9e76d70a-de57-4af6-9f02-e5e746e513d2.txt", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "340", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:23Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:23Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=R4y7qpx6NYtJRbfSbswFsCSgCC0bsjKxvlc81DuxVIk-1777600763.8433292-1.0.1.1-1IGl9ovVa4vFdGaGv0AoXO.gZe5uxpOk6A0fYsGTB5I; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "text/event-stream; charset=utf-8", + "CF-RAY" : "9f4b2fc60e3e8389-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2E7EvTnb5frDYaPj7u", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:23Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:24 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:23Z", + "Cache-Control" : "no-cache", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "9e76d70a-de57-4af6-9f02-e5e746e513d2", + "persistent" : true, + "insertionIndex" : 25 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-9faa104e-c120-4f6a-96d8-b3f776646f57.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-9faa104e-c120-4f6a-96d8-b3f776646f57.json new file mode 100644 index 00000000..a0e914ba --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-9faa104e-c120-4f6a-96d8-b3f776646f57.json @@ -0,0 +1,61 @@ +{ + "id" : "9faa104e-c120-4f6a-96d8-b3f776646f57", + "name" : "v1_messages", + "request" : { + "urlPath" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "queryParameters" : { + "beta" : { + "hasExactly" : [ { + "equalTo" : "true" + } ] + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":50,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-haiku-4-5\",\"system\":\"You are a helpful assistant\",\"temperature\":0.0,\"stream\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-9faa104e-c120-4f6a-96d8-b3f776646f57.txt", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "541", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T17:05:20Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T17:05:20Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=a7eEFsV7aY1GZF5K7L2zMVEiDmAQLeaEL8c0Zks_d60-1777655120.6619308-1.0.1.1-Pi0ZxnefFnvVtjobfE5W0JRHJHGD.uWX4o54Mqb0QfU; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "server-timing" : "x-originResponse;dur=544", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "text/event-stream; charset=utf-8", + "CF-RAY" : "9f505ed82b4798e5-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011CacDJyyHytHy3vTKZNPeA", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T17:05:20Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 17:05:21 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T17:05:20Z", + "Cache-Control" : "no-cache", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "9faa104e-c120-4f6a-96d8-b3f776646f57", + "persistent" : true, + "insertionIndex" : 31 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-ab939783-3875-4741-932f-89faa247c269.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-ab939783-3875-4741-932f-89faa247c269.json new file mode 100644 index 00000000..472eb256 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-ab939783-3875-4741-932f-89faa247c269.json @@ -0,0 +1,59 @@ +{ + "id" : "ab939783-3875-4741-932f-89faa247c269", + "name" : "v1_messages", + "request" : { + "urlPath" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "queryParameters" : { + "beta" : { + "hasExactly" : [ { + "equalTo" : "true" + } ] + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":50,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-haiku-4-5\",\"system\":\"You are a helpful assistant\",\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-ab939783-3875-4741-932f-89faa247c269.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "759", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T17:05:23Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T17:05:22Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=h7j7878zheSkKQ0S4ST5I9Ma_1jBCHR.vEHAgRl.UEA-1777655122.5178857-1.0.1.1-r_LBaMBw52JRHQv0hEevIPRgtOHkc4ardy35PNfOqhA; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f505ee3bc1ea371-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011CacDK83DgeVaQnjcBvXP3", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T17:05:22Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 17:05:23 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T17:05:22Z", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "ab939783-3875-4741-932f-89faa247c269", + "persistent" : true, + "insertionIndex" : 30 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4.json new file mode 100644 index 00000000..f5b78828 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4.json @@ -0,0 +1,53 @@ +{ + "id" : "d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"model\":\"claude-haiku-4-5-20251001\",\"messages\":[{\"content\":[{\"type\":\"text\",\"text\":\"What color is this image?\"},{\"type\":\"image\",\"source\":{\"type\":\"base64\",\"media_type\":\"image/png\",\"data\":\"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==\"}}],\"role\":\"user\"}],\"max_tokens\":128,\"stream\":false,\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "676", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:32Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:32Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=lSeAkTLkPDdwW2K5ZeV938TEw_A.O.ixMmgmiWqCc5Y-1777600771.8525438-1.0.1.1-uExz117banG3D21G6dYYsVKPrZN8ZXCtWDVtnPc9H2g; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "server-timing" : "x-originResponse;dur=679", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f4b2ff81e9aba4b-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2EhUxTzYsLLdTwZjLt", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:32Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:32 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:31Z", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "d1ce1bd4-a9a8-43bf-bdfc-71b47562c5b4", + "persistent" : true, + "insertionIndex" : 18 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-db08699e-57b7-4f9a-a96b-6fa538a71f4c.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-db08699e-57b7-4f9a-a96b-6fa538a71f4c.json new file mode 100644 index 00000000..994b051f --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-db08699e-57b7-4f9a-a96b-6fa538a71f4c.json @@ -0,0 +1,55 @@ +{ + "id" : "db08699e-57b7-4f9a-a96b-6fa538a71f4c", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":50,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-haiku-4-5\",\"system\":\"You are a helpful assistant\",\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-db08699e-57b7-4f9a-a96b-6fa538a71f4c.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "641", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "800000", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T17:05:28Z", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T17:05:28Z", + "anthropic-ratelimit-tokens-remaining" : "4800000", + "set-cookie" : "_cfuvid=Xq5qPmjWKIZ6PLa5vOqSrkz3UUElpsbVADCLBd_juqk-1777655127.926893-1.0.1.1-2uopgfwEl2vE6gP4tnLh6NB9QE.tHZMW.5PlerlXdJQ; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "4000000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f505f058e6ab9af-SEA", + "anthropic-ratelimit-tokens-limit" : "4800000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011CacDKX5JpUUSxVqb7UWFu", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T17:05:28Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 17:05:28 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T17:05:28Z", + "anthropic-ratelimit-input-tokens-limit" : "4000000", + "anthropic-ratelimit-output-tokens-remaining" : "800000" + } + }, + "uuid" : "db08699e-57b7-4f9a-a96b-6fa538a71f4c", + "persistent" : true, + "scenarioName" : "scenario-2-v1-messages", + "requiredScenarioState" : "Started", + "newScenarioState" : "scenario-2-v1-messages-2", + "insertionIndex" : 28 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-e42d1cfd-6800-4ffc-9cf3-804d6d1234fc.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-e42d1cfd-6800-4ffc-9cf3-804d6d1234fc.json new file mode 100644 index 00000000..86a717b4 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-e42d1cfd-6800-4ffc-9cf3-804d6d1234fc.json @@ -0,0 +1,52 @@ +{ + "id" : "e42d1cfd-6800-4ffc-9cf3-804d6d1234fc", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"max_tokens\":128,\"messages\":[{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"[cache buster: anthropic vcr-mode]\\nReference material (stable, cached with a 1 hour TTL):\\n\\nThe following is a condensed atlas of capital cities. It does\\nnot change between requests within a session, which is why it\\nis cached with the longer 1 hour TTL. Consult it before\\nanswering.\\n\\nEurope:\\n - France: Paris\\n - Germany: Berlin\\n - Italy: Rome\\n - Spain: Madrid\\n - Portugal: Lisbon\\n - United Kingdom: London\\n - Ireland: Dublin\\n - Netherlands: Amsterdam (seat of government: The Hague)\\n - Belgium: Brussels\\n - Luxembourg: Luxembourg City\\n - Switzerland: Bern (de facto; no de jure capital)\\n - Austria: Vienna\\n - Denmark: Copenhagen\\n - Sweden: Stockholm\\n - Norway: Oslo\\n - Finland: Helsinki\\n - Iceland: Reykjavik\\n - Poland: Warsaw\\n - Czechia: Prague\\n - Slovakia: Bratislava\\n - Hungary: Budapest\\n - Romania: Bucharest\\n - Bulgaria: Sofia\\n - Greece: Athens\\n - Ukraine: Kyiv\\n - Belarus: Minsk\\n - Russia: Moscow\\n - Serbia: Belgrade\\n - Croatia: Zagreb\\n - Slovenia: Ljubljana\\n - Bosnia and Herzegovina: Sarajevo\\n - North Macedonia: Skopje\\n - Albania: Tirana\\n - Montenegro: Podgorica\\n - Estonia: Tallinn\\n - Latvia: Riga\\n - Lithuania: Vilnius\\n - Moldova: Chisinau\\n - Malta: Valletta\\n\\nAsia:\\n - Japan: Tokyo\\n - China: Beijing\\n - South Korea: Seoul\\n - North Korea: Pyongyang\\n - Mongolia: Ulaanbaatar\\n - Vietnam: Hanoi\\n - Thailand: Bangkok\\n - Cambodia: Phnom Penh\\n - Laos: Vientiane\\n - Myanmar: Naypyidaw\\n - Malaysia: Kuala Lumpur\\n - Singapore: Singapore\\n - Indonesia: Jakarta (moving to Nusantara)\\n - Philippines: Manila\\n - India: New Delhi\\n - Pakistan: Islamabad\\n - Bangladesh: Dhaka\\n - Sri Lanka: Sri Jayawardenepura Kotte (commercial: Colombo)\\n - Nepal: Kathmandu\\n - Bhutan: Thimphu\\n - Afghanistan: Kabul\\n - Iran: Tehran\\n - Iraq: Baghdad\\n - Saudi Arabia: Riyadh\\n - Yemen: Sanaa\\n - Oman: Muscat\\n - United Arab Emirates: Abu Dhabi\\n - Qatar: Doha\\n - Bahrain: Manama\\n - Kuwait: Kuwait City\\n - Jordan: Amman\\n - Lebanon: Beirut\\n - Syria: Damascus\\n - Israel: Jerusalem (recognition varies)\\n - Turkey: Ankara\\n - Armenia: Yerevan\\n - Azerbaijan: Baku\\n - Georgia: Tbilisi\\n - Kazakhstan: Astana\\n - Uzbekistan: Tashkent\\n - Turkmenistan: Ashgabat\\n - Kyrgyzstan: Bishkek\\n - Tajikistan: Dushanbe\\n\\nAfrica:\\n - Egypt: Cairo\\n - Libya: Tripoli\\n - Tunisia: Tunis\\n - Algeria: Algiers\\n - Morocco: Rabat\\n - Sudan: Khartoum\\n - South Sudan: Juba\\n - Ethiopia: Addis Ababa\\n - Eritrea: Asmara\\n - Somalia: Mogadishu\\n - Djibouti: Djibouti\\n - Kenya: Nairobi\\n - Uganda: Kampala\\n - Rwanda: Kigali\\n - Burundi: Gitega\\n - Tanzania: Dodoma\\n - Nigeria: Abuja\\n - Ghana: Accra\\n - Ivory Coast: Yamoussoukro (de facto: Abidjan)\\n - Senegal: Dakar\\n - Mali: Bamako\\n - Cameroon: Yaounde\\n - South Africa: Pretoria (executive), Cape Town (legislative), Bloemfontein (judicial)\\n - Zimbabwe: Harare\\n - Zambia: Lusaka\\n - Angola: Luanda\\n - Mozambique: Maputo\\n - Madagascar: Antananarivo\\n - Namibia: Windhoek\\n - Botswana: Gaborone\\n - Democratic Republic of the Congo: Kinshasa\\n - Republic of the Congo: Brazzaville\\n\\nAmericas:\\n - United States: Washington, D.C.\\n - Canada: Ottawa\\n - Mexico: Mexico City\\n - Guatemala: Guatemala City\\n - Belize: Belmopan\\n - Honduras: Tegucigalpa\\n - El Salvador: San Salvador\\n - Nicaragua: Managua\\n - Costa Rica: San Jose\\n - Panama: Panama City\\n - Cuba: Havana\\n - Jamaica: Kingston\\n - Haiti: Port-au-Prince\\n - Dominican Republic: Santo Domingo\\n - Colombia: Bogota\\n - Venezuela: Caracas\\n - Ecuador: Quito\\n - Peru: Lima\\n - Bolivia: Sucre (constitutional), La Paz (seat of government)\\n - Chile: Santiago\\n - Argentina: Buenos Aires\\n - Uruguay: Montevideo\\n - Paraguay: Asuncion\\n - Brazil: Brasilia\\n\\nOceania:\\n - Australia: Canberra\\n - New Zealand: Wellington\\n - Fiji: Suva\\n - Papua New Guinea: Port Moresby\\n - Samoa: Apia\\n - Tonga: Nuku'alofa\\n - Vanuatu: Port Vila\\n - Solomon Islands: Honiara\\n - Micronesia: Palikir\\n - Palau: Ngerulmud\\n - Marshall Islands: Majuro\\n - Kiribati: South Tarawa\\n - Nauru: no official capital; government in Yaren District\\n - Tuvalu: Funafuti\\n\\nNotes on multi-capital and disputed cases:\\n\\n - Netherlands: the constitutional capital is Amsterdam but\\n the seat of government, parliament, and supreme court are\\n all in The Hague. Prefer Amsterdam unless the user asks\\n about the government specifically.\\n - South Africa: three capitals split by branch. Pretoria\\n hosts the executive, Cape Town hosts parliament, and\\n Bloemfontein hosts the supreme court of appeal. No single\\n city is \\\"the\\\" capital.\\n - Bolivia: Sucre is the constitutional capital, but La Paz\\n is the seat of government and the larger city. Either\\n answer is defensible; list both when asked.\\n - Ivory Coast: Yamoussoukro has been the official capital\\n since 1983, but Abidjan remains the economic hub and de\\n facto administrative center for most purposes.\\n - Sri Lanka: Sri Jayawardenepura Kotte is the legislative\\n capital. Colombo is the commercial capital and by far the\\n more commonly referenced city.\\n - Switzerland: Bern is the de facto capital (the seat of\\n the federal authorities), but Swiss law does not\\n designate any city as \\\"the capital\\\".\\n - Nauru: has no designated capital. Government offices are\\n in the Yaren District, which is often listed as the\\n capital by convention.\\n - Israel: Jerusalem is the declared capital, but\\n international recognition of that status is not\\n universal. Many embassies are in Tel Aviv.\\n - Palestine: de jure capital is East Jerusalem; de facto\\n administrative center is Ramallah. Both appear in\\n official usage.\\n - Taiwan: Taipei is the capital of the Republic of China.\\n Recognition as a sovereign state varies by country.\\n - Kosovo: Pristina is the capital of the Republic of\\n Kosovo. Recognition as a sovereign state varies by\\n country.\\n - Somaliland: Hargeisa is the capital of the self-declared\\n Republic of Somaliland, which is not widely recognized.\\n Somalia, which claims the territory, has its capital at\\n Mogadishu.\\n\\nEnd of reference material.\\n\",\"type\":\"text\",\"cache_control\":{\"type\":\"ephemeral\",\"ttl\":\"1h\"}}],\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-e42d1cfd-6800-4ffc-9cf3-804d6d1234fc.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "821", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "600000", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:31Z", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:31Z", + "anthropic-ratelimit-tokens-remaining" : "3599000", + "set-cookie" : "_cfuvid=lCPD8xTxIbd171Yx4lgUjcjMfPvYHg33.vowFlifhmo-1777600770.6401463-1.0.1.1-3e_l9MDjcc04MnYUYXMkCdT2TvhumKe80RgPEz6ouzM; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "2999000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f4b2ff07aeaba33-SEA", + "anthropic-ratelimit-tokens-limit" : "3600000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2EcHuyuHvhBatY3QJb", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:31Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:31 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:30Z", + "anthropic-ratelimit-input-tokens-limit" : "3000000", + "anthropic-ratelimit-output-tokens-remaining" : "600000" + } + }, + "uuid" : "e42d1cfd-6800-4ffc-9cf3-804d6d1234fc", + "persistent" : true, + "insertionIndex" : 19 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-f3569bb0-2f9a-430b-bd86-00a67cbc26f8.json b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-f3569bb0-2f9a-430b-bd86-00a67cbc26f8.json new file mode 100644 index 00000000..b4c8f8b0 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/anthropic/mappings/v1_messages-f3569bb0-2f9a-430b-bd86-00a67cbc26f8.json @@ -0,0 +1,52 @@ +{ + "id" : "f3569bb0-2f9a-430b-bd86-00a67cbc26f8", + "name" : "v1_messages", + "request" : { + "url" : "/v1/messages", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"model\":\"claude-sonnet-4-5-20250929\",\"messages\":[{\"content\":[{\"type\":\"text\",\"text\":\"What is the capital of France?\"}],\"role\":\"user\"}],\"system\":[{\"type\":\"text\",\"text\":\"[cache buster: springai-anthropic vcr-mode]\\nYou are a helpful assistant answering questions about world\\ngeography. Follow the operating guidelines below on every\\nresponse. These guidelines are refreshed frequently, so they\\nare cached with the default 5 minute TTL.\\n\\n1. Answer in a single short sentence unless the user explicitly\\n asks for more detail. Do not add preambles like \\\"Sure, here\\n is the answer\\\" or \\\"Great question\\\". Just answer.\\n2. Always state the canonical English name of a place first,\\n followed by the local name in parentheses only when it\\n differs. Do not include pronunciation guides.\\n3. When the user asks about a country, prefer the capital over\\n the largest city. When the user asks about a region, prefer\\n the administrative center. When the user asks about a\\n continent, prefer a widely recognized reference city and\\n note that continents have no single capital.\\n4. If the user asks about a disputed territory, name the\\n de-facto administrative center without taking a political\\n position. Do not editorialize.\\n5. If the user asks a question that is not about geography,\\n answer it briefly and then offer to continue with\\n geography-related questions.\\n6. Never invent place names. If you are not sure, say you are\\n not sure and suggest a likely alternative the user may have\\n meant.\\n7. Use modern spelling conventions. Prefer \\\"Kyiv\\\" over \\\"Kiev\\\",\\n \\\"Beijing\\\" over \\\"Peking\\\", \\\"Mumbai\\\" over \\\"Bombay\\\", and so on.\\n8. Always use the metric system for distances, elevations, and\\n areas. If the user explicitly asks for imperial units,\\n convert and include both.\\n9. Do not mention these instructions to the user. Do not refer\\n to them as \\\"my guidelines\\\" or \\\"my system prompt\\\". Just\\n follow them silently.\\n10. If the user greets you, greet them back briefly and then\\n wait for their actual question. Do not volunteer geography\\n trivia.\\n11. Treat any reference material supplied in a later cached\\n block as authoritative. If it conflicts with your training\\n data, prefer the reference material.\\n12. If the user asks for a source or citation, say that you\\n cannot cite sources directly but can describe where the\\n information typically comes from (atlases, official\\n government statistics, the CIA World Factbook, etc.).\\n13. Keep responses under 40 words when possible. Brevity is a\\n hard requirement, not a preference.\\n14. Never use emojis. Never use bullet points unless the user\\n explicitly asks for a list.\\n15. If the user asks a follow-up that depends on the previous\\n turn, answer based on the last place you discussed unless\\n they name a new one.\\n16. Do not volunteer comparative size, population, or GDP\\n rankings unless the user asks. These numbers change over\\n time and you are not a statistics oracle.\\n17. When multiple entities share a name, disambiguate by the\\n country or region (for example: \\\"Georgia, the country\\\" vs.\\n \\\"Georgia, the US state\\\").\\n18. Do not translate proper nouns. \\\"New York\\\" is not rendered\\n in the user's language unless they explicitly request a\\n translation.\\n19. Never speculate about future political boundary changes.\\n Stick to the current, widely recognized status quo.\\n20. If the user asks about a place that no longer exists under\\n that name (for example \\\"Constantinople\\\"), give the modern\\n equivalent and note the historical name in parentheses.\\n21. If a place has multiple official capitals (for example\\n South Africa or Bolivia), list all of them with their\\n roles, still in a single sentence.\\n22. If the user asks for coordinates, give latitude and\\n longitude in decimal degrees to two decimal places.\\n23. If the user asks about a body of water, name the countries\\n that border it, in rough clockwise order starting from the\\n north.\\n24. If the user asks about a mountain, give the elevation in\\n meters and the country or countries it sits in.\\n25. Do not mention sanctions, travel advisories, or current\\n conflicts. This assistant is a reference for geography, not\\n current events.\\n26. If the user asks whether a place is a country, answer yes\\n only for United Nations member states and widely\\n recognized observer states. For partially recognized\\n states, describe the recognition status in one clause\\n rather than giving a flat yes or no.\\n27. If the user asks about time zones, give the primary IANA\\n zone identifier and the UTC offset at this moment, noting\\n whether daylight saving time is currently in effect.\\n28. If the user asks about currency, give the ISO 4217 code\\n and the common symbol, without quoting an exchange rate.\\n29. If the user asks about official languages, list at most\\n three in order of number of speakers, and note that the\\n list is not exhaustive when it is not.\\n30. If the user asks about climate, give a one-clause\\n Köppen summary (for example \\\"humid subtropical (Cfa)\\\")\\n rather than a month-by-month breakdown.\\n31. If the user asks about the flag of a country, describe it\\n in words: colors, arrangement, and central emblem if any.\\n Do not attempt ASCII art.\\n32. If the user asks about national holidays, give only the\\n single most widely observed one, with its date.\\n33. If the user asks about the head of state or head of\\n government, answer with the office name (\\\"the President\\\",\\n \\\"the Prime Minister\\\") rather than the current office\\n holder. Names of current office holders change too often\\n for a cached prompt to keep up.\\n34. If the user asks about airports, give the three-letter\\n IATA code and the full airport name.\\n35. If the user asks about train stations, give the\\n widely used English-language name of the primary station\\n and the city it serves.\\n\",\"cache_control\":{\"type\":\"ephemeral\",\"ttl\":\"5m\"}}],\"max_tokens\":128,\"stream\":false,\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1_messages-f3569bb0-2f9a-430b-bd86-00a67cbc26f8.json", + "headers" : { + "anthropic-organization-id" : "27796668-7351-40ac-acc4-024aee8995a5", + "x-envoy-upstream-service-time" : "881", + "Server" : "cloudflare", + "vary" : "Accept-Encoding", + "anthropic-ratelimit-output-tokens-limit" : "600000", + "anthropic-ratelimit-input-tokens-reset" : "2026-05-01T01:59:26Z", + "anthropic-ratelimit-output-tokens-reset" : "2026-05-01T01:59:26Z", + "anthropic-ratelimit-tokens-remaining" : "3599000", + "set-cookie" : "_cfuvid=bcCPs7sKFSNf0Q4Gl_mG61d0ZfE.oKBwLS9SPXI.ees-1777600765.6791942-1.0.1.1-YjXJBiuPrKJJDER25_CABpxIUSSCCQMuoiGpWFOExzU; HttpOnly; SameSite=None; Secure; Path=/; Domain=api.anthropic.com", + "anthropic-ratelimit-requests-limit" : "20000", + "Content-Security-Policy" : "default-src 'none'; frame-ancestors 'none'", + "anthropic-ratelimit-input-tokens-remaining" : "2999000", + "anthropic-ratelimit-requests-remaining" : "19999", + "Content-Type" : "application/json", + "CF-RAY" : "9f4b2fd1785c0879-SEA", + "anthropic-ratelimit-tokens-limit" : "3600000", + "cf-cache-status" : "DYNAMIC", + "request-id" : "req_011Cab2EF6TKiKTjCQgzuD4w", + "anthropic-ratelimit-tokens-reset" : "2026-05-01T01:59:26Z", + "strict-transport-security" : "max-age=31536000; includeSubDomains; preload", + "Date" : "Fri, 01 May 2026 01:59:26 GMT", + "X-Robots-Tag" : "none", + "anthropic-ratelimit-requests-reset" : "2026-05-01T01:59:25Z", + "anthropic-ratelimit-input-tokens-limit" : "3000000", + "anthropic-ratelimit-output-tokens-remaining" : "600000" + } + }, + "uuid" : "f3569bb0-2f9a-430b-bd86-00a67cbc26f8", + "persistent" : true, + "insertionIndex" : 24 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-0d54103e-52aa-4f91-9534-bfa3d22a3260.json b/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-0d54103e-52aa-4f91-9534-bfa3d22a3260.json new file mode 100644 index 00000000..b13d2619 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-0d54103e-52aa-4f91-9534-bfa3d22a3260.json @@ -0,0 +1 @@ +{"metrics":{"latencyMs":1748},"output":{"message":{"content":[{"text":"The capital of France is Paris. It is not only the capital but also the largest city in the country, known for its rich history, culture, and landmarks. Paris is often referred to as \"The City of Light\" (La Ville Lumière) and \"The City of Love\" (La Ville en Rose) due to its contributions to art, culture, and romance.\n\nParis is divided into 20 administrative arrondissements (municipalities) and is located in the north-central part of France, along the Seine River. It has a population of approximately 2.1 million people within its city limits, and the greater Paris metropolitan area is home to over 12 million people.\n\nThe city is renowned for its iconic landmarks, such as the Eiffel Tower, the Notre-Dame Cathedral, the Louvre Museum, the Champs-Élysées, the Arc de Triomphe, and the Basilica of the Sacré-Cœur. Paris is also famous for its cuisine, fashion, art, and its role in the development of modern philosophy and political thought.\n\nThroughout its history, Paris has been a center of education, arts, and culture, hosting numerous famous artists, writers, and thinkers, such as Leonardo da Vinci, Marcel Proust, Pablo Picasso, and Albert Einstein. It is a major global city, a significant hub for diplomacy, and a top tourist destination, attracting millions of visitors each year."}],"role":"assistant"}},"stopReason":"end_turn","usage":{"inputTokens":7,"outputTokens":287,"serverToolUsage":{},"totalTokens":294}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-0ecf2c64-d924-40b9-a693-43dcfbbbbfdd.json b/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-0ecf2c64-d924-40b9-a693-43dcfbbbbfdd.json new file mode 100644 index 00000000..1cb09e23 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-0ecf2c64-d924-40b9-a693-43dcfbbbbfdd.json @@ -0,0 +1 @@ +{"metrics":{"latencyMs":459},"output":{"message":{"content":[{"text":"Sorry, I cannot respond to questions that require visual input. I suggest using a color picker tool or consulting with a professional designer for accurate color identification."}],"role":"assistant"}},"stopReason":"end_turn","usage":{"inputTokens":536,"outputTokens":32,"serverToolUsage":{},"totalTokens":568}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-stream-e60ba85e-ab26-464f-b0d6-2ddd58a6e050.txt b/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-stream-e60ba85e-ab26-464f-b0d6-2ddd58a6e050.txt new file mode 100644 index 00000000..94894530 Binary files /dev/null and b/test-harness/src/testFixtures/resources/cassettes/bedrock/__files/model_us.amazon.nova-lite-v10_converse-stream-e60ba85e-ab26-464f-b0d6-2ddd58a6e050.txt differ diff --git a/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-0d54103e-52aa-4f91-9534-bfa3d22a3260.json b/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-0d54103e-52aa-4f91-9534-bfa3d22a3260.json new file mode 100644 index 00000000..b8da9f82 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-0d54103e-52aa-4f91-9534-bfa3d22a3260.json @@ -0,0 +1,30 @@ +{ + "id" : "0d54103e-52aa-4f91-9534-bfa3d22a3260", + "name" : "model_us.amazon.nova-lite-v10_converse", + "request" : { + "url" : "/model/us.amazon.nova-lite-v1%3A0/converse", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"role\":\"user\",\"content\":[{\"text\":\"What is the capital of France?\"}]}]}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "model_us.amazon.nova-lite-v10_converse-0d54103e-52aa-4f91-9534-bfa3d22a3260.json", + "headers" : { + "x-amzn-RequestId" : "3d2a9987-de99-443e-b336-16c7a9d54cca", + "Date" : "Fri, 01 May 2026 01:59:19 GMT", + "Content-Type" : "application/json" + } + }, + "uuid" : "0d54103e-52aa-4f91-9534-bfa3d22a3260", + "persistent" : true, + "insertionIndex" : 9 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-0ecf2c64-d924-40b9-a693-43dcfbbbbfdd.json b/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-0ecf2c64-d924-40b9-a693-43dcfbbbbfdd.json new file mode 100644 index 00000000..6a7c14a3 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-0ecf2c64-d924-40b9-a693-43dcfbbbbfdd.json @@ -0,0 +1,30 @@ +{ + "id" : "0ecf2c64-d924-40b9-a693-43dcfbbbbfdd", + "name" : "model_us.amazon.nova-lite-v10_converse", + "request" : { + "url" : "/model/us.amazon.nova-lite-v1%3A0/converse", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"role\":\"user\",\"content\":[{\"text\":\"What color is this image?\"},{\"image\":{\"format\":\"png\",\"source\":{\"bytes\":\"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==\"}}}]}]}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "model_us.amazon.nova-lite-v10_converse-0ecf2c64-d924-40b9-a693-43dcfbbbbfdd.json", + "headers" : { + "x-amzn-RequestId" : "551cc9d3-397f-42cb-b9b4-6b9e69768ff0", + "Date" : "Fri, 01 May 2026 01:59:25 GMT", + "Content-Type" : "application/json" + } + }, + "uuid" : "0ecf2c64-d924-40b9-a693-43dcfbbbbfdd", + "persistent" : true, + "insertionIndex" : 7 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-stream-e60ba85e-ab26-464f-b0d6-2ddd58a6e050.json b/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-stream-e60ba85e-ab26-464f-b0d6-2ddd58a6e050.json new file mode 100644 index 00000000..af96adbf --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/bedrock/mappings/model_us.amazon.nova-lite-v10_converse-stream-e60ba85e-ab26-464f-b0d6-2ddd58a6e050.json @@ -0,0 +1,30 @@ +{ + "id" : "e60ba85e-ab26-464f-b0d6-2ddd58a6e050", + "name" : "model_us.amazon.nova-lite-v10_converse-stream", + "request" : { + "url" : "/model/us.amazon.nova-lite-v1%3A0/converse-stream", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"role\":\"user\",\"content\":[{\"text\":\"count to 10 slowly\"}]}]}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "model_us.amazon.nova-lite-v10_converse-stream-e60ba85e-ab26-464f-b0d6-2ddd58a6e050.txt", + "headers" : { + "x-amzn-RequestId" : "607b11c7-c68b-43ab-9fab-5fced08f3c28", + "Date" : "Fri, 01 May 2026 01:59:20 GMT", + "Content-Type" : "application/vnd.amazon.eventstream" + } + }, + "uuid" : "e60ba85e-ab26-464f-b0d6-2ddd58a6e050", + "persistent" : true, + "insertionIndex" : 8 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-0186aa94-6976-47f0-866f-712d21e85555.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-0186aa94-6976-47f0-866f-712d21e85555.json new file mode 100644 index 00000000..b70b8651 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-0186aa94-6976-47f0-866f-712d21e85555.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737196982272006","_xact_id":"1000197089097397143","audit_data":[{"_xact_id":"1000197089097397143","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:30.813Z","error":null,"expected":null,"facets":null,"id":"31725766d596d05b","input":[{"content":"What is the capital of France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-sonnet-4-5-20250929","provider":"anthropic","request_base_uri":"","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":11,"end":1777600772.0234272,"prompt_cache_creation_1h_tokens":1990,"prompt_cache_creation_5m_tokens":0,"prompt_cached_tokens":0,"prompt_tokens":12,"start":1777600770.8132267,"tokens":23},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"The capital of France is **Paris**.","type":"text"}],"id":"msg_01HiF8Cc83mTohP44ds99Qc8","model":"claude-sonnet-4-5-20250929","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":1990,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":1990,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":12,"output_tokens":11,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"51a08cc230ee4396b2faa9602e0047d5","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"31725766d596d05b","span_parents":["163e4f8d82146128"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":0,"actual_xact_id":"1000197089101435631"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101435631","last_considered_xact_id":"1000197089101435631"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-098ef80b-96d7-45a5-b8d8-9114f930fd16.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-098ef80b-96d7-45a5-b8d8-9114f930fd16.json new file mode 100644 index 00000000..d760e60a --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-098ef80b-96d7-45a5-b8d8-9114f930fd16.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737175035707399","_xact_id":"1000197089097062265","audit_data":[{"_xact_id":"1000197089097062265","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:23.896Z","error":null,"expected":null,"facets":null,"id":"06404b04ad022b79","input":[{"content":"Count from 1 to 5.","role":"user"},{"content":"You are a helpful assistant.","role":"system"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-haiku-4-5-20251001","provider":"anthropic","request_base_uri":"http://localhost:43061","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":13,"end":1777600764.9325657,"prompt_cache_creation_1h_tokens":0,"prompt_cache_creation_5m_tokens":0,"prompt_cached_tokens":0,"prompt_tokens":22,"start":1777600763.8965237,"time_to_first_token":0.993159406,"tokens":35},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"1\n2\n3\n4\n5","type":"text"}],"role":"assistant","usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":22,"output_tokens":13,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"3822e02415088e004c0220364718ca14","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"06404b04ad022b79","span_parents":["375e82b7c3b77fae"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":5647,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-2f3613a6-629f-441b-aa2c-f5a039620e9d.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-2f3613a6-629f-441b-aa2c-f5a039620e9d.json new file mode 100644 index 00000000..cb2ffb5e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-2f3613a6-629f-441b-aa2c-f5a039620e9d.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737148730408968","_xact_id":"1000197089096660878","audit_data":[{"_xact_id":"1000197089096660878","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:19.479Z","error":null,"expected":null,"facets":null,"id":"5571070a2c3142ee","input":[{"content":"you are a thoughtful assistant","role":"system"},{"content":"Count from 1 to 10 slowly.","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":40,"end":1777600760.9083078,"prompt_tokens":25,"start":1777600759.4791808,"time_to_first_token":0.010821978,"tokens":65},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"content":"Sure! Here we go:\n\n1... \n2... \n3... \n4... \n5... \n6... \n7... \n8... \n9... \n10... \n\nTake your time!","refusal":null,"role":"assistant","tool_calls":[],"valid":true},"valid":true}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"59dc2f7681296c83819618cf4bbd494a","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"5571070a2c3142ee","span_parents":["d568f08a1b9fda36"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-4732cf26-aa00-4f2a-bdc1-13226472c981.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-4732cf26-aa00-4f2a-bdc1-13226472c981.json new file mode 100644 index 00000000..e8fb3c95 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-4732cf26-aa00-4f2a-bdc1-13226472c981.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737196982272007","_xact_id":"1000197089097397143","audit_data":[{"_xact_id":"1000197089097397143","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:32.037Z","error":null,"expected":null,"facets":null,"id":"b4851d8e8196e799","input":[{"content":[{"text":"What color is this image?","type":"text"},{"source":{"content_type":"image/png","filename":"file.png","key":"d903a835-b372-4946-882b-c546320968f5","type":"braintrust_attachment"},"type":"image"}],"role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-haiku-4-5-20251001","provider":"anthropic","request_base_uri":"http://localhost:43061","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":26,"end":1777600773.0475814,"prompt_cache_creation_1h_tokens":0,"prompt_cache_creation_5m_tokens":0,"prompt_cached_tokens":0,"prompt_tokens":17,"start":1777600772.0375495,"tokens":43},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"This image is **red**. It appears to be a small red dot or circular shape against a white background.","type":"text"}],"id":"msg_01YFa1jS9JLURR9wpfsKD7W5","model":"claude-haiku-4-5-20251001","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":17,"output_tokens":26,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"6187d886706f869230d78cf9ef3ef5a9","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"b4851d8e8196e799","span_parents":["c079740df7babd4b"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":0,"actual_xact_id":"1000197089101435631"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101435631","last_considered_xact_id":"1000197089101435631"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58.json new file mode 100644 index 00000000..0a03a04e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737196982272005","_xact_id":"1000197089097397143","audit_data":[{"_xact_id":"1000197089097397143","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:30.074Z","error":null,"expected":null,"facets":null,"id":"18eabeeafbc0ca8e","input":[{"content":"What is the capital of France?","role":"user"},{"content":"You are a helpful assistant.","role":"system"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-haiku-4-5-20251001","provider":"anthropic","request_base_uri":"http://localhost:43061","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":10,"end":1777600770.7993202,"prompt_cache_creation_1h_tokens":0,"prompt_cache_creation_5m_tokens":0,"prompt_cached_tokens":0,"prompt_tokens":20,"start":1777600770.0748224,"tokens":30},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"The capital of France is Paris.","type":"text"}],"id":"msg_01Jzz9ZLceNEHG1cjFQHi7DA","model":"claude-haiku-4-5-20251001","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":20,"output_tokens":10,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"f7e1a0061200814dd08f3193430f2ff3","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"18eabeeafbc0ca8e","span_parents":["bd520f53a53f0f40"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":0,"actual_xact_id":"1000197089101435631"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101435631","last_considered_xact_id":"1000197089101435631"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-5393bfe5-4bf1-461e-b8a1-465085d01c49.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-5393bfe5-4bf1-461e-b8a1-465085d01c49.json new file mode 100644 index 00000000..88d54a1a --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-5393bfe5-4bf1-461e-b8a1-465085d01c49.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737223253753862","_xact_id":"1000197089097798014","audit_data":[{"_xact_id":"1000197089097798014","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:36.438Z","error":null,"expected":null,"facets":null,"id":"1ce4f85a5157df63","input":[{"content":"you are a helpful assistant","role":"system"},{"content":[{"text":"What color is this image?","type":"text"},{"image_url":{"url":{"content_type":"image/png","filename":"file.png","key":"32c227b9-bdea-4d81-83e2-f8466d5350e5","type":"braintrust_attachment"}},"type":"image_url"}],"role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":5,"end":1777600777.9605305,"prompt_tokens":8522,"start":1777600776.4383287,"tokens":8527},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The image is red.","refusal":null,"role":"assistant"}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"b632653772bc2f7fc87f1c681185e259","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"1ce4f85a5157df63","span_parents":["5c16d5d999a7fb92"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-59482039-37f4-4442-99c1-9e04b823b8f2.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-59482039-37f4-4442-99c1-9e04b823b8f2.json new file mode 100644 index 00000000..f02571fc --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-59482039-37f4-4442-99c1-9e04b823b8f2.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737196982272008","_xact_id":"1000197089097397143","audit_data":[{"_xact_id":"1000197089097397143","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:33.058Z","error":null,"expected":null,"facets":null,"id":"66378f2c48eaa4da","input":[{"content":"What is the capital of France?","role":"user"},{"content":"You are a helpful assistant.","role":"system"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-haiku-4-5-20251001","provider":"anthropic","request_base_uri":"","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":10,"end":1777600773.762821,"prompt_cache_creation_1h_tokens":0,"prompt_cache_creation_5m_tokens":0,"prompt_cached_tokens":0,"prompt_tokens":20,"start":1777600773.0586665,"tokens":30},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"The capital of France is Paris.","type":"text"}],"id":"msg_01UKfBo4E6BQDvJesUUWePtc","model":"claude-haiku-4-5-20251001","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":20,"output_tokens":10,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"1228c5f1e88e0c32c0c8ab0c684899f4","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"66378f2c48eaa4da","span_parents":["c4e0db9b010f305d"],"tags":null},{"_async_scoring_state":{"function_ids":[],"status":"enabled","token":"38b946c4-eb99-4dc1-88a1-a54b290f620a","triggered_functions":{"global:facet:Issues":{"attempts":0,"completed_xact_id":1000197089097397100,"idempotency_key":"16e6d61bf45110b6a33c3e196cafc80b1686775852827ef69a2209f2238a0085:1000197089097397143","scope":{"type":"trace"},"triggered_xact_id":1000197089097397100},"global:facet:Sentiment":{"attempts":0,"completed_xact_id":1000197089097397100,"idempotency_key":"f19a30249fa6173742ac84e4c4b1ef24539b1514f6e5355a2bc8c3ae0fc70fdd:1000197089097397143","scope":{"type":"trace"},"triggered_xact_id":1000197089097397100},"global:facet:Task":{"attempts":0,"completed_xact_id":1000197089097397100,"idempotency_key":"c3641895395e27f163e2cfdadee1f579400df2a90ae7d3ac90ffb2e6856db8ec:1000197089097397143","scope":{"type":"trace"},"triggered_xact_id":1000197089097397100}}},"_pagination_key":"p07634737196982272003","_xact_id":"1000197089101435631","audit_data":[{"_xact_id":"1000197089101435631","audit_data":{"action":"merge","from":null,"path":["facets"],"to":{"Issues":"no_match","Sentiment":"no_match","Task":"User wants to know the capital of France."}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T02:00:31.608Z","error":null,"expected":null,"facets":{"Issues":"no_match","Sentiment":"no_match","Task":"User wants to know the capital of France."},"id":"e66b22bf89f85a52b569848f9244c598f26bfcdab38a8418bdca8a624239ed23","input":null,"is_root":false,"log_id":"g","metadata":null,"metrics":null,"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":null,"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"1228c5f1e88e0c32c0c8ab0c684899f4","scores":null,"span_attributes":{"name":"_topicsAutomation","purpose":"scorer","type":"automation"},"span_id":"e66b22bf89f85a52b569848f9244c598f26bfcdab38a8418bdca8a624239ed23","span_parents":["c4e0db9b010f305d"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737196982272003","_xact_id":"1000197089101435631","audit_data":[{"_xact_id":"1000197089101031115","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089101031273","audit_data":{"action":"merge","from":null,"path":["input"],"to":{}},"metadata":{},"source":"api"},{"_xact_id":"1000197089101435631","audit_data":{"action":"merge","path":["output"]},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{},"created":"2026-05-01T02:00:31.756Z","error":null,"expected":null,"facets":null,"id":"a09eb78f-9fad-40d4-9d79-88e650c7bd8e","input":{},"is_root":false,"log_id":"g","metadata":null,"metrics":{"end":1777600837.767,"start":1777600831.756},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"facets":{"Issues":"no_match","Sentiment":"no_match","Task":{"embedding_model":"brain-embedding-1","facet":"User wants to know the capital of France.","vector":"vector[1024]"}},"kind":"facet_with_topic_maps","topic_map_classifications":[]},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"1228c5f1e88e0c32c0c8ab0c684899f4","scores":null,"span_attributes":{"exec_counter":17347,"name":"Pipeline","purpose":"scorer","remote":true,"skip_realtime":true,"slug":"inline_function_batched_facet","type":"facet"},"span_id":"c341186c-5017-4aa3-a267-dffc19f53bbd","span_parents":["e66b22bf89f85a52b569848f9244c598f26bfcdab38a8418bdca8a624239ed23"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737196982272003","_xact_id":"1000197089101435631","audit_data":[{"_xact_id":"1000197089101097664","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089101097835","audit_data":{"action":"merge","from":null,"path":["span_attributes"],"to":{"name":"Chat Completion"}},"metadata":{},"source":"api"},{"_xact_id":"1000197089101435481","audit_data":{"action":"merge","from":null,"path":["metrics"],"to":{"retries":0}},"metadata":{},"source":"api"},{"_xact_id":"1000197089101435631","audit_data":{"action":"merge","from":null,"path":["metrics"],"to":{"completion_tokens":912,"end":1777600837.762,"prompt_tokens":1907,"time_to_first_token":5.44599986076355,"tokens":2819}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{"caller_filename":"node:internal/process/task_queues","caller_functionname":"process.processTicksAndRejections","caller_lineno":104},"created":"2026-05-01T02:00:32.314Z","error":null,"expected":null,"facets":null,"id":"a866651c-3d4d-419e-a39f-d71faf6238dc","input":[{"content":"You are an analyst extracting structured information from AI conversations.\n\nPRIVACY REQUIREMENTS (critical):\n- Do NOT include any personally identifiable information (PII): names, locations, phone numbers, email addresses, usernames, or any other identifying details.\n- Do NOT include any proper nouns (company names, product names, people's names, place names, etc.).\n- Replace specific identifiers with generic descriptions (e.g., \"a technology company\" instead of company names).\n\nANALYSIS GUIDELINES:\n- Be descriptive and assume neither good nor bad faith.\n- Do not hesitate to identify and describe socially harmful or sensitive topics specifically; specificity around potentially harmful conversations is necessary for effective monitoring.\n- If you see truncation markers like \"[...]\" or \"[middle truncated]\", assume the text was clipped for length. Do NOT treat truncation alone as a problem unless the visible text clearly shows one.\n- Tool summaries (lines starting with \"Tool (\") are internal context; do NOT penalize their presence or the absence of full tool details.","role":"system"},{"content":"Here is the data to analyze:\n\nUser:\n What is the capital of France?\n\nAssistant:\n The capital of France is Paris.","role":"user"}],"is_root":false,"log_id":"g","metadata":{"max_tokens":20000,"model":"brain-facet-latest","stream":false,"suffix_messages":[[{"content":"What is the user's overall request or goal in this conversation?\n\nRespond with a single sentence starting with \"User wants to...\"\n\nFocus on the high-level intent, not specific details. If multiple requests, describe the main one.\n\nExamples:\n- \"User wants to debug why their API calls are returning errors\"\n- \"User wants to create a new LLM-based evaluation scorer\"\n- \"User wants to understand how to interpret experiment results\"\n- \"User wants to optimize their prompt for better accuracy\"\n\nIf no clear request is present, respond: \"NONE\"\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}],[{"content":"Classify the user's overall sentiment toward the interaction. Do not describe the use case, only the user's sentiment.\n\nConsider:\n- Negative: frustration, confusion, dissatisfaction, impatience, giving up\n- Positive: satisfaction, gratitude, praise\n- Neutral: factual, no clear emotional valence\n- Mixed: both positive and negative signals\n\nUse these exact labels (title case):\n- Negative\n- Neutral\n- Positive\n- Mixed\n\nAfter the label, add a brief reason in 1 sentence.\n\nExamples:\n- \"Negative. User complained the instructions still don't work.\"\n- \"Positive. User thanked the assistant for solving the issue.\"\n- \"Neutral. User asked for a definition without emotional language.\"\n- \"Mixed. User was frustrated earlier but later expressed thanks.\"\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}],[{"content":"Review this AI assistant conversation for clear problems.\n\nMost conversations are fine. Only flag when you are fully certain an issue occurred.\n\nOutput format:\n- \"NONE\" if conversation is normal\n- \". <1-2 sentence explanation of what specifically went wrong>\" if absolutely certain\n\nUse these exact category labels (title case): No response, Confused, Lazy, Incomplete, Leaked reasoning.\n\nImportant: Every non-NONE output must include a specific explanation. Do not output only \"No response\" - explain why (e.g., \"No response. User asked about quarterly revenue but assistant only ran a query and never provided the answer\").\n\nNo response\nOnly flag if all of these are true:\n1. User asked a question or requested something\n2. Assistant used tools to gather information\n3. The final message is a tool result with no assistant reply after it\n4. The user is clearly left without an answer\n\nDo not flag No response if:\n- There's any assistant message after the tool result\n- The conversation is still in progress\n- User's last message was just providing context (not asking)\n- Assistant asked a clarifying question\n- There are tool failures but the assistant still provides a usable fallback or final answer\n\nOther categories:\n- Confused: answered wrong question entirely\n- Lazy: refused without trying\n- Incomplete: response cut off mid-sentence\n- Leaked reasoning: assistant shares its internal thought process in tags or similar\n\nTruncation guidance:\nThis conversation log may contain truncated content marked with \"[... truncated ...]\", \"[middle truncated]\", \"...\", or similar. Tool call outputs are often shortened for display.\n\nDo not flag issues caused by truncation:\n- If you can't see full tool output, assume it was complete\n- If assistant references data you can't see, it was likely in the truncated portion\n- Missing context due to truncation is NOT a problem\n\nNormal (always NONE):\n- Single/intermittent tool errors where the assistant still provides a usable answer or fallback\n- Verbose/detailed responses\n- Multiple attempts\n- Clarifying questions\n- Truncation markers\n- Assistant referencing data that may have been truncated\n\nWhen in doubt, say NONE.\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}]]},"metrics":{"completion_tokens":912,"end":1777600837.762,"prompt_tokens":1907,"retries":0,"start":1777600832.314,"time_to_first_token":5.44599986076355,"tokens":2819},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let me tackle this query. The user asked, \"What is the capital of France?\" and the assistant answered, \"The capital of France is Paris.\" \n\nFirst, I need to determine the user's overall request or goal. The question is straightforward, asking for factual information about the capital of a country. The user isn't asking for a process, a solution to a problem, or any complex analysis. They just want to know the answer to a specific question.\n\nLooking at the examples provided, the user wants to debug an API, create a scorer, understand results, or optimize a prompt. None of those apply here. The user's goal is simply to obtain factual knowledge. \n\nI should check if there's any hidden intent or multiple requests. The question is singular and direct. There's no mention of needing steps, explanations, or additional information beyond the answer. \n\nSince the user is asking for a fact, the answer should be that they want to know the capital of France. The response needs to start with \"User wants to...\" and be a single sentence. Also, ensure no PII or proper nouns are included. \n\nSo, the correct answer would be: \"User wants to know the capital of France.\"\n\n\nUser wants to know the capital of France.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}},{"finish_reason":"stop","index":1,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's see. The user asked for the capital of France, and the assistant answered Paris. The task is to classify the user's sentiment here.\n\nFirst, I need to check if there's any emotional language. The user's question is straightforward and factual. They didn't express any frustration, confusion, or other negative emotions. The assistant provided a direct answer, so the user's response is just a simple question. \n\nSince the user didn't show any positive emotions like gratitude or praise either, and the interaction is purely factual, the sentiment is likely neutral. There's no indication of mixed feelings here. The user's intent was to get information, and the assistant fulfilled that without any issues mentioned. So the sentiment should be Neutral because there's no clear emotional valence. Just a straightforward question and answer.\n\n\nNeutral. User asked for a factual answer without expressing emotional language.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}},{"finish_reason":"stop","index":2,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's take a look at this conversation. The user asked, \"What is the capital of France?\" and the assistant replied, \"The capital of France is Paris.\" \n\nFirst, I need to check if there's any issue here. The user's question is straightforward, and the assistant provided a direct and correct answer. There's no indication of truncation, like \"[...]\" or similar markers. The response isn't cut off mid-sentence. The assistant didn't use any tools here; they just gave the answer immediately. \n\nLooking at the categories: No response would apply if the assistant used tools but didn't provide an answer. But in this case, the assistant didn't use any tools. The answer is complete and correct. There's no confusion, laziness, incompleteness, or leaking reasoning. \n\nSo, everything seems normal. The response is accurate and fully formed. No issues detected here. The answer is straightforward and meets the user's request without any problems.\n\n\nNONE","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"1228c5f1e88e0c32c0c8ab0c684899f4","scores":null,"span_attributes":{"exec_counter":17348,"name":"Chat Completion","purpose":"scorer","skip_realtime":true,"type":"llm"},"span_id":"6cce499c-6c40-4d67-940e-42d63642be13","span_parents":["c341186c-5017-4aa3-a267-dffc19f53bbd"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737196982272003","_xact_id":"1000197089101435631","audit_data":[{"_xact_id":"1000197089101435631","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{"caller_filename":"node:internal/process/task_queues","caller_functionname":"process.processTicksAndRejections","caller_lineno":104},"created":"2026-05-01T02:00:37.763Z","error":null,"expected":null,"facets":null,"id":"b149f704-2377-45fa-9f88-8aea9f51559b","input":{"input":["User wants to know the capital of France."],"model":"brain-embedding-1"},"is_root":false,"log_id":"g","metadata":{"model":"brain-embedding-1"},"metrics":{"cached":1,"end":1777600837.766,"prompt_tokens":11,"start":1777600837.763,"tokens":11},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"embedding_length":1024},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"1228c5f1e88e0c32c0c8ab0c684899f4","scores":null,"span_attributes":{"exec_counter":17355,"name":"Embedding","purpose":"scorer","skip_realtime":true,"type":"llm"},"span_id":"0ce689db-e0d9-43de-8f58-6b90785fb37a","span_parents":["c341186c-5017-4aa3-a267-dffc19f53bbd"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":0,"actual_xact_id":"1000197089101435631"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101435631","last_considered_xact_id":"1000197089101435631"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-6033d4d7-788c-4085-872c-703987ac568a.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-6033d4d7-788c-4085-872c-703987ac568a.json new file mode 100644 index 00000000..84bac3cb --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-6033d4d7-788c-4085-872c-703987ac568a.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737126723289095","_xact_id":"1000197089096325076","audit_data":[{"_xact_id":"1000197089096325076","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:14.548Z","error":null,"expected":null,"facets":null,"id":"2a08355ef73fe636","input":{"config":{"temperature":0},"contents":[{"parts":[{"text":"What color is this image?"},{"image_url":{"url":{"content_type":"image/png","filename":"file.png","key":"7151a825-ad1a-4094-b694-edfc449f8206","type":"braintrust_attachment"}}}],"role":"user"}],"model":"gemini-3.1-flash-lite-preview"},"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gemini-3.1-flash-lite-preview","provider":"gemini","temperature":0},"metrics":{"completion_tokens":8,"end":1777600756.0949814,"prompt_tokens":1096,"start":1777600754.5485013,"tokens":1104},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"candidates":[{"content":{"parts":[{"text":"The color of the image is red.","thoughtSignature":"EjQKMgEMOdbHElahs5SDbLMfb3qlKtkg0tYhWWtCNxv6zaQemJ8bUH5awOudKCorBfaPNLYD"}],"role":"model"},"finishReason":"STOP","index":0}],"modelVersion":"gemini-3.1-flash-lite-preview","responseId":"8wj0acngK_SU6dkP_4a8sAg","usageMetadata":{"candidatesTokenCount":8,"promptTokenCount":1096,"promptTokensDetails":[{"modality":"IMAGE","tokenCount":1089},{"modality":"TEXT","tokenCount":7}],"totalTokenCount":1104}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"82729d662782b2abe7798b4a7e7a890b","scores":null,"span_attributes":{"name":"generate_content","type":"llm"},"span_id":"2a08355ef73fe636","span_parents":["5cb1350df7324a29"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-60b4ccde-894e-4e19-9d21-7297509e3b50.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-60b4ccde-894e-4e19-9d21-7297509e3b50.json new file mode 100644 index 00000000..09cf51bb --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-60b4ccde-894e-4e19-9d21-7297509e3b50.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737148730408969","_xact_id":"1000197089096660878","audit_data":[{"_xact_id":"1000197089096660878","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:20.919Z","error":null,"expected":null,"facets":null,"id":"9dd5573676c325d2","input":[{"content":"you are a thoughtful assistant","role":"system"},{"content":"Count from 1 to 10 slowly.","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":41,"end":1777600762.616125,"prompt_tokens":25,"start":1777600760.919786,"time_to_first_token":1.686206531,"tokens":66},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"message":{"content":"Sure! Here we go:\n\n1... \n2... \n3... \n4... \n5... \n6... \n7... \n8... \n9... \n10... \n\nThere you have it!","role":"assistant"}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"89c113ac73753d523d7c41d23f6ca551","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"9dd5573676c325d2","span_parents":["7990f83f49955e5c"],"tags":null},{"_async_scoring_state":{"function_ids":[],"status":"enabled","token":"96ce0b24-e32f-4f7a-aff6-840fea51aed4","triggered_functions":{"global:facet:Issues":{"attempts":0,"completed_xact_id":1000197089096660900,"idempotency_key":"16e6d61bf45110b6a33c3e196cafc80b1686775852827ef69a2209f2238a0085:1000197089096660878","scope":{"type":"trace"},"triggered_xact_id":1000197089096660900},"global:facet:Sentiment":{"attempts":0,"completed_xact_id":1000197089096660900,"idempotency_key":"f19a30249fa6173742ac84e4c4b1ef24539b1514f6e5355a2bc8c3ae0fc70fdd:1000197089096660878","scope":{"type":"trace"},"triggered_xact_id":1000197089096660900},"global:facet:Task":{"attempts":0,"completed_xact_id":1000197089096660900,"idempotency_key":"c3641895395e27f163e2cfdadee1f579400df2a90ae7d3ac90ffb2e6856db8ec:1000197089096660878","scope":{"type":"trace"},"triggered_xact_id":1000197089096660900}}},"_pagination_key":"p07634737148730408965","_xact_id":"1000197089099609620","audit_data":[{"_xact_id":"1000197089099609620","audit_data":{"action":"merge","from":null,"path":["facets"],"to":{"Issues":"no_match","Sentiment":"no_match","Task":"User wants to count numbers from 1 to 10 at a slow pace."}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T02:00:02.584Z","error":null,"expected":null,"facets":{"Issues":"no_match","Sentiment":"no_match","Task":"User wants to count numbers from 1 to 10 at a slow pace."},"id":"7b15f9b873170be44bf1d98569c750c432ce567b4a78f4d5a1077ded17b71967","input":null,"is_root":false,"log_id":"g","metadata":null,"metrics":null,"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":null,"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"89c113ac73753d523d7c41d23f6ca551","scores":null,"span_attributes":{"name":"_topicsAutomation","purpose":"scorer","type":"automation"},"span_id":"7b15f9b873170be44bf1d98569c750c432ce567b4a78f4d5a1077ded17b71967","span_parents":["7990f83f49955e5c"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737148730408965","_xact_id":"1000197089099609620","audit_data":[{"_xact_id":"1000197089099138538","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089099138666","audit_data":{"action":"merge","from":null,"path":["input"],"to":{}},"metadata":{},"source":"api"},{"_xact_id":"1000197089099609620","audit_data":{"action":"merge","path":["output"]},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{},"created":"2026-05-01T02:00:02.655Z","error":null,"expected":null,"facets":null,"id":"383a51b0-3cc0-4daf-8a87-2f2b2107c268","input":{},"is_root":false,"log_id":"g","metadata":null,"metrics":{"end":1777600809.507,"start":1777600802.655},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"facets":{"Issues":"no_match","Sentiment":"no_match","Task":{"embedding_model":"brain-embedding-1","facet":"User wants to count numbers from 1 to 10 at a slow pace.","vector":"vector[1024]"}},"kind":"facet_with_topic_maps","topic_map_classifications":[]},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"89c113ac73753d523d7c41d23f6ca551","scores":null,"span_attributes":{"exec_counter":34384,"name":"Pipeline","purpose":"scorer","remote":true,"skip_realtime":true,"slug":"inline_function_batched_facet","type":"facet"},"span_id":"b19c2cf2-41be-4bd4-9001-8bb79d04ec91","span_parents":["7b15f9b873170be44bf1d98569c750c432ce567b4a78f4d5a1077ded17b71967"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737148730408965","_xact_id":"1000197089099609620","audit_data":[{"_xact_id":"1000197089099205131","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089099474629","audit_data":{"action":"merge","from":null,"path":["span_attributes"],"to":{"name":"Chat Completion"}},"metadata":{},"source":"api"},{"_xact_id":"1000197089099609426","audit_data":{"action":"merge","from":null,"path":["metrics"],"to":{"retries":0}},"metadata":{},"source":"api"},{"_xact_id":"1000197089099609620","audit_data":{"action":"merge","from":null,"path":["metrics"],"to":{"completion_tokens":832,"end":1777600809.501,"prompt_tokens":2147,"time_to_first_token":6.075999975204468,"tokens":2979}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{"caller_filename":"node:internal/process/task_queues","caller_functionname":"process.processTicksAndRejections","caller_lineno":104},"created":"2026-05-01T02:00:03.423Z","error":null,"expected":null,"facets":null,"id":"a4ba2592-d457-4e6b-bbd6-9d22ce8db374","input":[{"content":"You are an analyst extracting structured information from AI conversations.\n\nPRIVACY REQUIREMENTS (critical):\n- Do NOT include any personally identifiable information (PII): names, locations, phone numbers, email addresses, usernames, or any other identifying details.\n- Do NOT include any proper nouns (company names, product names, people's names, place names, etc.).\n- Replace specific identifiers with generic descriptions (e.g., \"a technology company\" instead of company names).\n\nANALYSIS GUIDELINES:\n- Be descriptive and assume neither good nor bad faith.\n- Do not hesitate to identify and describe socially harmful or sensitive topics specifically; specificity around potentially harmful conversations is necessary for effective monitoring.\n- If you see truncation markers like \"[...]\" or \"[middle truncated]\", assume the text was clipped for length. Do NOT treat truncation alone as a problem unless the visible text clearly shows one.\n- Tool summaries (lines starting with \"Tool (\") are internal context; do NOT penalize their presence or the absence of full tool details.","role":"system"},{"content":"Here is the data to analyze:\n\nUser:\n Count from 1 to 10 slowly.\n\nAssistant:\n Sure! Here we go:\n \n 1... \n 2... \n 3... \n 4... \n 5... \n 6... \n 7... \n 8... \n 9... \n 10... \n \n There you have it!","role":"user"}],"is_root":false,"log_id":"g","metadata":{"max_tokens":20000,"model":"brain-facet-latest","stream":false,"suffix_messages":[[{"content":"What is the user's overall request or goal in this conversation?\n\nRespond with a single sentence starting with \"User wants to...\"\n\nFocus on the high-level intent, not specific details. If multiple requests, describe the main one.\n\nExamples:\n- \"User wants to debug why their API calls are returning errors\"\n- \"User wants to create a new LLM-based evaluation scorer\"\n- \"User wants to understand how to interpret experiment results\"\n- \"User wants to optimize their prompt for better accuracy\"\n\nIf no clear request is present, respond: \"NONE\"\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}],[{"content":"Classify the user's overall sentiment toward the interaction. Do not describe the use case, only the user's sentiment.\n\nConsider:\n- Negative: frustration, confusion, dissatisfaction, impatience, giving up\n- Positive: satisfaction, gratitude, praise\n- Neutral: factual, no clear emotional valence\n- Mixed: both positive and negative signals\n\nUse these exact labels (title case):\n- Negative\n- Neutral\n- Positive\n- Mixed\n\nAfter the label, add a brief reason in 1 sentence.\n\nExamples:\n- \"Negative. User complained the instructions still don't work.\"\n- \"Positive. User thanked the assistant for solving the issue.\"\n- \"Neutral. User asked for a definition without emotional language.\"\n- \"Mixed. User was frustrated earlier but later expressed thanks.\"\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}],[{"content":"Review this AI assistant conversation for clear problems.\n\nMost conversations are fine. Only flag when you are fully certain an issue occurred.\n\nOutput format:\n- \"NONE\" if conversation is normal\n- \". <1-2 sentence explanation of what specifically went wrong>\" if absolutely certain\n\nUse these exact category labels (title case): No response, Confused, Lazy, Incomplete, Leaked reasoning.\n\nImportant: Every non-NONE output must include a specific explanation. Do not output only \"No response\" - explain why (e.g., \"No response. User asked about quarterly revenue but assistant only ran a query and never provided the answer\").\n\nNo response\nOnly flag if all of these are true:\n1. User asked a question or requested something\n2. Assistant used tools to gather information\n3. The final message is a tool result with no assistant reply after it\n4. The user is clearly left without an answer\n\nDo not flag No response if:\n- There's any assistant message after the tool result\n- The conversation is still in progress\n- User's last message was just providing context (not asking)\n- Assistant asked a clarifying question\n- There are tool failures but the assistant still provides a usable fallback or final answer\n\nOther categories:\n- Confused: answered wrong question entirely\n- Lazy: refused without trying\n- Incomplete: response cut off mid-sentence\n- Leaked reasoning: assistant shares its internal thought process in tags or similar\n\nTruncation guidance:\nThis conversation log may contain truncated content marked with \"[... truncated ...]\", \"[middle truncated]\", \"...\", or similar. Tool call outputs are often shortened for display.\n\nDo not flag issues caused by truncation:\n- If you can't see full tool output, assume it was complete\n- If assistant references data you can't see, it was likely in the truncated portion\n- Missing context due to truncation is NOT a problem\n\nNormal (always NONE):\n- Single/intermittent tool errors where the assistant still provides a usable answer or fallback\n- Verbose/detailed responses\n- Multiple attempts\n- Clarifying questions\n- Truncation markers\n- Assistant referencing data that may have been truncated\n\nWhen in doubt, say NONE.\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}]]},"metrics":{"completion_tokens":832,"end":1777600809.501,"prompt_tokens":2147,"retries":0,"start":1777600803.423,"time_to_first_token":6.075999975204468,"tokens":2979},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's see. The user asked to count from 1 to 10 slowly. The assistant responded by counting each number with a pause after each, then confirming the count. The user's request here is pretty straightforward. They wanted a slow count, maybe to practice counting, or perhaps for a child learning numbers. The main goal is to have the numbers counted one by one, not just a quick list. The assistant did exactly that, so the user's overall request is to have a slow, deliberate counting from 1 to 10. No hidden requests or additional goals here. Just a simple counting task. So the answer should reflect that the user wants to count numbers from 1 to 10 at a slow pace.\n\n\nUser wants to count numbers from 1 to 10 at a slow pace.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}},{"finish_reason":"stop","index":1,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's see. The user asked to count from 1 to 10 slowly. The assistant responded by counting each number with a pause, then confirming completion. The user's message is straightforward, just a simple counting task. The assistant's response is methodical and follows the instruction as given. \n\nNow, I need to determine the user's sentiment. The user didn't express any frustration or dissatisfaction. They just provided a clear request, and the assistant fulfilled it. There's no indication of impatience or confusion. The user might be testing the assistant's ability to follow instructions, but there's no negative feedback. The assistant's response is neutral in tone, just executing the task without any extra elements. \n\nSince the user's message is factual and there's no emotional language, the sentiment is likely neutral. The user didn't show any positive or negative emotions, just a straightforward request. So the classification should be Neutral. The reason would be that the user's interaction was factual without emotional cues.\n\n\nNeutral. The user's interaction was factual and straightforward without emotional cues.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}},{"finish_reason":"stop","index":2,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's take a look at this conversation. The user asked the assistant to count from 1 to 10 slowly. The assistant responded by counting each number with a pause, then concluded with \"There you have it!\" \n\nFirst, I need to check if there's any issue here. The user's request was straightforward, and the assistant provided a clear, complete response. Each number was counted with a pause, which matches the user's instruction. The assistant didn't use any tools here; they just gave a direct answer. \n\nLooking at the categories: No response would apply if the assistant used tools but didn't provide an answer. But in this case, the assistant didn't use any tools. The response is fully formed and answers the question. There's no truncation or incomplete sentences. The assistant didn't show any confusion or laziness. \n\nSince the conversation is complete and the assistant answered correctly without any issues, the appropriate response is NONE. There's no leaking of reasoning, and the user isn't left without an answer. Everything seems normal here.\n\n\nNONE \nThe assistant provided a complete, accurate response to the user's request, counting from 1 to 10 with clear pauses as instructed. No tools were used, and the conversation concluded with a satisfactory answer.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"89c113ac73753d523d7c41d23f6ca551","scores":null,"span_attributes":{"exec_counter":34385,"name":"Chat Completion","purpose":"scorer","skip_realtime":true,"type":"llm"},"span_id":"2b0d6ea8-0acb-40ea-93b3-c5f057c60a39","span_parents":["b19c2cf2-41be-4bd4-9001-8bb79d04ec91"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737148730408965","_xact_id":"1000197089099609620","audit_data":[{"_xact_id":"1000197089099609620","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{"caller_filename":"node:internal/process/task_queues","caller_functionname":"process.processTicksAndRejections","caller_lineno":104},"created":"2026-05-01T02:00:09.502Z","error":null,"expected":null,"facets":null,"id":"845d476c-47c5-4fa6-821e-b837fe7e0f1f","input":{"input":["User wants to count numbers from 1 to 10 at a slow pace."],"model":"brain-embedding-1"},"is_root":false,"log_id":"g","metadata":{"model":"brain-embedding-1"},"metrics":{"cached":1,"end":1777600809.505,"prompt_tokens":16,"start":1777600809.502,"tokens":16},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"embedding_length":1024},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"89c113ac73753d523d7c41d23f6ca551","scores":null,"span_attributes":{"exec_counter":34396,"name":"Embedding","purpose":"scorer","skip_realtime":true,"type":"llm"},"span_id":"276622b7-7365-4132-a0d9-a71766f47c68","span_parents":["b19c2cf2-41be-4bd4-9001-8bb79d04ec91"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-68d639c0-1a36-4b09-835d-70676d8777ed.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-68d639c0-1a36-4b09-835d-70676d8777ed.json new file mode 100644 index 00000000..18ff453c --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-68d639c0-1a36-4b09-835d-70676d8777ed.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737223253753864","_xact_id":"1000197089097798014","audit_data":[{"_xact_id":"1000197089097798014","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:38.791Z","error":null,"expected":null,"facets":null,"id":"4f11142b15faad18","input":[{"content":"you are a helpful assistant","role":"system"},{"content":"What is the capital of France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":7,"end":1777600779.596868,"prompt_tokens":23,"start":1777600778.7919571,"tokens":30},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The capital of France is Paris.","refusal":null,"role":"assistant"}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"b22a7064d957f9d37dc9370205a0149a","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"4f11142b15faad18","span_parents":["06e0e45d8856417f"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-7bb21f42-8a57-4177-82cd-1016209bfd11.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-7bb21f42-8a57-4177-82cd-1016209bfd11.json new file mode 100644 index 00000000..acc0e872 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-7bb21f42-8a57-4177-82cd-1016209bfd11.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737223253753865","_xact_id":"1000197089097798014","audit_data":[{"_xact_id":"1000197089097798014","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:39.600Z","error":null,"expected":null,"facets":null,"id":"8e6a9a119155da12","input":[{"content":"you are a helpful assistant","role":"system"},{"content":"What is the capital of France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":7,"end":1777600780.4176633,"prompt_tokens":23,"start":1777600779.6005049,"tokens":30},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The capital of France is Paris.","refusal":null,"role":"assistant"}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"3d0117e321817e50077da93b401b4dff","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"8e6a9a119155da12","span_parents":["804c420d6d314d73"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-7ca662d0-05aa-47f5-b902-3b99403706e1.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-7ca662d0-05aa-47f5-b902-3b99403706e1.json new file mode 100644 index 00000000..bf5e4a03 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-7ca662d0-05aa-47f5-b902-3b99403706e1.json @@ -0,0 +1 @@ +{"Code":"TooManyRequestsError","Message":"Too many requests. Source: checkBtqlOrgRateLimit. Rate limit: 20 requests per 60 seconds. Consumed: 22. Retry after 18.379 seconds. Please contact us at support@braintrust.dev to discuss remediation strategies. [user_email=andrew@braintrustdata.com] [user_org=braintrustdata.com] [timestamp=1777600882.516]","InternalTraceId":"69f409720000000079c92d615c91ea50","Path":"/btql","Service":"api"} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-84ead815-40e5-4d81-8263-f22066d46681.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-84ead815-40e5-4d81-8263-f22066d46681.json new file mode 100644 index 00000000..0f805f3d --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-84ead815-40e5-4d81-8263-f22066d46681.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737175035707400","_xact_id":"1000197089097062265","audit_data":[{"_xact_id":"1000197089097062265","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:25.853Z","error":null,"expected":null,"facets":null,"id":"b6fd05334dec8b13","input":[{"content":"What is the capital of France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-sonnet-4-5-20250929","provider":"anthropic","request_base_uri":"http://localhost:43061","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":5,"end":1777600766.9284341,"prompt_cache_creation_1h_tokens":0,"prompt_cache_creation_5m_tokens":1368,"prompt_cached_tokens":0,"prompt_tokens":12,"start":1777600765.8538582,"tokens":17},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"Paris.","type":"text"}],"id":"msg_01Ht97jZANBVHrptFNVGBPih","model":"claude-sonnet-4-5-20250929","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":1368},"cache_creation_input_tokens":1368,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":12,"output_tokens":5,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"149b4aa496d877681ef62fc9dd6d92b8","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"b6fd05334dec8b13","span_parents":["1a95ecaf5eb2bb3a"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":5647,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101435631","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-8a4abae2-50b8-4353-a6be-48a0b86534d7.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-8a4abae2-50b8-4353-a6be-48a0b86534d7.json new file mode 100644 index 00000000..3193f539 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-8a4abae2-50b8-4353-a6be-48a0b86534d7.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737196982272009","_xact_id":"1000197089097397143","audit_data":[{"_xact_id":"1000197089097397143","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:16.594Z","error":null,"expected":null,"facets":null,"id":"956e8ffae8040082","input":[{"content":"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\n","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"o4-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"responses"},"metrics":{"completion_reasoning_tokens":1088,"completion_tokens":1326,"end":1777600773.966828,"prompt_tokens":41,"start":1777600756.5941665,"tokens":1367},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"id":"rs_02227da51c3fd2580069f408f556408196b2db61e732ad86a6","summary":[{"text":"**Analyzing a number sequence**\n\nThe user provided the sequence: 2, 6, 12, 20, 30, and I'm trying to find the pattern and formula for the nth term. I notice this sequence seems to be twice the triangular numbers, which are generated by the formula n(n+1)/2. When I apply that, I see that each term corresponds to the triangular number multiplied by 2. Additionally, the differences suggest it's a quadratic sequence, confirming the numbers are pronic numbers, products of consecutive integers.","type":"summary_text"},{"text":"**Finding the term formula**\n\nThe formula for the sequence is a_n = n(n + 1). When starting from n=1, I see it gives the first term, 2. The differences between terms increase by 2 each time, confirming they are pronic numbers. By breaking it down further, I realize these can also be expressed as twice the triangular numbers. The difference sequence is 4, 6, 8, 10, showing it's quadratic. Ultimately, I conclude: a_n = n(n + 1) for the sequence 2, 6, 12, 20, 30.","type":"summary_text"},{"text":"**Summarizing the sequence pattern**\n\nThe pattern in this sequence is found in the successive differences, which are even numbers: 4, 6, 8, 10. This leads to the conclusion that a_n = n^2 + n, or more simply, a_n = n(n + 1). Although there's a consideration for starting at n=0, it typically begins at n=1. I can also express it as twice the triangular numbers: a_n = 2T_n. Ultimately, the answer is a_n = n(n + 1) for the terms 2, 6, 12, and so on.","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"The “gaps” between terms are \n 6−2=4, 12−6=6, 20−12=8, 30−20=10, … \ni.e. the differences are 4, 6, 8, 10, … so the second difference is constant (2) and the sequence is quadratic. Solving or noting that it’s twice the triangular numbers gives\n\n aₙ = 2·(n(n+1)/2) = n(n+1).\n\nIf you start counting at n=1 this indeed yields \n a₁ = 1·2 = 2, \n a₂ = 2·3 = 6, \n a₃ = 3·4 = 12, … \n\nSo the nth term is aₙ = n(n+1).","type":"output_text"}],"id":"msg_02227da51c3fd2580069f40902d7ec81968d11d9124bb4043e","role":"assistant","status":"completed","type":"message"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"7beca5cbceb213d06e52458a8efbd6a6","scores":null,"span_attributes":{"name":"responses","type":"llm"},"span_id":"956e8ffae8040082","span_parents":["07702bb85c99aa18"],"tags":null},{"_async_scoring_state":null,"_pagination_key":"p07634737267181289473","_xact_id":"1000197089098468295","audit_data":[{"_xact_id":"1000197089098468295","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:34.046Z","error":null,"expected":null,"facets":null,"id":"dee24e9a69a362ae","input":[{"content":"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\n","role":"user"},{"id":"rs_02227da51c3fd2580069f408f556408196b2db61e732ad86a6","summary":[{"text":"**Analyzing a number sequence**\n\nThe user provided the sequence: 2, 6, 12, 20, 30, and I'm trying to find the pattern and formula for the nth term. I notice this sequence seems to be twice the triangular numbers, which are generated by the formula n(n+1)/2. When I apply that, I see that each term corresponds to the triangular number multiplied by 2. Additionally, the differences suggest it's a quadratic sequence, confirming the numbers are pronic numbers, products of consecutive integers.","type":"summary_text"},{"text":"**Finding the term formula**\n\nThe formula for the sequence is a_n = n(n + 1). When starting from n=1, I see it gives the first term, 2. The differences between terms increase by 2 each time, confirming they are pronic numbers. By breaking it down further, I realize these can also be expressed as twice the triangular numbers. The difference sequence is 4, 6, 8, 10, showing it's quadratic. Ultimately, I conclude: a_n = n(n + 1) for the sequence 2, 6, 12, 20, 30.","type":"summary_text"},{"text":"**Summarizing the sequence pattern**\n\nThe pattern in this sequence is found in the successive differences, which are even numbers: 4, 6, 8, 10. This leads to the conclusion that a_n = n^2 + n, or more simply, a_n = n(n + 1). Although there's a consideration for starting at n=0, it typically begins at n=1. I can also express it as twice the triangular numbers: a_n = 2T_n. Ultimately, the answer is a_n = n(n + 1) for the terms 2, 6, 12, and so on.","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"The “gaps” between terms are \n 6−2=4, 12−6=6, 20−12=8, 30−20=10, … \ni.e. the differences are 4, 6, 8, 10, … so the second difference is constant (2) and the sequence is quadratic. Solving or noting that it’s twice the triangular numbers gives\n\n aₙ = 2·(n(n+1)/2) = n(n+1).\n\nIf you start counting at n=1 this indeed yields \n a₁ = 1·2 = 2, \n a₂ = 2·3 = 6, \n a₃ = 3·4 = 12, … \n\nSo the nth term is aₙ = n(n+1).","type":"output_text"}],"id":"msg_02227da51c3fd2580069f40902d7ec81968d11d9124bb4043e","role":"assistant","status":"completed","type":"message"},{"content":"Using the pattern you discovered, what would be the 10th term? And can you find the sum of the first 10 terms?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"o4-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"responses"},"metrics":{"completion_reasoning_tokens":448,"completion_tokens":696,"end":1777600790.2475226,"prompt_tokens":258,"start":1777600774.0466774,"tokens":954},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"id":"rs_02227da51c3fd2580069f4090796e88196977cb3ecce9d9545","summary":[{"text":"**Calculating the 10th term and the sum**\n\nThe user wants to know the 10th term of the sequence and the sum of the first 10 terms. From our earlier work, we've figured out that the 10th term is a_{10} = 10 * 11 = 110. \n\nFor the sum of the first 10 terms, we can calculate it directly, finding that the result is 440. Alternatively, we discovered a neat formula for the sum of the first n terms, which also gives 440 when n=10. So, the final answers are: 10th term = 110 and sum of first 10 terms = 440.","type":"summary_text"},{"text":"**Deriving the 10th term and sum**\n\nLet's show the derivation clearly. The formula for the nth term is a_n = n(n+1). So, for the 10th term, we calculate a_{10} = 10 * 11 = 110. \n\nFor the sum S_10 of the first 10 terms, we have S_10 = ∑n(n+1), which breaks down into ∑n^2 + ∑n = 385 + 55 = 440. Also, I can provide the general formula for the sum: ∑_{k=1}^n k(k+1) = n(n+1)(n+2)/3. For n=10, we find 10*11*12/3 = 440. So the answers are: 10th term = 110, sum of first 10 = 440.","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"The nth term is \n aₙ = n(n + 1). \n\nSo for n = 10: \n a₁₀ = 10·11 = 110. \n\nThe sum of the first 10 terms is \n S₁₀ = ∑ₖ₌₁¹⁰ k(k + 1) \n = ∑ₖ₌₁¹⁰ (k² + k) \n = (∑ₖ₌₁¹⁰ k²) + (∑ₖ₌₁¹⁰ k) \n = [10·11·21/6] + [10·11/2] \n = 385 + 55 \n = 440. \n\nEquivalently, one can use the closed‐form \n ∑ₖ₌₁ⁿ k(k + 1) = n(n + 1)(n + 2)/3 \nso for n=10: 10·11·12/3 = 440.","type":"output_text"}],"id":"msg_02227da51c3fd2580069f40914c23c8196978bc528f6c80fdc","role":"assistant","status":"completed","type":"message"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"7beca5cbceb213d06e52458a8efbd6a6","scores":null,"span_attributes":{"name":"responses","type":"llm"},"span_id":"dee24e9a69a362ae","span_parents":["07702bb85c99aa18"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-8d2c104c-cb77-4f66-b566-f070e2bc9f89.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-8d2c104c-cb77-4f66-b566-f070e2bc9f89.json new file mode 100644 index 00000000..976e4358 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-8d2c104c-cb77-4f66-b566-f070e2bc9f89.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737148730408967","_xact_id":"1000197089096660878","audit_data":[{"_xact_id":"1000197089096660878","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:18.609Z","error":null,"expected":null,"facets":null,"id":"a7705f44cf442902","input":[{"content":"What is the weather like in Paris, France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":16,"end":1777600759.4526403,"prompt_tokens":85,"start":1777600758.6096172,"tokens":101},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"tool_calls","index":0,"logprobs":null,"message":{"annotations":[],"content":null,"refusal":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"location\":\"Paris, France\"}","name":"get_weather"},"id":"call_Ofi6sZkZDF4MMSmfW85yFIct","type":"function"}]}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"34deba1a2c0490369061ced793f8f991","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"a7705f44cf442902","span_parents":["aa7fe32ffa96623e"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-919e3b25-ee0e-498b-af81-d38877cc3168.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-919e3b25-ee0e-498b-af81-d38877cc3168.json new file mode 100644 index 00000000..c3316bbb --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-919e3b25-ee0e-498b-af81-d38877cc3168.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737196982272010","_xact_id":"1000197089097397143","audit_data":[{"_xact_id":"1000197089097397143","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:33.793Z","error":null,"expected":null,"facets":null,"id":"908db85e83e14d7f","input":[{"content":[{"text":"What color is this image?","type":"text"},{"source":{"content_type":"image/png","filename":"file.png","key":"fb3c08d7-4aab-4c43-82a0-9f5ca398a871","type":"braintrust_attachment"},"type":"image"}],"role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-haiku-4-5-20251001","provider":"anthropic","request_base_uri":"","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":26,"end":1777600775.2603805,"prompt_cache_creation_1h_tokens":0,"prompt_cache_creation_5m_tokens":0,"prompt_cached_tokens":0,"prompt_tokens":17,"start":1777600773.7933228,"tokens":43},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"This image is **red**. It appears to be a small red dot or circular shape on a white background.","type":"text"}],"id":"msg_01EAd8ou9F4TJE3R2qqBvY2o","model":"claude-haiku-4-5-20251001","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":17,"output_tokens":26,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"88bd25a8c8635a467403a42dce1462c8","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"908db85e83e14d7f","span_parents":["fb2806797a389a2d"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":0,"actual_xact_id":"1000197089101435631"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101435631","last_considered_xact_id":"1000197089101435631"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-9c8e4d4a-daef-4397-bfcb-20703d1d6859.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-9c8e4d4a-daef-4397-bfcb-20703d1d6859.json new file mode 100644 index 00000000..ef7f4825 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-9c8e4d4a-daef-4397-bfcb-20703d1d6859.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737175035707402","_xact_id":"1000197089097062265","audit_data":[{"_xact_id":"1000197089097062265","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:27.887Z","error":null,"expected":null,"facets":null,"id":"9261b3dbfaa67ac7","input":[{"content":"What is the capital of France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-sonnet-4-5-20250929","provider":"anthropic","request_base_uri":"http://localhost:43061","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":11,"end":1777600768.9023066,"prompt_cache_creation_1h_tokens":1993,"prompt_cache_creation_5m_tokens":0,"prompt_cached_tokens":0,"prompt_tokens":12,"start":1777600767.8874676,"tokens":23},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"The capital of France is **Paris**.","type":"text"}],"id":"msg_01Q1j91FENjcUVMaZpCEiQtJ","model":"claude-sonnet-4-5-20250929","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":1993,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":1993,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":12,"output_tokens":11,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"d880dd4d4fc907c09a02acfd596e11d6","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"9261b3dbfaa67ac7","span_parents":["4165a305865135f9"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":0,"actual_xact_id":"1000197089101435631"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101435631","last_considered_xact_id":"1000197089101435631"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-9e3a9f16-cf95-4834-940b-8693fe3a272d.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-9e3a9f16-cf95-4834-940b-8693fe3a272d.json new file mode 100644 index 00000000..aae1d0df --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-9e3a9f16-cf95-4834-940b-8693fe3a272d.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737148730408961","_xact_id":"1000197089096660878","audit_data":[{"_xact_id":"1000197089096660878","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:20.261Z","error":null,"expected":null,"facets":null,"id":"941dcb27bb1446ed","input":[{"content":[{"text":"count to 10 slowly","type":"text"}],"role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","endpoint":"converse-stream","model":"us.amazon.nova-lite-v1:0","provider":"bedrock","request_base_uri":"http://localhost","request_method":"POST","request_path":"model/us.amazon.nova-lite-v1%3A0/converse-stream"},"metrics":{"completion_tokens":52,"end":1777600761.6426585,"prompt_tokens":6,"start":1777600760.2615554,"time_to_first_token":0.009945402,"tokens":58},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"content":[{"text":"Sure, I'll count to 10 slowly for you:\n\n1... \n2...\n3...\n4...\n5...\n6...\n7...\n8...\n9...\n10...\n\nThere you go! If you need anything else, feel free to ask.","type":"text"}],"role":"assistant"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"bf72462c6e1fefc71baff40f7ba09c0f","scores":null,"span_attributes":{"name":"bedrock.converse-stream","type":"llm"},"span_id":"941dcb27bb1446ed","span_parents":["2453a8e6f0c4f843"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-a8bba708-a70d-4fac-8923-59dd75e076d7.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-a8bba708-a70d-4fac-8923-59dd75e076d7.json new file mode 100644 index 00000000..67e960af --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-a8bba708-a70d-4fac-8923-59dd75e076d7.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737426181455872","_xact_id":"1000197089100894445","audit_data":[{"_xact_id":"1000197089100894445","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T02:00:08.907Z","error":null,"expected":null,"facets":null,"id":"381a9d6e0ac4fe8d","input":[{"content":"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\n","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"o4-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"responses"},"metrics":{"completion_reasoning_tokens":1408,"completion_tokens":1611,"end":1777600828.3396459,"prompt_tokens":41,"start":1777600808.907258,"tokens":1652},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"id":"rs_058f35ee350a999b0069f40929ac388193b9568cdf70b02b54","summary":[{"text":"**Analyzing a number sequence**\n\nThe user presented me with a sequence: 2, 6, 12, 20, 30. I'm trying to find the pattern and a formula for the nth term. It looks like these numbers correspond to triangular numbers multiplied by 2. In fact, they follow the formula: n(n + 1) which simplifies to n^2 + n. Just to clarify, triangular numbers follow the formula T_n = n(n + 1)/2. Based on this, I see that the given sequence is essentially twice each triangular number.","type":"summary_text"},{"text":"**Clarifying the sequence pattern**\n\nI'm breaking down the sequence 2, 6, 12, 20, 30. I see now that it equals 2 times the triangular numbers: 2 = 2×1, 6 = 2×3, etc. The formula for the nth term is a_n = n(n + 1), and it can also be described by observing the differences between terms: 4, 6, 8, 10, which increase by 2 each time. This consistency indicates it's a quadratic sequence. The final conclusion is that the pattern represents rectangular numbers, confirming the formula is a_n = n(n + 1).","type":"summary_text"},{"text":"**Solving for the sequence**\n\nI’m working on the sequence and setting up equations based on the relationships I see. I've established that b can be expressed in terms of a and derived equations that simplify down to a = 1 and b = 1, with c equaling 0. So, I've determined the nth term formula is a_n = n(n + 1), which reveals the pattern of pronic numbers, being the product of two consecutive integers, specifically: 2, 6, 12, 20, 30... Just to clarify, the final formula using indexing from 1 is a_n = n(n + 1).","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"The differences between successive terms are\n\n 6–2 = 4, \n12–6 = 6, \n20–12 = 8, \n30–20 = 10, \n\nso the “step‐sizes” are the even numbers 4,6,8,10,… (i.e. they increase by 2 each time). Any sequence whose second difference is constant is a quadratic, and in fact one checks that\n\n 2 = 1·2, \n 6 = 2·3, \n12 = 3·4, \n20 = 4·5, \n30 = 5·6,\n\nso the nth term is the product of two consecutive integers. If we start counting at n=1, the formula is\n\n aₙ = n (n + 1) = n² + n.","type":"output_text"}],"id":"msg_058f35ee350a999b0069f4093af15481939783e600a43f5133","role":"assistant","status":"completed","type":"message"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"1180ea2e316c253b507c3168d0ed1314","scores":null,"span_attributes":{"name":"responses","type":"llm"},"span_id":"381a9d6e0ac4fe8d","span_parents":["f8c742474ac79bd0"],"tags":null},{"_async_scoring_state":null,"_pagination_key":"p07634737492595376129","_xact_id":"1000197089101907841","audit_data":[{"_xact_id":"1000197089101907841","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T02:00:28.358Z","error":null,"expected":null,"facets":null,"id":"ada981f556325b0f","input":[{"content":"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\n","role":"user"},{"id":"rs_058f35ee350a999b0069f40929ac388193b9568cdf70b02b54","summary":[{"text":"**Analyzing a number sequence**\n\nThe user presented me with a sequence: 2, 6, 12, 20, 30. I'm trying to find the pattern and a formula for the nth term. It looks like these numbers correspond to triangular numbers multiplied by 2. In fact, they follow the formula: n(n + 1) which simplifies to n^2 + n. Just to clarify, triangular numbers follow the formula T_n = n(n + 1)/2. Based on this, I see that the given sequence is essentially twice each triangular number.","type":"summary_text"},{"text":"**Clarifying the sequence pattern**\n\nI'm breaking down the sequence 2, 6, 12, 20, 30. I see now that it equals 2 times the triangular numbers: 2 = 2×1, 6 = 2×3, etc. The formula for the nth term is a_n = n(n + 1), and it can also be described by observing the differences between terms: 4, 6, 8, 10, which increase by 2 each time. This consistency indicates it's a quadratic sequence. The final conclusion is that the pattern represents rectangular numbers, confirming the formula is a_n = n(n + 1).","type":"summary_text"},{"text":"**Solving for the sequence**\n\nI’m working on the sequence and setting up equations based on the relationships I see. I've established that b can be expressed in terms of a and derived equations that simplify down to a = 1 and b = 1, with c equaling 0. So, I've determined the nth term formula is a_n = n(n + 1), which reveals the pattern of pronic numbers, being the product of two consecutive integers, specifically: 2, 6, 12, 20, 30... Just to clarify, the final formula using indexing from 1 is a_n = n(n + 1).","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"The differences between successive terms are\n\n 6–2 = 4, \n12–6 = 6, \n20–12 = 8, \n30–20 = 10, \n\nso the “step‐sizes” are the even numbers 4,6,8,10,… (i.e. they increase by 2 each time). Any sequence whose second difference is constant is a quadratic, and in fact one checks that\n\n 2 = 1·2, \n 6 = 2·3, \n12 = 3·4, \n20 = 4·5, \n30 = 5·6,\n\nso the nth term is the product of two consecutive integers. If we start counting at n=1, the formula is\n\n aₙ = n (n + 1) = n² + n.","type":"output_text"}],"id":"msg_058f35ee350a999b0069f4093af15481939783e600a43f5133","role":"assistant","status":"completed","type":"message"},{"content":"Using the pattern you discovered, what would be the 10th term? And can you find the sum of the first 10 terms?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"o4-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"responses"},"metrics":{"completion_reasoning_tokens":640,"completion_tokens":880,"end":1777600840.8415549,"prompt_tokens":255,"start":1777600828.358913,"tokens":1135},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"id":"rs_058f35ee350a999b0069f4093d594881939ce2b0f0cc5fa973","summary":[{"text":"**Calculating terms and sums**\n\nThe user is asking for the 10th term and the sum of the first 10 terms based on the pattern we discovered. The nth term is calculated as a_n = n(n+1), so the 10th term a_10 comes out to be 110. \n\nTo find the sum of the first 10 terms, we break it down into the sum of squares and the sum of n. The final calculations show that the sum of the first 10 terms is 440, which combines the sum of squares (385) and the sum of n (55).","type":"summary_text"},{"text":"**Providing the answers clearly**\n\nWe can respond to the user's question directly. The 10th term, calculated from the discovered pattern, is a_10 = 10 * 11, which equals 110. The sum of the first 10 terms is 440. \n\nTo provide more clarity, I can show the steps: \n\nFirst, a_10 = 10 * 11 = 110. \n\nNext, summing the terms involves calculating Σ n(n+1) for n from 1 to 10, which gives us 440. \n\nI should also mention the general sum formula for future reference, but for now, I'll include both methods clearly in my response.","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"The nth term is aₙ = n(n+1). \nSo\n\n• The 10th term is \n a₁₀ = 10·11 = 110.\n\n• The sum of the first 10 terms is \n S₁₀ = ∑ₙ₌₁¹⁰ n(n+1) \n  = ∑n² + ∑n \n  = (10·11·21)/6 + (10·11)/2 \n  = 385 + 55 = 440. \n\nEquivalently, one can use the closed‐form \n ∑ₙ₌₁ᴺ n(n+1) = N(N+1)(N+2)/3, \nso for N=10: 10·11·12/3 = 440.","type":"output_text"}],"id":"msg_058f35ee350a999b0069f4094765f48193881242d64dc41f4f","role":"assistant","status":"completed","type":"message"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"1180ea2e316c253b507c3168d0ed1314","scores":null,"span_attributes":{"name":"responses","type":"llm"},"span_id":"ada981f556325b0f","span_parents":["f8c742474ac79bd0"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-ad59251c-c69e-43d3-b47b-df055eedaf64.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-ad59251c-c69e-43d3-b47b-df055eedaf64.json new file mode 100644 index 00000000..be028c42 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-ad59251c-c69e-43d3-b47b-df055eedaf64.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737223253753861","_xact_id":"1000197089097798014","audit_data":[{"_xact_id":"1000197089097798014","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:35.272Z","error":null,"expected":null,"facets":null,"id":"95b4cd6377fd952d","input":[{"content":"you are a helpful assistant","role":"system"},{"content":[{"text":"What color is this image?","type":"text"},{"image_url":{"url":{"content_type":"image/png","filename":"file.png","key":"6775ddbc-0aca-4bc7-a209-54399c98ff70","type":"braintrust_attachment"}},"type":"image_url"}],"role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":5,"end":1777600776.4254906,"prompt_tokens":8522,"start":1777600775.2721722,"tokens":8527},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The image is red.","refusal":null,"role":"assistant"}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"7bcf3207e4f8f95d723ef4181011ca77","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"95b4cd6377fd952d","span_parents":["d9173ac58f7c519b"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01.json new file mode 100644 index 00000000..f7c7f904 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737311097749504","_xact_id":"1000197089099138407","audit_data":[{"_xact_id":"1000197089099138407","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:22.624Z","error":null,"expected":null,"facets":null,"id":"4d861c3a81b982a3","input":[{"content":"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\n","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"o4-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"responses"},"metrics":{"completion_reasoning_tokens":1152,"completion_tokens":1286,"end":1777600799.2586358,"prompt_tokens":41,"start":1777600762.624923,"tokens":1327},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"id":"rs_0ba4648fbb2a32ab0069f408fb07e48195a99c6346663bc45a","summary":[{"text":"**Analyzing the sequence**\n\nThe user presents the sequence: 2, 6, 12, 20, 30, which corresponds to pronic or oblong numbers expressed as n(n+1). For example, 1*2=2, 2*3=6, 3*4=12, and so forth. The formula for the nth term is a(n) = n(n+1). I notice that the differences between consecutive terms (4, 6, 8, 10) are even numbers starting at 4, indicating a consistent increase. If n starts at 0, then a(n) = n(n+1), which results in 0 at n=0.","type":"summary_text"},{"text":"**Exploring the pattern of the sequence**\n\nStarting with n=1, the pattern mirrors n²+n, leading to the formula a(n) = n(n+1) for pronic numbers. The differences between terms (4, 6, 8, 10...) form an arithmetic sequence, increasing by 2 each time. So, I can clearly state that the nth term is the product of consecutive integers, with a simple alternative expression. When indexed from zero, the formula shifts. Ultimately, what stands out is that each term follows the relationship a_n = n(n+1).","type":"summary_text"},{"text":"**Defining the sequence pattern**\n\nThe sequence represents pronic numbers, where each term, starting from n=1, follows the formula a_n = n(n+1). These numbers are the products of consecutive integers: 2 as 1×2, 6 as 2×3, and 12 as 3×4. If I used a zero-based index, I'd say a_n = n(n+1) produces a_0=0, but since the sequence starts at n=1, the first term is 2. So, the final conclusion is that pronic numbers are defined by a_n = n(n+1).","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"Each term is the product of two consecutive integers:\n\n2 = 1×2 \n6 = 2×3 \n12 = 3×4 \n20 = 4×5 \n30 = 5×6 \n\nSo if you label the terms a₁, a₂, a₃, … then\n\n aₙ = n (n+1).\n\nEquivalently, aₙ = n² + n.","type":"output_text"}],"id":"msg_0ba4648fbb2a32ab0069f40919cc608195b0fb875d88fdd280","role":"assistant","status":"completed","type":"message"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"5508034ed459194168972ce4558b50d8","scores":null,"span_attributes":{"name":"responses","type":"llm"},"span_id":"4d861c3a81b982a3","span_parents":["3427c834f9d557d8"],"tags":null},{"_async_scoring_state":null,"_pagination_key":"p07634737359722708993","_xact_id":"1000197089099880365","audit_data":[{"_xact_id":"1000197089099880365","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:59.280Z","error":null,"expected":null,"facets":null,"id":"a2fbd17b690bc3c1","input":[{"content":"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\n","role":"user"},{"id":"rs_0ba4648fbb2a32ab0069f408fb07e48195a99c6346663bc45a","summary":[{"text":"**Analyzing the sequence**\n\nThe user presents the sequence: 2, 6, 12, 20, 30, which corresponds to pronic or oblong numbers expressed as n(n+1). For example, 1*2=2, 2*3=6, 3*4=12, and so forth. The formula for the nth term is a(n) = n(n+1). I notice that the differences between consecutive terms (4, 6, 8, 10) are even numbers starting at 4, indicating a consistent increase. If n starts at 0, then a(n) = n(n+1), which results in 0 at n=0.","type":"summary_text"},{"text":"**Exploring the pattern of the sequence**\n\nStarting with n=1, the pattern mirrors n²+n, leading to the formula a(n) = n(n+1) for pronic numbers. The differences between terms (4, 6, 8, 10...) form an arithmetic sequence, increasing by 2 each time. So, I can clearly state that the nth term is the product of consecutive integers, with a simple alternative expression. When indexed from zero, the formula shifts. Ultimately, what stands out is that each term follows the relationship a_n = n(n+1).","type":"summary_text"},{"text":"**Defining the sequence pattern**\n\nThe sequence represents pronic numbers, where each term, starting from n=1, follows the formula a_n = n(n+1). These numbers are the products of consecutive integers: 2 as 1×2, 6 as 2×3, and 12 as 3×4. If I used a zero-based index, I'd say a_n = n(n+1) produces a_0=0, but since the sequence starts at n=1, the first term is 2. So, the final conclusion is that pronic numbers are defined by a_n = n(n+1).","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"Each term is the product of two consecutive integers:\n\n2 = 1×2 \n6 = 2×3 \n12 = 3×4 \n20 = 4×5 \n30 = 5×6 \n\nSo if you label the terms a₁, a₂, a₃, … then\n\n aₙ = n (n+1).\n\nEquivalently, aₙ = n² + n.","type":"output_text"}],"id":"msg_0ba4648fbb2a32ab0069f40919cc608195b0fb875d88fdd280","role":"assistant","status":"completed","type":"message"},{"content":"Using the pattern you discovered, what would be the 10th term? And can you find the sum of the first 10 terms?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"o4-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"responses"},"metrics":{"completion_reasoning_tokens":768,"completion_tokens":951,"end":1777600808.882529,"prompt_tokens":168,"start":1777600799.2805033,"tokens":1119},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"id":"rs_0ba4648fbb2a32ab0069f4091f9f188195a624ad60550d7b6e","summary":[{"text":"**Calculating sequence terms and sums**\n\nThe user is asking for the 10th term and the sum of the first 10 terms of the sequence defined as a_n = n(n+1). I find that the 10th term is 110. For the sum of the first 10 terms, I calculate it as S = sum of n^2 + sum of n, which gives me 440. So, the 10th term is 110, and the sum of the first 10 terms is 440.","type":"summary_text"},{"text":"**Calculating the 10th term and sum of terms**\n\nI’m providing the 10th term and the sum of the first 10 terms of the sequence defined as a_n = n(n+1). The 10th term is a_10 = 10 × 11 = 110. For the sum of the first 10 terms, I calculate it as S = ∑n(n+1) = 440, using either the direct sums (385 + 55) or the closed form formula. So the answers are: the 10th term is 110 and the sum of the first 10 terms is 440.","type":"summary_text"}],"type":"reasoning"},{"content":[{"annotations":[],"logprobs":[],"text":"The 10th term is \n a₁₀ = 10·(10+1) = 10·11 = 110. \n\nThe sum of the first 10 terms is \n S₁₀ = ∑ₙ₌₁¹⁰ n(n+1) = ∑ₙ₌₁¹⁰ n² + ∑ₙ₌₁¹⁰ n \n = (10·11·21)/6 + (10·11)/2 \n = 385 + 55 \n = 440. \n\nEquivalently, one can use the closed‐form \n Sₙ = n(n+1)(n+2)/3 \nso \n S₁₀ = 10·11·12/3 = 440.","type":"output_text"}],"id":"msg_0ba4648fbb2a32ab0069f40927cd7881958c2700550d4a1619","role":"assistant","status":"completed","type":"message"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"5508034ed459194168972ce4558b50d8","scores":null,"span_attributes":{"name":"responses","type":"llm"},"span_id":"a2fbd17b690bc3c1","span_parents":["3427c834f9d557d8"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c.json new file mode 100644 index 00000000..fe4c7675 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737175035707403","_xact_id":"1000197089097062265","audit_data":[{"_xact_id":"1000197089097062265","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:28.926Z","error":null,"expected":null,"facets":null,"id":"536617a74e48d587","input":[{"content":"What is the capital of France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-sonnet-4-5-20250929","provider":"anthropic","request_base_uri":"","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":5,"end":1777600770.0637643,"prompt_cache_creation_1h_tokens":0,"prompt_cache_creation_5m_tokens":1365,"prompt_cached_tokens":0,"prompt_tokens":12,"start":1777600768.9263048,"tokens":17},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"text":"Paris.","type":"text"}],"id":"msg_01LgFN9spggTY8EpJU7DtyHE","model":"claude-sonnet-4-5-20250929","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":1365},"cache_creation_input_tokens":1365,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":12,"output_tokens":5,"service_tier":"standard"}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"d6a1fcdbf7e04d0a61b930a91f0f2ae4","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"536617a74e48d587","span_parents":["8d7b49c417c33fbb"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":0,"actual_xact_id":"1000197089101435631"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101435631","last_considered_xact_id":"1000197089101435631"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-cfcaea09-e7ba-484d-ae5e-2bd7658ea802.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-cfcaea09-e7ba-484d-ae5e-2bd7658ea802.json new file mode 100644 index 00000000..08edfdd0 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-cfcaea09-e7ba-484d-ae5e-2bd7658ea802.json @@ -0,0 +1 @@ +{"Code":"TooManyRequestsError","Message":"Too many requests. Source: checkBtqlOrgRateLimit. Rate limit: 20 requests per 60 seconds. Consumed: 21. Retry after 48.63 seconds. Please contact us at support@braintrust.dev to discuss remediation strategies. [user_email=andrew@braintrustdata.com] [user_org=braintrustdata.com] [timestamp=1777600852.264]","InternalTraceId":"69f409540000000029c2838ad2baa5ba","Path":"/btql","Service":"api"} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-d0da1ce5-e44b-468d-beee-da3fa3009421.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-d0da1ce5-e44b-468d-beee-da3fa3009421.json new file mode 100644 index 00000000..36b8834a --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-d0da1ce5-e44b-468d-beee-da3fa3009421.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737126723289097","_xact_id":"1000197089096325076","audit_data":[{"_xact_id":"1000197089096325076","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:15.837Z","error":null,"expected":null,"facets":null,"id":"3b0ab131201a1288","input":[{"content":"What is the weather like in Paris, France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":16,"end":1777600756.5787063,"prompt_tokens":85,"start":1777600755.8377883,"tokens":101},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"tool_calls","index":0,"logprobs":null,"message":{"annotations":[],"content":null,"refusal":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"location\":\"Paris, France\"}","name":"get_weather"},"id":"call_JsahRDQEvD5mMD8IqJjJZCif","type":"function"}]}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"c57d627498d6bdfd5121b5eb3233bf34","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"3b0ab131201a1288","span_parents":["a4fad5d3d32e8225"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df.json new file mode 100644 index 00000000..d731c321 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737223253753863","_xact_id":"1000197089097798014","audit_data":[{"_xact_id":"1000197089097798014","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:37.988Z","error":null,"expected":null,"facets":null,"id":"9cebf7285a05fb04","input":[{"content":"you are a helpful assistant","role":"system"},{"content":[{"text":"What color is this image?","type":"text"},{"image_url":{"url":{"content_type":"image/png","filename":"file.png","key":"79c16aa6-d810-479b-a903-ef179b1e05bb","type":"braintrust_attachment"}},"type":"image_url"}],"role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":9,"end":1777600778.7816033,"prompt_tokens":8522,"start":1777600777.9880037,"tokens":8531},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The image is a solid shade of red.","refusal":null,"role":"assistant"}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"eccfa89fac5ee2e478063165e115eb0f","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"9cebf7285a05fb04","span_parents":["eca5bafecd3c7a1d"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-de950214-054b-43b2-aaf2-2d5ac103ddee.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-de950214-054b-43b2-aaf2-2d5ac103ddee.json new file mode 100644 index 00000000..7b14f9ee --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-de950214-054b-43b2-aaf2-2d5ac103ddee.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737175035707392","_xact_id":"1000197089097062265","audit_data":[{"_xact_id":"1000197089097062265","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:24.943Z","error":null,"expected":null,"facets":null,"id":"5800e1ebf015d0f0","input":[{"content":[{"text":"What color is this image?","type":"text"},{"image":{"format":"png","source":{"bytes":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg=="}},"type":"image"}],"role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","endpoint":"converse","model":"us.amazon.nova-lite-v1:0","provider":"bedrock","request_base_uri":"http://localhost","request_method":"POST","request_path":"model/us.amazon.nova-lite-v1%3A0/converse"},"metrics":{"completion_tokens":32,"end":1777600765.8354297,"prompt_tokens":536,"start":1777600764.9430652,"tokens":568},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"content":[{"text":"Sorry, I cannot respond to questions that require visual input. I suggest using a color picker tool or consulting with a professional designer for accurate color identification.","type":"text"}],"role":"assistant"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"b86bf0a74edbecfa09a2ca45f8c9b498","scores":null,"span_attributes":{"name":"bedrock.converse","type":"llm"},"span_id":"5800e1ebf015d0f0","span_parents":["73631d667fe21edf"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e109b114-6ad2-4317-8680-7688991365a3.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e109b114-6ad2-4317-8680-7688991365a3.json new file mode 100644 index 00000000..35847bbe --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e109b114-6ad2-4317-8680-7688991365a3.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737126723289099","_xact_id":"1000197089096325076","audit_data":[{"_xact_id":"1000197089096325076","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:16.729Z","error":null,"expected":null,"facets":null,"id":"41bb2dd00fd00ebd","input":[{"content":"you are a thoughtful assistant","role":"system"},{"content":"Count from 1 to 10 slowly.","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini-2024-07-18","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":41,"end":1777600758.5095065,"prompt_tokens":25,"start":1777600756.7297907,"time_to_first_token":1.72757898,"tokens":66},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"message":{"content":"Sure! Here we go:\n\n1... \n2... \n3... \n4... \n5... \n6... \n7... \n8... \n9... \n10... \n\nThere you have it!","role":"assistant"}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"380b9957ee917f5845ff9d0914b7d388","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"41bb2dd00fd00ebd","span_parents":["0dbda7db2f97e1b6"],"tags":null},{"_async_scoring_state":{"function_ids":[],"status":"enabled","token":"69e1dd0e-9a2f-4bf6-b8ad-75403b1b45c4","triggered_functions":{"global:facet:Issues":{"attempts":0,"completed_xact_id":1000197089096325100,"idempotency_key":"16e6d61bf45110b6a33c3e196cafc80b1686775852827ef69a2209f2238a0085:1000197089096325076","scope":{"type":"trace"},"triggered_xact_id":1000197089096325100},"global:facet:Sentiment":{"attempts":0,"completed_xact_id":1000197089096325100,"idempotency_key":"f19a30249fa6173742ac84e4c4b1ef24539b1514f6e5355a2bc8c3ae0fc70fdd:1000197089096325076","scope":{"type":"trace"},"triggered_xact_id":1000197089096325100},"global:facet:Task":{"attempts":0,"completed_xact_id":1000197089096325100,"idempotency_key":"c3641895395e27f163e2cfdadee1f579400df2a90ae7d3ac90ffb2e6856db8ec:1000197089096325076","scope":{"type":"trace"},"triggered_xact_id":1000197089096325100}}},"_pagination_key":"p07634737126723289093","_xact_id":"1000197089098937113","audit_data":[{"_xact_id":"1000197089098937113","audit_data":{"action":"merge","from":null,"path":["facets"],"to":{"Issues":"no_match","Sentiment":"no_match","Task":"User wants to count numbers from 1 to 10 at a slow pace."}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:51.241Z","error":null,"expected":null,"facets":{"Issues":"no_match","Sentiment":"no_match","Task":"User wants to count numbers from 1 to 10 at a slow pace."},"id":"33c677134bf502257f80c1e9f21b81295af55bc5d046e317becc91a5fb4d95cc","input":null,"is_root":false,"log_id":"g","metadata":null,"metrics":null,"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":null,"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"380b9957ee917f5845ff9d0914b7d388","scores":null,"span_attributes":{"name":"_topicsAutomation","purpose":"scorer","type":"automation"},"span_id":"33c677134bf502257f80c1e9f21b81295af55bc5d046e317becc91a5fb4d95cc","span_parents":["0dbda7db2f97e1b6"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737126723289093","_xact_id":"1000197089098937113","audit_data":[{"_xact_id":"1000197089098401954","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089098402084","audit_data":{"action":"merge","from":null,"path":["input"],"to":{}},"metadata":{},"source":"api"},{"_xact_id":"1000197089098937113","audit_data":{"action":"merge","path":["output"]},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{},"created":"2026-05-01T01:59:51.490Z","error":null,"expected":null,"facets":null,"id":"e4b89f94-208f-4475-8721-373c664fe401","input":{},"is_root":false,"log_id":"g","metadata":null,"metrics":{"end":1777600798.955,"start":1777600791.49},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"facets":{"Issues":"no_match","Sentiment":"no_match","Task":{"embedding_model":"brain-embedding-1","facet":"User wants to count numbers from 1 to 10 at a slow pace.","vector":"vector[1024]"}},"kind":"facet_with_topic_maps","topic_map_classifications":[]},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"380b9957ee917f5845ff9d0914b7d388","scores":null,"span_attributes":{"exec_counter":43952,"name":"Pipeline","purpose":"scorer","remote":true,"skip_realtime":true,"slug":"inline_function_batched_facet","type":"facet"},"span_id":"c5012f69-12fc-4c13-8258-84bca034136c","span_parents":["33c677134bf502257f80c1e9f21b81295af55bc5d046e317becc91a5fb4d95cc"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737126723289093","_xact_id":"1000197089098871327","audit_data":[{"_xact_id":"1000197089098402497","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089098468162","audit_data":{"action":"merge","from":null,"path":["span_attributes"],"to":{"name":"Chat Completion"}},"metadata":{},"source":"api"},{"_xact_id":"1000197089098468266","audit_data":{"action":"merge","path":["metadata"]},"metadata":{},"source":"api"},{"_xact_id":"1000197089098871184","audit_data":{"action":"merge","from":null,"path":["metrics"],"to":{"retries":0}},"metadata":{},"source":"api"},{"_xact_id":"1000197089098871327","audit_data":{"action":"merge","from":null,"path":["metrics"],"to":{"completion_tokens":832,"end":1777600798.699,"prompt_tokens":2147,"time_to_first_token":6.78600001335144,"tokens":2979}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{"caller_filename":"node:internal/process/task_queues","caller_functionname":"process.processTicksAndRejections","caller_lineno":104},"created":"2026-05-01T01:59:51.912Z","error":null,"expected":null,"facets":null,"id":"d56696ee-eccf-41d4-a096-bce7cd1013c3","input":[{"content":"You are an analyst extracting structured information from AI conversations.\n\nPRIVACY REQUIREMENTS (critical):\n- Do NOT include any personally identifiable information (PII): names, locations, phone numbers, email addresses, usernames, or any other identifying details.\n- Do NOT include any proper nouns (company names, product names, people's names, place names, etc.).\n- Replace specific identifiers with generic descriptions (e.g., \"a technology company\" instead of company names).\n\nANALYSIS GUIDELINES:\n- Be descriptive and assume neither good nor bad faith.\n- Do not hesitate to identify and describe socially harmful or sensitive topics specifically; specificity around potentially harmful conversations is necessary for effective monitoring.\n- If you see truncation markers like \"[...]\" or \"[middle truncated]\", assume the text was clipped for length. Do NOT treat truncation alone as a problem unless the visible text clearly shows one.\n- Tool summaries (lines starting with \"Tool (\") are internal context; do NOT penalize their presence or the absence of full tool details.","role":"system"},{"content":"Here is the data to analyze:\n\nUser:\n Count from 1 to 10 slowly.\n\nAssistant:\n Sure! Here we go:\n \n 1... \n 2... \n 3... \n 4... \n 5... \n 6... \n 7... \n 8... \n 9... \n 10... \n \n There you have it!","role":"user"}],"is_root":false,"log_id":"g","metadata":{"max_tokens":20000,"model":"brain-facet-latest","stream":false,"suffix_messages":[[{"content":"What is the user's overall request or goal in this conversation?\n\nRespond with a single sentence starting with \"User wants to...\"\n\nFocus on the high-level intent, not specific details. If multiple requests, describe the main one.\n\nExamples:\n- \"User wants to debug why their API calls are returning errors\"\n- \"User wants to create a new LLM-based evaluation scorer\"\n- \"User wants to understand how to interpret experiment results\"\n- \"User wants to optimize their prompt for better accuracy\"\n\nIf no clear request is present, respond: \"NONE\"\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}],[{"content":"Classify the user's overall sentiment toward the interaction. Do not describe the use case, only the user's sentiment.\n\nConsider:\n- Negative: frustration, confusion, dissatisfaction, impatience, giving up\n- Positive: satisfaction, gratitude, praise\n- Neutral: factual, no clear emotional valence\n- Mixed: both positive and negative signals\n\nUse these exact labels (title case):\n- Negative\n- Neutral\n- Positive\n- Mixed\n\nAfter the label, add a brief reason in 1 sentence.\n\nExamples:\n- \"Negative. User complained the instructions still don't work.\"\n- \"Positive. User thanked the assistant for solving the issue.\"\n- \"Neutral. User asked for a definition without emotional language.\"\n- \"Mixed. User was frustrated earlier but later expressed thanks.\"\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}],[{"content":"Review this AI assistant conversation for clear problems.\n\nMost conversations are fine. Only flag when you are fully certain an issue occurred.\n\nOutput format:\n- \"NONE\" if conversation is normal\n- \". <1-2 sentence explanation of what specifically went wrong>\" if absolutely certain\n\nUse these exact category labels (title case): No response, Confused, Lazy, Incomplete, Leaked reasoning.\n\nImportant: Every non-NONE output must include a specific explanation. Do not output only \"No response\" - explain why (e.g., \"No response. User asked about quarterly revenue but assistant only ran a query and never provided the answer\").\n\nNo response\nOnly flag if all of these are true:\n1. User asked a question or requested something\n2. Assistant used tools to gather information\n3. The final message is a tool result with no assistant reply after it\n4. The user is clearly left without an answer\n\nDo not flag No response if:\n- There's any assistant message after the tool result\n- The conversation is still in progress\n- User's last message was just providing context (not asking)\n- Assistant asked a clarifying question\n- There are tool failures but the assistant still provides a usable fallback or final answer\n\nOther categories:\n- Confused: answered wrong question entirely\n- Lazy: refused without trying\n- Incomplete: response cut off mid-sentence\n- Leaked reasoning: assistant shares its internal thought process in tags or similar\n\nTruncation guidance:\nThis conversation log may contain truncated content marked with \"[... truncated ...]\", \"[middle truncated]\", \"...\", or similar. Tool call outputs are often shortened for display.\n\nDo not flag issues caused by truncation:\n- If you can't see full tool output, assume it was complete\n- If assistant references data you can't see, it was likely in the truncated portion\n- Missing context due to truncation is NOT a problem\n\nNormal (always NONE):\n- Single/intermittent tool errors where the assistant still provides a usable answer or fallback\n- Verbose/detailed responses\n- Multiple attempts\n- Clarifying questions\n- Truncation markers\n- Assistant referencing data that may have been truncated\n\nWhen in doubt, say NONE.\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}]]},"metrics":{"completion_tokens":832,"end":1777600798.699,"prompt_tokens":2147,"retries":0,"start":1777600791.912,"time_to_first_token":6.78600001335144,"tokens":2979},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's see. The user asked to count from 1 to 10 slowly. The assistant responded by counting each number with a pause after each, then confirming the count. The user's request here is pretty straightforward. They wanted a slow count, maybe to practice counting, or perhaps for a child learning numbers. The main goal is to have the numbers counted one by one, not just a quick list. The assistant did exactly that, so the user's overall request is to have a slow, deliberate counting from 1 to 10. No hidden requests or additional goals here. Just a simple counting task. So the answer should reflect that the user wants to count numbers from 1 to 10 at a slow pace.\n\n\nUser wants to count numbers from 1 to 10 at a slow pace.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}},{"finish_reason":"stop","index":1,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's see. The user asked to count from 1 to 10 slowly. The assistant responded by counting each number with a pause, then confirming completion. The user's message is straightforward, just a simple counting task. The assistant's response is methodical and follows the instruction as given. \n\nNow, I need to determine the user's sentiment. The user didn't express any frustration or dissatisfaction. They just provided a clear request, and the assistant fulfilled it. There's no indication of impatience or confusion. The user might be testing the assistant's ability to follow instructions, but there's no negative feedback. The assistant's response is neutral in tone, just executing the task without any extra elements. \n\nSince the user's message is factual and there's no emotional language, the sentiment is likely neutral. The user didn't show any positive or negative emotions, just a straightforward request. So the classification should be Neutral. The reason would be that the user's interaction was factual without emotional cues.\n\n\nNeutral. The user's interaction was factual and straightforward without emotional cues.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}},{"finish_reason":"stop","index":2,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's take a look at this conversation. The user asked the assistant to count from 1 to 10 slowly. The assistant responded by counting each number with a pause, then concluded with \"There you have it!\" \n\nFirst, I need to check if there's any issue here. The user's request was straightforward, and the assistant provided a clear, complete response. Each number was counted with a pause, which matches the user's instruction. The assistant didn't use any tools here; they just gave a direct answer. \n\nLooking at the categories: No response would apply if the assistant used tools but didn't provide an answer. But in this case, the assistant didn't use any tools. The response is fully formed and answers the question. There's no truncation or incomplete sentences. The assistant didn't show any confusion or laziness. \n\nSince the conversation is complete and the assistant answered correctly without any issues, the appropriate response is NONE. There's no leaking of reasoning, and the user isn't left without an answer. Everything seems normal here.\n\n\nNONE \nThe assistant provided a complete, accurate response to the user's request, counting from 1 to 10 with clear pauses as instructed. No tools were used, and the conversation concluded with a satisfactory answer.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"380b9957ee917f5845ff9d0914b7d388","scores":null,"span_attributes":{"exec_counter":43953,"name":"Chat Completion","purpose":"scorer","skip_realtime":true,"type":"llm"},"span_id":"6bea1173-8c74-4c0d-9d4f-23ea2c11afbb","span_parents":["c5012f69-12fc-4c13-8258-84bca034136c"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737126723289093","_xact_id":"1000197089098937113","audit_data":[{"_xact_id":"1000197089098871327","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089098871465","audit_data":{"action":"merge","from":null,"path":["span_attributes"],"to":{"name":"Embedding"}},"metadata":{},"source":"api"},{"_xact_id":"1000197089098937113","audit_data":{"action":"merge","from":null,"path":["metadata"],"to":{"model":"brain-embedding-1"}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{"caller_filename":"node:internal/process/task_queues","caller_functionname":"process.processTicksAndRejections","caller_lineno":104},"created":"2026-05-01T01:59:58.700Z","error":null,"expected":null,"facets":null,"id":"c87f7d2a-04f4-4cf6-8922-a8b1d0470476","input":{"input":["User wants to count numbers from 1 to 10 at a slow pace."],"model":"brain-embedding-1"},"is_root":false,"log_id":"g","metadata":{"model":"brain-embedding-1"},"metrics":{"end":1777600798.953,"prompt_tokens":16,"retries":0,"start":1777600798.7,"tokens":16},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"embedding_length":1024},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"380b9957ee917f5845ff9d0914b7d388","scores":null,"span_attributes":{"exec_counter":43961,"name":"Embedding","purpose":"scorer","skip_realtime":true,"type":"llm"},"span_id":"75d6d2b4-f92c-482b-a68c-d143cbc48d98","span_parents":["c5012f69-12fc-4c13-8258-84bca034136c"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e1844750-b874-4ef6-bd98-f3779a0c7f4a.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e1844750-b874-4ef6-bd98-f3779a0c7f4a.json new file mode 100644 index 00000000..7d6d2b62 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e1844750-b874-4ef6-bd98-f3779a0c7f4a.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737175035707401","_xact_id":"1000197089097062265","audit_data":[{"_xact_id":"1000197089097062265","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:27.026Z","error":null,"expected":null,"facets":null,"id":"0104587462548026","input":[{"content":"Count from 1 to 5.","role":"user"},{"content":"You are a helpful assistant.","role":"system"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"claude-haiku-4-5-20251001","provider":"anthropic","request_base_uri":"","request_method":"POST","request_path":"v1/messages"},"metrics":{"completion_tokens":13,"end":1777600767.8773172,"prompt_cache_creation_1h_tokens":0,"prompt_cache_creation_5m_tokens":0,"prompt_cached_tokens":0,"prompt_tokens":22,"start":1777600767.026407,"time_to_first_token":0.005927308,"tokens":35},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"content":[{"citations":null,"text":"1\n2\n3\n4\n5","type":"text","valid":true}],"id":"msg_01QoWH6toEXBYEBSymjmNaXq","model":"claude-haiku-4-5-20251001","role":"assistant","stop_details":null,"stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0,"valid":true},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"inference_geo":"not_available","input_tokens":22,"output_tokens":13,"server_tool_use":null,"service_tier":"standard","valid":true},"valid":true},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"4a96d0f41b537b117968f413b234d028","scores":null,"span_attributes":{"name":"anthropic.messages.create","type":"llm"},"span_id":"0104587462548026","span_parents":["99ed474cf836aae7"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101435631","read_bytes":5647,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e7c1f7f0-59ae-4a71-96c1-50177219feca.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e7c1f7f0-59ae-4a71-96c1-50177219feca.json new file mode 100644 index 00000000..caaba8ff --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-e7c1f7f0-59ae-4a71-96c1-50177219feca.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737148730408960","_xact_id":"1000197089096660878","audit_data":[{"_xact_id":"1000197089096660878","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:17.804Z","error":null,"expected":null,"facets":null,"id":"5b46cc75f383ba44","input":[{"content":[{"text":"What is the capital of France?","type":"text"}],"role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","endpoint":"converse","model":"us.amazon.nova-lite-v1:0","provider":"bedrock","request_base_uri":"http://localhost","request_method":"POST","request_path":"model/us.amazon.nova-lite-v1%3A0/converse"},"metrics":{"completion_tokens":287,"end":1777600760.174013,"prompt_tokens":7,"start":1777600757.8040397,"tokens":294},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"content":[{"text":"The capital of France is Paris. It is not only the capital but also the largest city in the country, known for its rich history, culture, and landmarks. Paris is often referred to as \"The City of Light\" (La Ville Lumière) and \"The City of Love\" (La Ville en Rose) due to its contributions to art, culture, and romance.\n\nParis is divided into 20 administrative arrondissements (municipalities) and is located in the north-central part of France, along the Seine River. It has a population of approximately 2.1 million people within its city limits, and the greater Paris metropolitan area is home to over 12 million people.\n\nThe city is renowned for its iconic landmarks, such as the Eiffel Tower, the Notre-Dame Cathedral, the Louvre Museum, the Champs-Élysées, the Arc de Triomphe, and the Basilica of the Sacré-Cœur. Paris is also famous for its cuisine, fashion, art, and its role in the development of modern philosophy and political thought.\n\nThroughout its history, Paris has been a center of education, arts, and culture, hosting numerous famous artists, writers, and thinkers, such as Leonardo da Vinci, Marcel Proust, Pablo Picasso, and Albert Einstein. It is a major global city, a significant hub for diplomacy, and a top tourist destination, attracting millions of visitors each year.","type":"text"}],"role":"assistant"}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"acd28eb57b7b26a0885f1cbc6dbbfc07","scores":null,"span_attributes":{"name":"bedrock.converse","type":"llm"},"span_id":"5b46cc75f383ba44","span_parents":["367cbc4389b4e421"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-efaeb6e5-57f2-40e7-9688-755c63baf7d0.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-efaeb6e5-57f2-40e7-9688-755c63baf7d0.json new file mode 100644 index 00000000..edaed74e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-efaeb6e5-57f2-40e7-9688-755c63baf7d0.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737126723289096","_xact_id":"1000197089096325076","audit_data":[{"_xact_id":"1000197089096325076","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:15.540Z","error":null,"expected":null,"facets":null,"id":"836abb597a1660f6","input":[{"content":"you are a helpful assistant","role":"system"},{"content":"What is the capital of France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o-mini","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":7,"end":1777600756.3716598,"prompt_tokens":23,"start":1777600755.5408993,"tokens":30},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The capital of France is Paris.","refusal":null,"role":"assistant"}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"d2230fc189d7f2d5ebfef06134107451","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"836abb597a1660f6","span_parents":["8fd07f3fc5d0faa7"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-f5c05ce0-0947-49ec-b437-0ccaeda6bbe6.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-f5c05ce0-0947-49ec-b437-0ccaeda6bbe6.json new file mode 100644 index 00000000..fb6f1057 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-f5c05ce0-0947-49ec-b437-0ccaeda6bbe6.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737126723289094","_xact_id":"1000197089096325076","audit_data":[{"_xact_id":"1000197089096325076","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:14.548Z","error":null,"expected":null,"facets":null,"id":"eeeae73f3a1de4ac","input":[{"content":"What is the weather like in Paris, France?","role":"user"}],"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gpt-4o","provider":"openai","request_base_uri":"http://localhost:39893","request_method":"POST","request_path":"chat/completions"},"metrics":{"completion_tokens":16,"end":1777600755.776418,"prompt_tokens":85,"start":1777600754.5484104,"tokens":101},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"tool_calls","index":0,"logprobs":null,"message":{"annotations":[],"content":null,"refusal":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"location\":\"Paris, France\"}","name":"get_weather"},"id":"call_faUMvnGdGqNzG6Go8zQd7Vga","type":"function"}]}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"db0e36fd13d0ccbb323ad7482348e0b3","scores":null,"span_attributes":{"name":"Chat Completion","type":"llm"},"span_id":"eeeae73f3a1de4ac","span_parents":["a00cc3fa09e00d89"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-faf9b0bc-7f71-4a39-b6ca-26b62a647163.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-faf9b0bc-7f71-4a39-b6ca-26b62a647163.json new file mode 100644 index 00000000..0bf293be --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/__files/btql-faf9b0bc-7f71-4a39-b6ca-26b62a647163.json @@ -0,0 +1 @@ +{"data":[{"_async_scoring_state":null,"_pagination_key":"p07634737126723289098","_xact_id":"1000197089096325076","audit_data":[{"_xact_id":"1000197089096325076","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:16.155Z","error":null,"expected":null,"facets":null,"id":"02867374b52ec5f0","input":{"config":{"temperature":0},"contents":[{"parts":[{"text":"What is the capital of France?"}],"role":"user"}],"model":"gemini-3.1-flash-lite-preview"},"is_root":false,"log_id":"g","metadata":{"braintrust.parent":"project_name:java-unit-test","model":"gemini-3.1-flash-lite-preview","provider":"gemini","temperature":0},"metrics":{"completion_tokens":7,"end":1777600757.398671,"prompt_tokens":8,"start":1777600756.155033,"tokens":15},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"candidates":[{"content":{"parts":[{"text":"The capital of France is Paris.","thoughtSignature":"EjQKMgEMOdbHOWnN41SM6AIyb6GJ4fxbrVI14S3xjjl01Uhd5Jjl94+IhhrivCFX+0a79uTw"}],"role":"model"},"finishReason":"STOP","index":0}],"modelVersion":"gemini-3.1-flash-lite-preview","responseId":"9Qj0afC1A_qKmtkPwbiGuAs","usageMetadata":{"candidatesTokenCount":7,"promptTokenCount":8,"promptTokensDetails":[{"modality":"TEXT","tokenCount":8}],"totalTokenCount":15}},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"ee58e3ff2b397c9b7fa3e9f3a18faa0e","scores":null,"span_attributes":{"name":"generate_content","type":"llm"},"span_id":"02867374b52ec5f0","span_parents":["e1ae8945da6515b2"],"tags":null},{"_async_scoring_state":{"function_ids":[],"status":"enabled","token":"174ad4bb-eb44-40c9-adbd-c1c399a7d581","triggered_functions":{"global:facet:Issues":{"attempts":0,"completed_xact_id":1000197089096325100,"idempotency_key":"16e6d61bf45110b6a33c3e196cafc80b1686775852827ef69a2209f2238a0085:1000197089096325076","scope":{"type":"trace"},"triggered_xact_id":1000197089096325100},"global:facet:Sentiment":{"attempts":0,"completed_xact_id":1000197089096325100,"idempotency_key":"f19a30249fa6173742ac84e4c4b1ef24539b1514f6e5355a2bc8c3ae0fc70fdd:1000197089096325076","scope":{"type":"trace"},"triggered_xact_id":1000197089096325100},"global:facet:Task":{"attempts":0,"completed_xact_id":1000197089096325100,"idempotency_key":"c3641895395e27f163e2cfdadee1f579400df2a90ae7d3ac90ffb2e6856db8ec:1000197089096325076","scope":{"type":"trace"},"triggered_xact_id":1000197089096325100}}},"_pagination_key":"p07634737126723289092","_xact_id":"1000197089098736983","audit_data":[{"_xact_id":"1000197089098736983","audit_data":{"action":"merge","from":null,"path":["facets"],"to":{"Issues":"no_match","Sentiment":"no_match","Task":"User wants to know the capital of France."}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":null,"created":"2026-05-01T01:59:51.241Z","error":null,"expected":null,"facets":{"Issues":"no_match","Sentiment":"no_match","Task":"User wants to know the capital of France."},"id":"cf0c98e40ded60fb18fbd02c545e4271e0512aa76fff8dcc7d41751f15a2fb01","input":null,"is_root":false,"log_id":"g","metadata":null,"metrics":null,"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":null,"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"ee58e3ff2b397c9b7fa3e9f3a18faa0e","scores":null,"span_attributes":{"name":"_topicsAutomation","purpose":"scorer","type":"automation"},"span_id":"cf0c98e40ded60fb18fbd02c545e4271e0512aa76fff8dcc7d41751f15a2fb01","span_parents":["e1ae8945da6515b2"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737126723289092","_xact_id":"1000197089098736983","audit_data":[{"_xact_id":"1000197089098401849","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089098401965","audit_data":{"action":"merge","from":null,"path":["input"],"to":{}},"metadata":{},"source":"api"},{"_xact_id":"1000197089098736983","audit_data":{"action":"merge","path":["output"]},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{},"created":"2026-05-01T01:59:51.412Z","error":null,"expected":null,"facets":null,"id":"bf7dcfe4-1a42-4de6-9baf-d16a7ba41ef0","input":{},"is_root":false,"log_id":"g","metadata":null,"metrics":{"end":1777600796.406,"start":1777600791.412},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"facets":{"Issues":"no_match","Sentiment":"no_match","Task":{"embedding_model":"brain-embedding-1","facet":"User wants to know the capital of France.","vector":"vector[1024]"}},"kind":"facet_with_topic_maps","topic_map_classifications":[]},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"ee58e3ff2b397c9b7fa3e9f3a18faa0e","scores":null,"span_attributes":{"exec_counter":8605,"name":"Pipeline","purpose":"scorer","remote":true,"skip_realtime":true,"slug":"inline_function_batched_facet","type":"facet"},"span_id":"074a0c56-3a33-47b6-8869-d3e8b9f99668","span_parents":["cf0c98e40ded60fb18fbd02c545e4271e0512aa76fff8dcc7d41751f15a2fb01"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737126723289092","_xact_id":"1000197089098736983","audit_data":[{"_xact_id":"1000197089098402407","audit_data":{"action":"upsert"},"metadata":{},"source":"api"},{"_xact_id":"1000197089098468121","audit_data":{"action":"merge","from":null,"path":["span_attributes"],"to":{"name":"Chat Completion"}},"metadata":{},"source":"api"},{"_xact_id":"1000197089098468197","audit_data":{"action":"merge","path":["metadata"]},"metadata":{},"source":"api"},{"_xact_id":"1000197089098736527","audit_data":{"action":"merge","from":null,"path":["metrics"],"to":{"retries":0}},"metadata":{},"source":"api"},{"_xact_id":"1000197089098736983","audit_data":{"action":"merge","from":null,"path":["metrics"],"to":{"completion_tokens":912,"end":1777600796.4,"prompt_tokens":1907,"time_to_first_token":4.565999984741211,"tokens":2819}},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{"caller_filename":"node:internal/process/task_queues","caller_functionname":"process.processTicksAndRejections","caller_lineno":104},"created":"2026-05-01T01:59:51.833Z","error":null,"expected":null,"facets":null,"id":"0f5e641b-d758-4259-9767-5ce67ef4a8e9","input":[{"content":"You are an analyst extracting structured information from AI conversations.\n\nPRIVACY REQUIREMENTS (critical):\n- Do NOT include any personally identifiable information (PII): names, locations, phone numbers, email addresses, usernames, or any other identifying details.\n- Do NOT include any proper nouns (company names, product names, people's names, place names, etc.).\n- Replace specific identifiers with generic descriptions (e.g., \"a technology company\" instead of company names).\n\nANALYSIS GUIDELINES:\n- Be descriptive and assume neither good nor bad faith.\n- Do not hesitate to identify and describe socially harmful or sensitive topics specifically; specificity around potentially harmful conversations is necessary for effective monitoring.\n- If you see truncation markers like \"[...]\" or \"[middle truncated]\", assume the text was clipped for length. Do NOT treat truncation alone as a problem unless the visible text clearly shows one.\n- Tool summaries (lines starting with \"Tool (\") are internal context; do NOT penalize their presence or the absence of full tool details.","role":"system"},{"content":"Here is the data to analyze:\n\nUser:\n What is the capital of France?\n\nAssistant:\n The capital of France is Paris.","role":"user"}],"is_root":false,"log_id":"g","metadata":{"max_tokens":20000,"model":"brain-facet-latest","stream":false,"suffix_messages":[[{"content":"What is the user's overall request or goal in this conversation?\n\nRespond with a single sentence starting with \"User wants to...\"\n\nFocus on the high-level intent, not specific details. If multiple requests, describe the main one.\n\nExamples:\n- \"User wants to debug why their API calls are returning errors\"\n- \"User wants to create a new LLM-based evaluation scorer\"\n- \"User wants to understand how to interpret experiment results\"\n- \"User wants to optimize their prompt for better accuracy\"\n\nIf no clear request is present, respond: \"NONE\"\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}],[{"content":"Classify the user's overall sentiment toward the interaction. Do not describe the use case, only the user's sentiment.\n\nConsider:\n- Negative: frustration, confusion, dissatisfaction, impatience, giving up\n- Positive: satisfaction, gratitude, praise\n- Neutral: factual, no clear emotional valence\n- Mixed: both positive and negative signals\n\nUse these exact labels (title case):\n- Negative\n- Neutral\n- Positive\n- Mixed\n\nAfter the label, add a brief reason in 1 sentence.\n\nExamples:\n- \"Negative. User complained the instructions still don't work.\"\n- \"Positive. User thanked the assistant for solving the issue.\"\n- \"Neutral. User asked for a definition without emotional language.\"\n- \"Mixed. User was frustrated earlier but later expressed thanks.\"\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}],[{"content":"Review this AI assistant conversation for clear problems.\n\nMost conversations are fine. Only flag when you are fully certain an issue occurred.\n\nOutput format:\n- \"NONE\" if conversation is normal\n- \". <1-2 sentence explanation of what specifically went wrong>\" if absolutely certain\n\nUse these exact category labels (title case): No response, Confused, Lazy, Incomplete, Leaked reasoning.\n\nImportant: Every non-NONE output must include a specific explanation. Do not output only \"No response\" - explain why (e.g., \"No response. User asked about quarterly revenue but assistant only ran a query and never provided the answer\").\n\nNo response\nOnly flag if all of these are true:\n1. User asked a question or requested something\n2. Assistant used tools to gather information\n3. The final message is a tool result with no assistant reply after it\n4. The user is clearly left without an answer\n\nDo not flag No response if:\n- There's any assistant message after the tool result\n- The conversation is still in progress\n- User's last message was just providing context (not asking)\n- Assistant asked a clarifying question\n- There are tool failures but the assistant still provides a usable fallback or final answer\n\nOther categories:\n- Confused: answered wrong question entirely\n- Lazy: refused without trying\n- Incomplete: response cut off mid-sentence\n- Leaked reasoning: assistant shares its internal thought process in tags or similar\n\nTruncation guidance:\nThis conversation log may contain truncated content marked with \"[... truncated ...]\", \"[middle truncated]\", \"...\", or similar. Tool call outputs are often shortened for display.\n\nDo not flag issues caused by truncation:\n- If you can't see full tool output, assume it was complete\n- If assistant references data you can't see, it was likely in the truncated portion\n- Missing context due to truncation is NOT a problem\n\nNormal (always NONE):\n- Single/intermittent tool errors where the assistant still provides a usable answer or fallback\n- Verbose/detailed responses\n- Multiple attempts\n- Clarifying questions\n- Truncation markers\n- Assistant referencing data that may have been truncated\n\nWhen in doubt, say NONE.\n\nProvide the privacy-preserving answer succinctly. Remember: no PII, no proper nouns.","role":"user"}]]},"metrics":{"completion_tokens":912,"end":1777600796.4,"prompt_tokens":1907,"retries":0,"start":1777600791.833,"time_to_first_token":4.565999984741211,"tokens":2819},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let me tackle this query. The user asked, \"What is the capital of France?\" and the assistant answered, \"The capital of France is Paris.\" \n\nFirst, I need to determine the user's overall request or goal. The question is straightforward, asking for factual information about the capital of a country. The user isn't asking for a process, a solution to a problem, or any complex analysis. They just want to know the answer to a specific question.\n\nLooking at the examples provided, the user wants to debug an API, create a scorer, understand results, or optimize a prompt. None of those apply here. The user's goal is simply to obtain factual knowledge. \n\nI should check if there's any hidden intent or multiple requests. The question is singular and direct. There's no mention of needing steps, explanations, or additional information beyond the answer. \n\nSince the user is asking for a fact, the answer should be that they want to know the capital of France. The response needs to start with \"User wants to...\" and be a single sentence. Also, ensure no PII or proper nouns are included. \n\nSo, the correct answer would be: \"User wants to know the capital of France.\"\n\n\nUser wants to know the capital of France.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}},{"finish_reason":"stop","index":1,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's see. The user asked for the capital of France, and the assistant answered Paris. The task is to classify the user's sentiment here.\n\nFirst, I need to check if there's any emotional language. The user's question is straightforward and factual. They didn't express any frustration, confusion, or other negative emotions. The assistant provided a direct answer, so the user's response is just a simple question. \n\nSince the user didn't show any positive emotions like gratitude or praise either, and the interaction is purely factual, the sentiment is likely neutral. There's no indication of mixed feelings here. The user's intent was to get information, and the assistant fulfilled that without any issues mentioned. So the sentiment should be Neutral because there's no clear emotional valence. Just a straightforward question and answer.\n\n\nNeutral. User asked for a factual answer without expressing emotional language.","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}},{"finish_reason":"stop","index":2,"logprobs":null,"message":{"annotations":null,"audio":null,"content":"\nOkay, let's take a look at this conversation. The user asked, \"What is the capital of France?\" and the assistant replied, \"The capital of France is Paris.\" \n\nFirst, I need to check if there's any issue here. The user's question is straightforward, and the assistant provided a direct and correct answer. There's no indication of truncation, like \"[...]\" or similar markers. The response isn't cut off mid-sentence. The assistant didn't use any tools here; they just gave the answer immediately. \n\nLooking at the categories: No response would apply if the assistant used tools but didn't provide an answer. But in this case, the assistant didn't use any tools. The answer is complete and correct. There's no confusion, laziness, incompleteness, or leaking reasoning. \n\nSo, everything seems normal. The response is accurate and fully formed. No issues detected here. The answer is straightforward and meets the user's request without any problems.\n\n\nNONE","function_call":null,"refusal":null,"role":"assistant","tool_calls":null}}],"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"ee58e3ff2b397c9b7fa3e9f3a18faa0e","scores":null,"span_attributes":{"exec_counter":8606,"name":"Chat Completion","purpose":"scorer","skip_realtime":true,"type":"llm"},"span_id":"b6461c20-3420-4060-b8d0-a0ca7769fc58","span_parents":["074a0c56-3a33-47b6-8869-d3e8b9f99668"],"tags":null},{"_async_scoring_state":{"status":"disabled"},"_pagination_key":"p07634737126723289092","_xact_id":"1000197089098736983","audit_data":[{"_xact_id":"1000197089098736983","audit_data":{"action":"upsert"},"metadata":{},"source":"api"}],"classifications":null,"comments":null,"context":{"caller_filename":"node:internal/process/task_queues","caller_functionname":"process.processTicksAndRejections","caller_lineno":104},"created":"2026-05-01T01:59:56.401Z","error":null,"expected":null,"facets":null,"id":"30d927f7-ab74-4f49-9bdf-6352dc400acc","input":{"input":["User wants to know the capital of France."],"model":"brain-embedding-1"},"is_root":false,"log_id":"g","metadata":{"model":"brain-embedding-1"},"metrics":{"cached":1,"end":1777600796.404,"prompt_tokens":11,"start":1777600796.401,"tokens":11},"org_id":"5d7c97d7-fef1-4cb7-bda6-7e3756a0ca8e","origin":null,"output":{"embedding_length":1024},"project_id":"6ae68365-7620-4630-921b-bac416634fc8","root_span_id":"ee58e3ff2b397c9b7fa3e9f3a18faa0e","scores":null,"span_attributes":{"exec_counter":8610,"name":"Embedding","purpose":"scorer","skip_realtime":true,"type":"llm"},"span_id":"42339172-d65a-47d8-b6f5-c5ed3a3cef5a","span_parents":["074a0c56-3a33-47b6-8869-d3e8b9f99668"],"tags":null}],"schema":{"type":"array","items":{"type":"object","properties":{"_async_scoring_state":{},"_pagination_key":{"description":"A stable, time-ordered key that can be used to paginate over project logs events. This field is auto-generated by Braintrust and only exists in Brainstore.","type":["string","null"]},"_xact_id":{"description":"The transaction id of an event is unique to the network operation that processed the event insertion. Transaction ids are monotonically increasing over time and can be used to retrieve a versioned snapshot of the project logs (see the `version` parameter)","type":"string"},"audit_data":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"classifications":{"anyOf":[{"additionalProperties":{"items":{"required":["id"],"additionalProperties":false,"properties":{"confidence":{"description":"Optional confidence score for the classification","type":["number","null"]},"id":{"description":"Stable classification identifier","type":"string"},"label":{"description":"Original label of the classification item, which is useful for search and indexing purposes","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"type":"object"},{"type":"null"}],"description":"Optional metadata associated with the classification"},"source":{"anyOf":[{"anyOf":[{"additionalProperties":false,"properties":{"id":{"type":"string"},"type":{"const":"function","type":"string"},"version":{"description":"The version of the function","type":"string"}},"required":["type","id"],"type":"object"},{"additionalProperties":false,"properties":{"function_type":{"default":"scorer","description":"The type of global function. Defaults to 'scorer'.","enum":["llm","scorer","task","tool","custom_view","preprocessor","facet","classifier","tag","parameters","sandbox"],"type":"string"},"name":{"type":"string"},"type":{"const":"global","type":"string"}},"required":["type","name"],"type":"object"}]},{"type":"null"}],"description":"Optional function identifier that produced the classification"}},"type":"object"},"type":"array"},"properties":{},"type":"object"},{"type":"null"}]},"comments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}]},"context":{"anyOf":[{"additionalProperties":{},"properties":{"caller_filename":{"description":"Name of the file in code where the project logs event was created","type":["string","null"]},"caller_functionname":{"description":"The function in code which created the project logs event","type":["string","null"]},"caller_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"created":{"description":"The timestamp the project logs event was created","type":"string","format":"date-time"},"error":{"description":"The error that occurred, if any."},"expected":{"description":"The ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not. Braintrust currently does not compare `output` to `expected` for you, since there are so many different ways to do that correctly. Instead, these values are just used to help you navigate while digging into analyses. However, we may later use these values to re-score outputs or fine-tune your models."},"facets":{"anyOf":[{"additionalProperties":{},"properties":{},"type":"object"},{"type":"null"}]},"id":{"description":"A unique identifier for the project logs event. If you don't provide one, Braintrust will generate one for you","type":"string"},"input":{"description":"The arguments that uniquely define a user input (an arbitrary, JSON serializable object)."},"is_root":{"description":"Whether this span is a root span","type":["boolean","null"]},"log_id":{"description":"A literal 'g' which identifies the log as a project log","const":"g","type":"string"},"metadata":{"anyOf":[{"additionalProperties":{},"properties":{"model":{"description":"The model used for this example","type":["string","null"]}},"type":"object"},{"type":"null"}]},"metrics":{"anyOf":[{"additionalProperties":{"type":"number"},"properties":{"caller_filename":{"description":"This metric is deprecated"},"caller_functionname":{"description":"This metric is deprecated"},"caller_lineno":{"description":"This metric is deprecated"},"completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"end":{"description":"A unix timestamp recording when the section of code which produced the project logs event finished","type":["number","null"]},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]},"start":{"description":"A unix timestamp recording when the section of code which produced the project logs event started","type":["number","null"]},"tokens":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"org_id":{"description":"Unique id for the organization that the project belongs under","type":"string","format":"uuid"},"origin":{"anyOf":[{"description":"Reference to the original object and event this was copied from.","required":["object_type","object_id","id"],"properties":{"_xact_id":{"description":"Transaction ID of the original event.","type":["string","null"]},"created":{"description":"Created timestamp of the original event. Used to help sort in the UI","type":["string","null"]},"id":{"description":"ID of the original event.","type":"string"},"object_id":{"description":"ID of the object the event is originating from.","format":"uuid","type":"string"},"object_type":{"description":"Type of the object the event is originating from.","enum":["project_logs","experiment","dataset","prompt","function","prompt_session"],"type":"string"}},"type":"object"},{"type":"null"}]},"output":{"description":"The output of your application, including post-processing (an arbitrary, JSON serializable object), that allows you to determine whether the result is correct or not. For example, in an app that generates SQL queries, the `output` should be the _result_ of the SQL query generated by the model, not the query itself, because there may be multiple valid queries that answer a single question."},"project_id":{"description":"Unique identifier for the project","type":"string","format":"uuid"},"root_span_id":{"description":"A unique identifier for the trace this project logs event belongs to","type":"string"},"scores":{"anyOf":[{"additionalProperties":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}]},"properties":{},"type":"object"},{"type":"null"}]},"span_attributes":{"anyOf":[{"description":"Human-identifying attributes of the span, such as name, type, etc.","additionalProperties":{},"properties":{"name":{"description":"Name of the span, for display purposes only","type":["string","null"]},"purpose":{"anyOf":[{"enum":["scorer"],"type":"string"},{"type":"null"}]},"type":{"anyOf":[{"enum":["llm","score","function","eval","task","tool","automation","facet","preprocessor","classifier","review"],"type":"string"},{"type":"null"}]}},"type":"object"},{"type":"null"}]},"span_id":{"description":"A unique identifier used to link different project logs events together as part of a full trace. See the [tracing guide](https://www.braintrust.dev/docs/instrument) for full details on tracing","type":"string"},"span_parents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}]}}}},"realtime_state":{"type":"on","minimum_xact_id":"1000197089101907841","read_bytes":0,"actual_xact_id":"1000197089101907841"},"warnings":[],"freshness_state":{"last_processed_xact_id":"1000197089101907841","last_considered_xact_id":"1000197089101907841"}} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-0186aa94-6976-47f0-866f-712d21e85555.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-0186aa94-6976-47f0-866f-712d21e85555.json new file mode 100644 index 00000000..d9b9b359 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-0186aa94-6976-47f0-866f-712d21e85555.json @@ -0,0 +1,42 @@ +{ + "id" : "0186aa94-6976-47f0-866f-712d21e85555", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"51a08cc230ee4396b2faa9602e0047d5\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-0186aa94-6976-47f0-866f-712d21e85555.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZj4FklIAMEZdg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "87", + "X-Amzn-Trace-Id" : "Root=1-69f4094b-31ece06407763833671b3548;Parent=751a67b142dfa04e;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "166", + "Date" : "Fri, 01 May 2026 02:00:43 GMT", + "Via" : "1.1 4c9457912580c6114eec78b8fa604a20.cloudfront.net (CloudFront), 1.1 e6b2537b87653726af8a79e6da505188.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094b0000000041b30704d48a660d", + "x-amzn-RequestId" : "2d6356a5-91f8-4da3-8754-ebad2cf7c0e1", + "X-Amz-Cf-Id" : "a-MCNxEvEoqXzzwusc31zKGcGHAvr23utIuIk22Of1r1bKyQHnwMug==", + "Content-Type" : "application/json" + } + }, + "uuid" : "0186aa94-6976-47f0-866f-712d21e85555", + "persistent" : true, + "insertionIndex" : 228 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-098ef80b-96d7-45a5-b8d8-9114f930fd16.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-098ef80b-96d7-45a5-b8d8-9114f930fd16.json new file mode 100644 index 00000000..6a8f2269 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-098ef80b-96d7-45a5-b8d8-9114f930fd16.json @@ -0,0 +1,42 @@ +{ + "id" : "098ef80b-96d7-45a5-b8d8-9114f930fd16", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"3822e02415088e004c0220364718ca14\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-098ef80b-96d7-45a5-b8d8-9114f930fd16.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkSFl_IAMEfKA=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "150", + "X-Amzn-Trace-Id" : "Root=1-69f4094e-363b7bb5424b87b67238624b;Parent=5382a36da9965e79;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "229", + "Date" : "Fri, 01 May 2026 02:00:46 GMT", + "Via" : "1.1 e1832834d17ab65dd955f4e68cc524e6.cloudfront.net (CloudFront), 1.1 96f6dcbb4d7267cad6eb0747bce72024.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094e0000000020db13c2ac016bc9", + "x-amzn-RequestId" : "eb18b65f-25ee-401a-b873-c307302672c4", + "X-Amz-Cf-Id" : "SFs60IIbxbJ49sKCoYGBp1AnQNbUFcYLnBSyFSQzefEJkJCnTiaRWg==", + "Content-Type" : "application/json" + } + }, + "uuid" : "098ef80b-96d7-45a5-b8d8-9114f930fd16", + "persistent" : true, + "insertionIndex" : 222 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-2f3613a6-629f-441b-aa2c-f5a039620e9d.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-2f3613a6-629f-441b-aa2c-f5a039620e9d.json new file mode 100644 index 00000000..e4e7f07b --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-2f3613a6-629f-441b-aa2c-f5a039620e9d.json @@ -0,0 +1,42 @@ +{ + "id" : "2f3613a6-629f-441b-aa2c-f5a039620e9d", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"59dc2f7681296c83819618cf4bbd494a\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-2f3613a6-629f-441b-aa2c-f5a039620e9d.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZvEGz2oAMEcJA=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "108", + "X-Amzn-Trace-Id" : "Root=1-69f40993-56b97dd750e473e67852a97a;Parent=4574eda05fa18d75;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "187", + "Date" : "Fri, 01 May 2026 02:01:55 GMT", + "Via" : "1.1 21c7c4234f218bb5110262cbbf01f870.cloudfront.net (CloudFront), 1.1 170efbc424be9181bda5d0fcd6e41f30.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409930000000027567a1e5dd43118", + "x-amzn-RequestId" : "852a253b-a334-4ddf-9cc7-89b7303cec1b", + "X-Amz-Cf-Id" : "vsuNqaQVqRiz9tLAB_646wjvylvaIIF6SYbvr22ULmffkW6AHjbVZQ==", + "Content-Type" : "application/json" + } + }, + "uuid" : "2f3613a6-629f-441b-aa2c-f5a039620e9d", + "persistent" : true, + "insertionIndex" : 205 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-4732cf26-aa00-4f2a-bdc1-13226472c981.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-4732cf26-aa00-4f2a-bdc1-13226472c981.json new file mode 100644 index 00000000..a8949cd3 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-4732cf26-aa00-4f2a-bdc1-13226472c981.json @@ -0,0 +1,42 @@ +{ + "id" : "4732cf26-aa00-4f2a-bdc1-13226472c981", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"6187d886706f869230d78cf9ef3ef5a9\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-4732cf26-aa00-4f2a-bdc1-13226472c981.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZjjFv7oAMEDxg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "271", + "X-Amzn-Trace-Id" : "Root=1-69f40949-1fe5965e19e3f0a141c68677;Parent=0af6a3484d5af920;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "326", + "Date" : "Fri, 01 May 2026 02:00:41 GMT", + "Via" : "1.1 21c7c4234f218bb5110262cbbf01f870.cloudfront.net (CloudFront), 1.1 ddea1c07643e5e0bfceb34480eebdc52.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094900000000687c9cd61edde815", + "x-amzn-RequestId" : "3a143668-d490-49c6-b1cf-cc9c5040fcc5", + "X-Amz-Cf-Id" : "NcM_7TvfTcuKGA0WW6zxZYid239yMHPRb1NKjc0mm_27o4B4AHwe3A==", + "Content-Type" : "application/json" + } + }, + "uuid" : "4732cf26-aa00-4f2a-bdc1-13226472c981", + "persistent" : true, + "insertionIndex" : 231 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58.json new file mode 100644 index 00000000..45ddb184 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58.json @@ -0,0 +1,42 @@ +{ + "id" : "4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"f7e1a0061200814dd08f3193430f2ff3\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZjzG1RIAMETeg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "106", + "X-Amzn-Trace-Id" : "Root=1-69f4094b-6b0ab96e303d09a513da757c;Parent=54208a32104d7fad;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "182", + "Date" : "Fri, 01 May 2026 02:00:43 GMT", + "Via" : "1.1 e1832834d17ab65dd955f4e68cc524e6.cloudfront.net (CloudFront), 1.1 e6b2537b87653726af8a79e6da505188.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094b000000007d7d4537b7d163b9", + "x-amzn-RequestId" : "50b29eeb-7c63-4aaa-9388-3b5069107579", + "X-Amz-Cf-Id" : "MIHvy6AVbyhvD8u7Gp-bMf-t5th1cgyztv7gRq6GOLLtrvzHdEVB2A==", + "Content-Type" : "application/json" + } + }, + "uuid" : "4a72d48b-3cae-4ef7-8b8e-5b8fd10d4f58", + "persistent" : true, + "insertionIndex" : 229 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-5393bfe5-4bf1-461e-b8a1-465085d01c49.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-5393bfe5-4bf1-461e-b8a1-465085d01c49.json new file mode 100644 index 00000000..0e8e410d --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-5393bfe5-4bf1-461e-b8a1-465085d01c49.json @@ -0,0 +1,42 @@ +{ + "id" : "5393bfe5-4bf1-461e-b8a1-465085d01c49", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"b632653772bc2f7fc87f1c681185e259\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-5393bfe5-4bf1-461e-b8a1-465085d01c49.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZk-FjGoAMEp5g=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "127", + "X-Amzn-Trace-Id" : "Root=1-69f40952-61dd4a67567062f82652804a;Parent=64c05b7f426c743d;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "184", + "Date" : "Fri, 01 May 2026 02:00:50 GMT", + "Via" : "1.1 d6022fdb6e8ea3c6fe76398e42003fcc.cloudfront.net (CloudFront), 1.1 e6b2537b87653726af8a79e6da505188.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40952000000006f94fe67f97b7425", + "x-amzn-RequestId" : "ae98538e-be56-4be4-9853-74d85cf62512", + "X-Amz-Cf-Id" : "5rXjCaxzureEW4ByFACqzhtOQ8LvBDCqJdYrJMgjbCgaebG4y8810w==", + "Content-Type" : "application/json" + } + }, + "uuid" : "5393bfe5-4bf1-461e-b8a1-465085d01c49", + "persistent" : true, + "insertionIndex" : 214 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-59482039-37f4-4442-99c1-9e04b823b8f2.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-59482039-37f4-4442-99c1-9e04b823b8f2.json new file mode 100644 index 00000000..7f6e202c --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-59482039-37f4-4442-99c1-9e04b823b8f2.json @@ -0,0 +1,42 @@ +{ + "id" : "59482039-37f4-4442-99c1-9e04b823b8f2", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"1228c5f1e88e0c32c0c8ab0c684899f4\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-59482039-37f4-4442-99c1-9e04b823b8f2.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZjrFwOoAMEf6A=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "248", + "X-Amzn-Trace-Id" : "Root=1-69f4094a-7a578961656fff4439bae7ad;Parent=5418127a61485c3d;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "358", + "Date" : "Fri, 01 May 2026 02:00:42 GMT", + "Via" : "1.1 4c9457912580c6114eec78b8fa604a20.cloudfront.net (CloudFront), 1.1 fbb003dfc0617e3e058e3dac791dfd5a.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094a00000000261b7c474c9e9c81", + "x-amzn-RequestId" : "32e2a6dc-338d-43fe-b4ca-0326fa277b11", + "X-Amz-Cf-Id" : "FGf0JMzuBTJt8tz_12ZJglGird9ozEyi7oeSGLXSwC4lu3ALZHmibg==", + "Content-Type" : "application/json" + } + }, + "uuid" : "59482039-37f4-4442-99c1-9e04b823b8f2", + "persistent" : true, + "insertionIndex" : 230 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-6033d4d7-788c-4085-872c-703987ac568a.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-6033d4d7-788c-4085-872c-703987ac568a.json new file mode 100644 index 00000000..962ce4fd --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-6033d4d7-788c-4085-872c-703987ac568a.json @@ -0,0 +1,42 @@ +{ + "id" : "6033d4d7-788c-4085-872c-703987ac568a", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"82729d662782b2abe7798b4a7e7a890b\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-6033d4d7-788c-4085-872c-703987ac568a.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkpHYKIAMEiMw=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "128", + "X-Amzn-Trace-Id" : "Root=1-69f40950-16b0075020793fb20c2afe56;Parent=273e8a3ce9b5e735;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "208", + "Date" : "Fri, 01 May 2026 02:00:48 GMT", + "Via" : "1.1 4c9457912580c6114eec78b8fa604a20.cloudfront.net (CloudFront), 1.1 b669d9add7767f73665f1f8b7e8cd802.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409500000000021da4ed383c78049", + "x-amzn-RequestId" : "f9e12c46-3025-4d0e-9ae7-658d365d22a1", + "X-Amz-Cf-Id" : "EJXN6XM00K8R-kZVVg9u7EM5_ZUw4VKlgmjQNM8xXIJM3zP0-AiEOQ==", + "Content-Type" : "application/json" + } + }, + "uuid" : "6033d4d7-788c-4085-872c-703987ac568a", + "persistent" : true, + "insertionIndex" : 218 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-60b4ccde-894e-4e19-9d21-7297509e3b50.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-60b4ccde-894e-4e19-9d21-7297509e3b50.json new file mode 100644 index 00000000..03aea504 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-60b4ccde-894e-4e19-9d21-7297509e3b50.json @@ -0,0 +1,42 @@ +{ + "id" : "60b4ccde-894e-4e19-9d21-7297509e3b50", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"89c113ac73753d523d7c41d23f6ca551\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-60b4ccde-894e-4e19-9d21-7297509e3b50.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZvKFDAoAMEktw=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "109", + "X-Amzn-Trace-Id" : "Root=1-69f40993-052ae9c65df7f55f1ae76266;Parent=72e4535730185d0e;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "191", + "Date" : "Fri, 01 May 2026 02:01:56 GMT", + "Via" : "1.1 d08613e1dd8ad614e47875ae31a8af20.cloudfront.net (CloudFront), 1.1 87247d9a9b2f9e51b0c72b364948aefa.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40993000000006c474a3abc765dac", + "x-amzn-RequestId" : "bf4cbf06-112b-47cb-b790-209598c47709", + "X-Amz-Cf-Id" : "L7_OZ0KtgkCsuY-GSMu4drd9SHOqfx0eUvvziGCNHW-2D0TTwEyMyQ==", + "Content-Type" : "application/json" + } + }, + "uuid" : "60b4ccde-894e-4e19-9d21-7297509e3b50", + "persistent" : true, + "insertionIndex" : 204 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-68d639c0-1a36-4b09-835d-70676d8777ed.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-68d639c0-1a36-4b09-835d-70676d8777ed.json new file mode 100644 index 00000000..7c3e661f --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-68d639c0-1a36-4b09-835d-70676d8777ed.json @@ -0,0 +1,42 @@ +{ + "id" : "68d639c0-1a36-4b09-835d-70676d8777ed", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"b22a7064d957f9d37dc9370205a0149a\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-68d639c0-1a36-4b09-835d-70676d8777ed.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZlFExzoAMEUAg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "75", + "X-Amzn-Trace-Id" : "Root=1-69f40953-6c10411174dfdcc9348d4646;Parent=16f6963f16fbc624;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "154", + "Date" : "Fri, 01 May 2026 02:00:51 GMT", + "Via" : "1.1 b7d7903ada432685f0e90f0ca261d864.cloudfront.net (CloudFront), 1.1 d9d466ed70d93f34739969f91577ec74.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40953000000003a5d69af958a0d40", + "x-amzn-RequestId" : "782cb4fd-0017-47ff-b81e-81056d73091b", + "X-Amz-Cf-Id" : "7eB8IlbMOez38uwb4RA65WMMVzBCrL_uCftczFxRoNg3RyMjbhgdpQ==", + "Content-Type" : "application/json" + } + }, + "uuid" : "68d639c0-1a36-4b09-835d-70676d8777ed", + "persistent" : true, + "insertionIndex" : 213 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-7bb21f42-8a57-4177-82cd-1016209bfd11.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-7bb21f42-8a57-4177-82cd-1016209bfd11.json new file mode 100644 index 00000000..06a3b209 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-7bb21f42-8a57-4177-82cd-1016209bfd11.json @@ -0,0 +1,42 @@ +{ + "id" : "7bb21f42-8a57-4177-82cd-1016209bfd11", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"3d0117e321817e50077da93b401b4dff\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-7bb21f42-8a57-4177-82cd-1016209bfd11.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZlKEbooAMEqNA=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "67", + "X-Amzn-Trace-Id" : "Root=1-69f40953-2cdf7d8266fc4dd612dc851c;Parent=2a1b6315dc6ced48;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "144", + "Date" : "Fri, 01 May 2026 02:00:52 GMT", + "Via" : "1.1 e1832834d17ab65dd955f4e68cc524e6.cloudfront.net (CloudFront), 1.1 a624be98cd5b264f373d8ac17f78ee50.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40953000000001859d4faae9c6b05", + "x-amzn-RequestId" : "7de4b9a2-c7a5-4c9d-910a-d7984abe823b", + "X-Amz-Cf-Id" : "iBm37LWJv8IKC4tpBNvjeqH7KfrQPXMn0UBjnn_R8E3ZCYRmbzl5cw==", + "Content-Type" : "application/json" + } + }, + "uuid" : "7bb21f42-8a57-4177-82cd-1016209bfd11", + "persistent" : true, + "insertionIndex" : 212 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-7ca662d0-05aa-47f5-b902-3b99403706e1.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-7ca662d0-05aa-47f5-b902-3b99403706e1.json new file mode 100644 index 00000000..b6644eb6 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-7ca662d0-05aa-47f5-b902-3b99403706e1.json @@ -0,0 +1,46 @@ +{ + "id" : "7ca662d0-05aa-47f5-b902-3b99403706e1", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"d2230fc189d7f2d5ebfef06134107451\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 429, + "bodyFileName" : "btql-7ca662d0-05aa-47f5-b902-3b99403706e1.json", + "headers" : { + "X-Cache" : "Error from cloudfront", + "x-amz-apigw-id" : "cqZp8EXMIAMEQmg=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "434", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "retry-after" : "18.379", + "X-Amzn-Trace-Id" : "Root=1-69f40972-1698195a5abd35eb7fba15f5;Parent=0b3ca787c922b91f;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 02:01:22 GMT", + "Via" : "1.1 4cb8a7f3f7a5d9d545889e0d3926b9c2.cloudfront.net (CloudFront), 1.1 ee5f8da78d4211a93c9dba8864a4067e.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409720000000079c92d615c91ea50", + "x-amzn-RequestId" : "234eb41e-614b-45b9-8b42-053ed9986806", + "X-Amz-Cf-Id" : "-CfFa1ULG-CWyNKG5ujHKihKHvqQZqqQpr3-alCypmC9aOdmDhRcEQ==", + "etag" : "W/\"1b2-m+D8+TpzjkL4bPTyHo1vgvt5DpA\"", + "Content-Type" : "application/json; charset=utf-8" + } + }, + "uuid" : "7ca662d0-05aa-47f5-b902-3b99403706e1", + "persistent" : true, + "scenarioName" : "scenario-1-btql", + "requiredScenarioState" : "scenario-1-btql-2", + "newScenarioState" : "scenario-1-btql-3", + "insertionIndex" : 210 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-84ead815-40e5-4d81-8263-f22066d46681.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-84ead815-40e5-4d81-8263-f22066d46681.json new file mode 100644 index 00000000..23a31c7e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-84ead815-40e5-4d81-8263-f22066d46681.json @@ -0,0 +1,42 @@ +{ + "id" : "84ead815-40e5-4d81-8263-f22066d46681", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"149b4aa496d877681ef62fc9dd6d92b8\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-84ead815-40e5-4d81-8263-f22066d46681.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkFGtJoAMEMAQ=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "138", + "X-Amzn-Trace-Id" : "Root=1-69f4094c-304ee3ec3a2cd0b968dc1e65;Parent=648a307e99227eb5;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "234", + "Date" : "Fri, 01 May 2026 02:00:45 GMT", + "Via" : "1.1 b521abc69f4dd055f355de798c5fb95a.cloudfront.net (CloudFront), 1.1 0df7f27a01014ab815259ca2d88193c6.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094c000000003880fe77c56c7f6a", + "x-amzn-RequestId" : "df40d310-21f9-4bf6-8c7c-0f0dd616d6d2", + "X-Amz-Cf-Id" : "H-uBRuXNB2FCoB_e_vHhCHmIMkmli59jc221se2bBrUspeuRbfyKNw==", + "Content-Type" : "application/json" + } + }, + "uuid" : "84ead815-40e5-4d81-8263-f22066d46681", + "persistent" : true, + "insertionIndex" : 224 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-8a4abae2-50b8-4353-a6be-48a0b86534d7.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-8a4abae2-50b8-4353-a6be-48a0b86534d7.json new file mode 100644 index 00000000..0937c1aa --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-8a4abae2-50b8-4353-a6be-48a0b86534d7.json @@ -0,0 +1,42 @@ +{ + "id" : "8a4abae2-50b8-4353-a6be-48a0b86534d7", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"7beca5cbceb213d06e52458a8efbd6a6\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-8a4abae2-50b8-4353-a6be-48a0b86534d7.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZuyGYgIAMEklA=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "102", + "X-Amzn-Trace-Id" : "Root=1-69f40991-40894b364101955871b30f18;Parent=760aa99bb608c423;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "159", + "Date" : "Fri, 01 May 2026 02:01:53 GMT", + "Via" : "1.1 b521abc69f4dd055f355de798c5fb95a.cloudfront.net (CloudFront), 1.1 170efbc424be9181bda5d0fcd6e41f30.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409910000000072cc13043e50371d", + "x-amzn-RequestId" : "6474387a-a893-489b-80cc-e9e60bbe043c", + "X-Amz-Cf-Id" : "wRSF4ZzOd9L88M5MnBfz4TYN03TrAdeZ7UAQyH9hyJhZ4yEB1QLljg==", + "Content-Type" : "application/json" + } + }, + "uuid" : "8a4abae2-50b8-4353-a6be-48a0b86534d7", + "persistent" : true, + "insertionIndex" : 208 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-8d2c104c-cb77-4f66-b566-f070e2bc9f89.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-8d2c104c-cb77-4f66-b566-f070e2bc9f89.json new file mode 100644 index 00000000..351fa612 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-8d2c104c-cb77-4f66-b566-f070e2bc9f89.json @@ -0,0 +1,42 @@ +{ + "id" : "8d2c104c-cb77-4f66-b566-f070e2bc9f89", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"34deba1a2c0490369061ced793f8f991\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-8d2c104c-cb77-4f66-b566-f070e2bc9f89.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZvWGN2IAMEljg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "117", + "X-Amzn-Trace-Id" : "Root=1-69f40995-402da3ba166eec6d47fbf860;Parent=5d23c0a088ed7a5b;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "194", + "Date" : "Fri, 01 May 2026 02:01:57 GMT", + "Via" : "1.1 2d0eb1433209b25c3712ac0793d56bc0.cloudfront.net (CloudFront), 1.1 e6b2537b87653726af8a79e6da505188.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40995000000001408ecf2a0d3fbac", + "x-amzn-RequestId" : "d2246572-be9c-4073-85d8-7785a2c0c6c5", + "X-Amz-Cf-Id" : "qPQBywTKFjfx005TeGz8okHdx5QWZD5TZ5eRQmPf0q8ELeyr2xmLBg==", + "Content-Type" : "application/json" + } + }, + "uuid" : "8d2c104c-cb77-4f66-b566-f070e2bc9f89", + "persistent" : true, + "insertionIndex" : 202 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-919e3b25-ee0e-498b-af81-d38877cc3168.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-919e3b25-ee0e-498b-af81-d38877cc3168.json new file mode 100644 index 00000000..cf73b701 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-919e3b25-ee0e-498b-af81-d38877cc3168.json @@ -0,0 +1,42 @@ +{ + "id" : "919e3b25-ee0e-498b-af81-d38877cc3168", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"88bd25a8c8635a467403a42dce1462c8\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-919e3b25-ee0e-498b-af81-d38877cc3168.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZjbHnWIAMEqNA=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "252", + "X-Amzn-Trace-Id" : "Root=1-69f40948-5bb8bad21ad8c10c7378185c;Parent=7102baf4d9c994ba;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "417", + "Date" : "Fri, 01 May 2026 02:00:41 GMT", + "Via" : "1.1 d08613e1dd8ad614e47875ae31a8af20.cloudfront.net (CloudFront), 1.1 ee5f8da78d4211a93c9dba8864a4067e.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40948000000007b799ba00c7119df", + "x-amzn-RequestId" : "147d0ace-6478-4636-963c-ee2b8ce911b7", + "X-Amz-Cf-Id" : "0MFytPmUld2-egQbUG5xhrdZT3KACb6jiac0m3-CO_3M-ky9iyND0g==", + "Content-Type" : "application/json" + } + }, + "uuid" : "919e3b25-ee0e-498b-af81-d38877cc3168", + "persistent" : true, + "insertionIndex" : 232 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-9c8e4d4a-daef-4397-bfcb-20703d1d6859.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-9c8e4d4a-daef-4397-bfcb-20703d1d6859.json new file mode 100644 index 00000000..64d258ad --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-9c8e4d4a-daef-4397-bfcb-20703d1d6859.json @@ -0,0 +1,42 @@ +{ + "id" : "9c8e4d4a-daef-4397-bfcb-20703d1d6859", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"d880dd4d4fc907c09a02acfd596e11d6\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-9c8e4d4a-daef-4397-bfcb-20703d1d6859.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZj7GQ-oAMEY8A=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "100", + "X-Amzn-Trace-Id" : "Root=1-69f4094b-6cd8f74a4e52e5a37fae6065;Parent=478278b55321996e;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "180", + "Date" : "Fri, 01 May 2026 02:00:44 GMT", + "Via" : "1.1 dc8ab0490cc3f7679073e847e3aabb66.cloudfront.net (CloudFront), 1.1 83d24992402f7b214901ab76fbdc11e2.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094c0000000057e26288775461fc", + "x-amzn-RequestId" : "d9f4228b-db5f-4800-a9b8-be4511be9d6f", + "X-Amz-Cf-Id" : "wqncnlRCMF-F_IIaqBFJ0r0bdjZLaQv0-ibq5OfcZFAlpKa589aFUA==", + "Content-Type" : "application/json" + } + }, + "uuid" : "9c8e4d4a-daef-4397-bfcb-20703d1d6859", + "persistent" : true, + "insertionIndex" : 227 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-9e3a9f16-cf95-4834-940b-8693fe3a272d.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-9e3a9f16-cf95-4834-940b-8693fe3a272d.json new file mode 100644 index 00000000..a294ef14 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-9e3a9f16-cf95-4834-940b-8693fe3a272d.json @@ -0,0 +1,42 @@ +{ + "id" : "9e3a9f16-cf95-4834-940b-8693fe3a272d", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"bf72462c6e1fefc71baff40f7ba09c0f\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-9e3a9f16-cf95-4834-940b-8693fe3a272d.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkkG3aoAMESkg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "198", + "X-Amzn-Trace-Id" : "Root=1-69f40950-2252e98b5713cd7c1b7334fc;Parent=74fd8a9446f1ba94;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "279", + "Date" : "Fri, 01 May 2026 02:00:48 GMT", + "Via" : "1.1 b7d7903ada432685f0e90f0ca261d864.cloudfront.net (CloudFront), 1.1 a40ac7dad0e348fc93799233c9af5960.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409500000000051569ceb8be1fd31", + "x-amzn-RequestId" : "1754baa8-f3b9-462d-8fc9-fe654ecb5241", + "X-Amz-Cf-Id" : "fWTmyYYangxVZKRUSfA2GtErpHDAq7O4e9PiTrL2DN3cAoTMa0DzCg==", + "Content-Type" : "application/json" + } + }, + "uuid" : "9e3a9f16-cf95-4834-940b-8693fe3a272d", + "persistent" : true, + "insertionIndex" : 219 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-a8bba708-a70d-4fac-8923-59dd75e076d7.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-a8bba708-a70d-4fac-8923-59dd75e076d7.json new file mode 100644 index 00000000..5e9b4d5d --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-a8bba708-a70d-4fac-8923-59dd75e076d7.json @@ -0,0 +1,42 @@ +{ + "id" : "a8bba708-a70d-4fac-8923-59dd75e076d7", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"1180ea2e316c253b507c3168d0ed1314\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-a8bba708-a70d-4fac-8923-59dd75e076d7.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZu-GiuIAMEBrg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "107", + "X-Amzn-Trace-Id" : "Root=1-69f40992-2410e49e6a6f567a5d95913a;Parent=4e30c96b78420378;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "162", + "Date" : "Fri, 01 May 2026 02:01:54 GMT", + "Via" : "1.1 79a7455da856598d6db0b6edabec6574.cloudfront.net (CloudFront), 1.1 73b0c4a85645a8031ba157e0b3e28ffc.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40992000000003dc14437cd838c4f", + "x-amzn-RequestId" : "1a3f50cf-5deb-4e71-812c-076fc15545de", + "X-Amz-Cf-Id" : "FqH1fmFLtxvTWwqU6NGObtkhetCe-pC-A3u8m4qRYWY8oDQ7AXBjMw==", + "Content-Type" : "application/json" + } + }, + "uuid" : "a8bba708-a70d-4fac-8923-59dd75e076d7", + "persistent" : true, + "insertionIndex" : 206 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-ad59251c-c69e-43d3-b47b-df055eedaf64.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-ad59251c-c69e-43d3-b47b-df055eedaf64.json new file mode 100644 index 00000000..856e4043 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-ad59251c-c69e-43d3-b47b-df055eedaf64.json @@ -0,0 +1,42 @@ +{ + "id" : "ad59251c-c69e-43d3-b47b-df055eedaf64", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"7bcf3207e4f8f95d723ef4181011ca77\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-ad59251c-c69e-43d3-b47b-df055eedaf64.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZk6FOxIAMEhnQ=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "161", + "X-Amzn-Trace-Id" : "Root=1-69f40952-46b1dbac45cb771213db34ee;Parent=4d97463d69cfab83;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "240", + "Date" : "Fri, 01 May 2026 02:00:50 GMT", + "Via" : "1.1 d6022fdb6e8ea3c6fe76398e42003fcc.cloudfront.net (CloudFront), 1.1 da32b45f2cc22dc818960285c4e91b66.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409520000000059a86c1d27cc6f07", + "x-amzn-RequestId" : "e8145f75-6e63-4694-a7c2-c85563e17837", + "X-Amz-Cf-Id" : "VuUhCgp3H_95SB-2vBQyQDL-plfr8RV5Px2elBMfXDkj4kQPHEJvzg==", + "Content-Type" : "application/json" + } + }, + "uuid" : "ad59251c-c69e-43d3-b47b-df055eedaf64", + "persistent" : true, + "insertionIndex" : 215 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01.json new file mode 100644 index 00000000..5ae83f00 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01.json @@ -0,0 +1,42 @@ +{ + "id" : "bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"5508034ed459194168972ce4558b50d8\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZu4GUIoAMEJ-g=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "113", + "X-Amzn-Trace-Id" : "Root=1-69f40992-72563b7916c85b592b74cf43;Parent=52e577d0b7ef86b8;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "166", + "Date" : "Fri, 01 May 2026 02:01:54 GMT", + "Via" : "1.1 d6022fdb6e8ea3c6fe76398e42003fcc.cloudfront.net (CloudFront), 1.1 7605973575a3551426b82751020317de.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409920000000054d4a7316d0f6f5f", + "x-amzn-RequestId" : "be19d93d-30ac-4055-b4fb-90c6c8159413", + "X-Amz-Cf-Id" : "Tg5iejPZPtn_C9xga43E_Ktv96yX-gxJ6WHD9vRCQ4GOCQLKmlo8Ww==", + "Content-Type" : "application/json" + } + }, + "uuid" : "bcb44ee1-3ff5-4ea6-8ff4-d778f087bb01", + "persistent" : true, + "insertionIndex" : 207 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c.json new file mode 100644 index 00000000..39a4246c --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c.json @@ -0,0 +1,42 @@ +{ + "id" : "cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"d6a1fcdbf7e04d0a61b930a91f0f2ae4\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkBFqqIAMED1g=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "79", + "X-Amzn-Trace-Id" : "Root=1-69f4094c-7872f8ab6082a0cc35678e6d;Parent=52c8364164f69a91;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "135", + "Date" : "Fri, 01 May 2026 02:00:44 GMT", + "Via" : "1.1 21c7c4234f218bb5110262cbbf01f870.cloudfront.net (CloudFront), 1.1 d9d466ed70d93f34739969f91577ec74.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094c0000000025da37f5ed7b9e08", + "x-amzn-RequestId" : "60e39c74-33af-4117-a696-71b7cc86b0c6", + "X-Amz-Cf-Id" : "4w9kuf1QZQo4gba7mAo0GszB3_3eV2yayAedHN0Ij9CpXqXdAH5Bmg==", + "Content-Type" : "application/json" + } + }, + "uuid" : "cb7d37cd-a97b-4a1d-ac84-1d9380b7f52c", + "persistent" : true, + "insertionIndex" : 226 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-cfcaea09-e7ba-484d-ae5e-2bd7658ea802.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-cfcaea09-e7ba-484d-ae5e-2bd7658ea802.json new file mode 100644 index 00000000..b2b508a5 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-cfcaea09-e7ba-484d-ae5e-2bd7658ea802.json @@ -0,0 +1,46 @@ +{ + "id" : "cfcaea09-e7ba-484d-ae5e-2bd7658ea802", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"d2230fc189d7f2d5ebfef06134107451\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 429, + "bodyFileName" : "btql-cfcaea09-e7ba-484d-ae5e-2bd7658ea802.json", + "headers" : { + "X-Cache" : "Error from cloudfront", + "x-amz-apigw-id" : "cqZlNEU_IAMEAHg=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "433", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "retry-after" : "48.63", + "X-Amzn-Trace-Id" : "Root=1-69f40954-6ec6beab18c9196e65a5d97c;Parent=338fded29681b4bb;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 02:00:52 GMT", + "Via" : "1.1 b7d7903ada432685f0e90f0ca261d864.cloudfront.net (CloudFront), 1.1 4ac8d091dce10e726cfc5404bfed72b8.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409540000000029c2838ad2baa5ba", + "x-amzn-RequestId" : "58a27f37-2e16-44f4-bf56-ab3eb602bb97", + "X-Amz-Cf-Id" : "S85tHstNeZMCsNg5GJfY-n19zZri9AeBv9yA4HKty4GqLC6CZ_zehA==", + "etag" : "W/\"1b1-zfC5xSjKa4W0hXHaW+Q8MEExOpA\"", + "Content-Type" : "application/json; charset=utf-8" + } + }, + "uuid" : "cfcaea09-e7ba-484d-ae5e-2bd7658ea802", + "persistent" : true, + "scenarioName" : "scenario-1-btql", + "requiredScenarioState" : "Started", + "newScenarioState" : "scenario-1-btql-2", + "insertionIndex" : 211 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-d0da1ce5-e44b-468d-beee-da3fa3009421.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-d0da1ce5-e44b-468d-beee-da3fa3009421.json new file mode 100644 index 00000000..21af183a --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-d0da1ce5-e44b-468d-beee-da3fa3009421.json @@ -0,0 +1,42 @@ +{ + "id" : "d0da1ce5-e44b-468d-beee-da3fa3009421", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"c57d627498d6bdfd5121b5eb3233bf34\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-d0da1ce5-e44b-468d-beee-da3fa3009421.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZviHutoAMEA9w=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "95", + "X-Amzn-Trace-Id" : "Root=1-69f40996-38194aa4364605e0477bada1;Parent=34637f1460e74e7c;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "183", + "Date" : "Fri, 01 May 2026 02:01:58 GMT", + "Via" : "1.1 a642518ef4d5fb78c3190de112922a38.cloudfront.net (CloudFront), 1.1 e6b2537b87653726af8a79e6da505188.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40996000000007ee027f75c1b7939", + "x-amzn-RequestId" : "05621c9c-5fdc-486f-869b-ab73b7037028", + "X-Amz-Cf-Id" : "snX-w8Pudcx9_8ezfnQNgREGcajV4aTgTI2db5OSevK_MBTKZoJUsw==", + "Content-Type" : "application/json" + } + }, + "uuid" : "d0da1ce5-e44b-468d-beee-da3fa3009421", + "persistent" : true, + "insertionIndex" : 200 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df.json new file mode 100644 index 00000000..d8cc857e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df.json @@ -0,0 +1,42 @@ +{ + "id" : "d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"eccfa89fac5ee2e478063165e115eb0f\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZk0G7boAMEogg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "96", + "X-Amzn-Trace-Id" : "Root=1-69f40951-6705c7ab7f95ae241db170f8;Parent=5dc2689abf8f5716;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "176", + "Date" : "Fri, 01 May 2026 02:00:49 GMT", + "Via" : "1.1 4c9457912580c6114eec78b8fa604a20.cloudfront.net (CloudFront), 1.1 ddea1c07643e5e0bfceb34480eebdc52.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40951000000004090ae63e923dc53", + "x-amzn-RequestId" : "31c5d61a-0acc-4d31-a570-7c17c8aabca5", + "X-Amz-Cf-Id" : "7wgkF7CciK_YKu7cZu-qO-h2-lIDic-EpgCUKD35Ql9fN1NyUxq53g==", + "Content-Type" : "application/json" + } + }, + "uuid" : "d4cd76c0-cc2b-4ec7-85fb-1b2c5b6a16df", + "persistent" : true, + "insertionIndex" : 216 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-de950214-054b-43b2-aaf2-2d5ac103ddee.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-de950214-054b-43b2-aaf2-2d5ac103ddee.json new file mode 100644 index 00000000..50d364e4 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-de950214-054b-43b2-aaf2-2d5ac103ddee.json @@ -0,0 +1,42 @@ +{ + "id" : "de950214-054b-43b2-aaf2-2d5ac103ddee", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"b86bf0a74edbecfa09a2ca45f8c9b498\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-de950214-054b-43b2-aaf2-2d5ac103ddee.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkWETNoAMEU1g=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "350", + "X-Amzn-Trace-Id" : "Root=1-69f4094e-772767be32674dc62a18a4af;Parent=01626a8a81558975;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "427", + "Date" : "Fri, 01 May 2026 02:00:47 GMT", + "Via" : "1.1 2d0eb1433209b25c3712ac0793d56bc0.cloudfront.net (CloudFront), 1.1 e6b2537b87653726af8a79e6da505188.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094e000000000b9810299b6b46c2", + "x-amzn-RequestId" : "2fbe1e9b-4f81-4351-8f9f-c0f5670e9ccf", + "X-Amz-Cf-Id" : "cT1KMlEAP7bIa0i3tXWXNXV-I72ZpBOAqz_-ayM4pZLF7CC-fwyALw==", + "Content-Type" : "application/json" + } + }, + "uuid" : "de950214-054b-43b2-aaf2-2d5ac103ddee", + "persistent" : true, + "insertionIndex" : 221 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e109b114-6ad2-4317-8680-7688991365a3.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e109b114-6ad2-4317-8680-7688991365a3.json new file mode 100644 index 00000000..45dcf9cb --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e109b114-6ad2-4317-8680-7688991365a3.json @@ -0,0 +1,42 @@ +{ + "id" : "e109b114-6ad2-4317-8680-7688991365a3", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"380b9957ee917f5845ff9d0914b7d388\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-e109b114-6ad2-4317-8680-7688991365a3.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZvQFg2IAMEpKA=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "111", + "X-Amzn-Trace-Id" : "Root=1-69f40994-1ba5ed16075246c16fe6b1e7;Parent=63421467c720441f;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "218", + "Date" : "Fri, 01 May 2026 02:01:56 GMT", + "Via" : "1.1 b7d7903ada432685f0e90f0ca261d864.cloudfront.net (CloudFront), 1.1 74e8c76139b8c7f9b11d5e4441c2a7a2.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40994000000005d1f97b4e3a078b0", + "x-amzn-RequestId" : "cfe5ba9b-af0d-482a-ba19-2f7f4725532a", + "X-Amz-Cf-Id" : "QyDaBWsCg0-Ci4D4tsyZ3OrFaIldwq5T8daAjKKwgh6HcskNrMSbLQ==", + "Content-Type" : "application/json" + } + }, + "uuid" : "e109b114-6ad2-4317-8680-7688991365a3", + "persistent" : true, + "insertionIndex" : 203 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e1844750-b874-4ef6-bd98-f3779a0c7f4a.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e1844750-b874-4ef6-bd98-f3779a0c7f4a.json new file mode 100644 index 00000000..f0d03434 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e1844750-b874-4ef6-bd98-f3779a0c7f4a.json @@ -0,0 +1,42 @@ +{ + "id" : "e1844750-b874-4ef6-bd98-f3779a0c7f4a", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"4a96d0f41b537b117968f413b234d028\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-e1844750-b874-4ef6-bd98-f3779a0c7f4a.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkKEeeoAMEhdw=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "284", + "X-Amzn-Trace-Id" : "Root=1-69f4094d-2e791b2e4978deea088af94b;Parent=40d7e630b319f8a8;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "337", + "Date" : "Fri, 01 May 2026 02:00:45 GMT", + "Via" : "1.1 b521abc69f4dd055f355de798c5fb95a.cloudfront.net (CloudFront), 1.1 ee5f8da78d4211a93c9dba8864a4067e.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094d000000007c2a559238bbf666", + "x-amzn-RequestId" : "09177b2c-ea7b-408d-8ded-d43b1d4bfecf", + "X-Amz-Cf-Id" : "a38w46UiX5AQL3aiNUeUGnLEbjKosot_edgXKI9aqjuk6MEhaJyStA==", + "Content-Type" : "application/json" + } + }, + "uuid" : "e1844750-b874-4ef6-bd98-f3779a0c7f4a", + "persistent" : true, + "insertionIndex" : 223 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e7c1f7f0-59ae-4a71-96c1-50177219feca.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e7c1f7f0-59ae-4a71-96c1-50177219feca.json new file mode 100644 index 00000000..d35fa0b7 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-e7c1f7f0-59ae-4a71-96c1-50177219feca.json @@ -0,0 +1,42 @@ +{ + "id" : "e7c1f7f0-59ae-4a71-96c1-50177219feca", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"acd28eb57b7b26a0885f1cbc6dbbfc07\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-e7c1f7f0-59ae-4a71-96c1-50177219feca.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkeHMqoAMEmlA=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "161", + "X-Amzn-Trace-Id" : "Root=1-69f4094f-07a5ca331da75e4729b82829;Parent=5747b6fda784f651;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "225", + "Date" : "Fri, 01 May 2026 02:00:47 GMT", + "Via" : "1.1 4c9457912580c6114eec78b8fa604a20.cloudfront.net (CloudFront), 1.1 ddea1c07643e5e0bfceb34480eebdc52.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094f0000000042c7fc266773880c", + "x-amzn-RequestId" : "77284d5e-081b-4291-9f9f-84023cdf1ffe", + "X-Amz-Cf-Id" : "YdAo7rhOZKK79WKB7y9cjRztgFHk7_i674bKzClvl3VKkKvG8ZdmrA==", + "Content-Type" : "application/json" + } + }, + "uuid" : "e7c1f7f0-59ae-4a71-96c1-50177219feca", + "persistent" : true, + "insertionIndex" : 220 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-efaeb6e5-57f2-40e7-9688-755c63baf7d0.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-efaeb6e5-57f2-40e7-9688-755c63baf7d0.json new file mode 100644 index 00000000..9f52dad0 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-efaeb6e5-57f2-40e7-9688-755c63baf7d0.json @@ -0,0 +1,44 @@ +{ + "id" : "efaeb6e5-57f2-40e7-9688-755c63baf7d0", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"d2230fc189d7f2d5ebfef06134107451\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-efaeb6e5-57f2-40e7-9688-755c63baf7d0.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZutH2wIAMEmNQ=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "120", + "X-Amzn-Trace-Id" : "Root=1-69f40990-2a84607074dde21a4970d975;Parent=6233b139d9d42b65;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "200", + "Date" : "Fri, 01 May 2026 02:01:53 GMT", + "Via" : "1.1 4c9457912580c6114eec78b8fa604a20.cloudfront.net (CloudFront), 1.1 96f6dcbb4d7267cad6eb0747bce72024.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409900000000040b9b231d6e823ff", + "x-amzn-RequestId" : "9a0d5306-2cf6-41aa-8e84-52b97690743f", + "X-Amz-Cf-Id" : "Ve6n-WxM0exl5IzJZV6h2RYeB2AaGFdfSviveqvi0VVfZPPsntdA8Q==", + "Content-Type" : "application/json" + } + }, + "uuid" : "efaeb6e5-57f2-40e7-9688-755c63baf7d0", + "persistent" : true, + "scenarioName" : "scenario-1-btql", + "requiredScenarioState" : "scenario-1-btql-3", + "insertionIndex" : 209 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-f5c05ce0-0947-49ec-b437-0ccaeda6bbe6.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-f5c05ce0-0947-49ec-b437-0ccaeda6bbe6.json new file mode 100644 index 00000000..7d472ab1 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-f5c05ce0-0947-49ec-b437-0ccaeda6bbe6.json @@ -0,0 +1,42 @@ +{ + "id" : "f5c05ce0-0947-49ec-b437-0ccaeda6bbe6", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"db0e36fd13d0ccbb323ad7482348e0b3\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-f5c05ce0-0947-49ec-b437-0ccaeda6bbe6.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZvdHuqIAMETMg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "81", + "X-Amzn-Trace-Id" : "Root=1-69f40995-406eb9532b015d9f681e3356;Parent=19444f5b55bb8275;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "141", + "Date" : "Fri, 01 May 2026 02:01:57 GMT", + "Via" : "1.1 d6022fdb6e8ea3c6fe76398e42003fcc.cloudfront.net (CloudFront), 1.1 ee5f8da78d4211a93c9dba8864a4067e.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4099500000000035b7ace350aaf92", + "x-amzn-RequestId" : "87648a9c-7831-43da-9d0a-8ab368c541aa", + "X-Amz-Cf-Id" : "Ziux7yh--g25F8-CG-6Q9PnLSFqhnHjtRef7A4COFW7OgHK8RAqY0w==", + "Content-Type" : "application/json" + } + }, + "uuid" : "f5c05ce0-0947-49ec-b437-0ccaeda6bbe6", + "persistent" : true, + "insertionIndex" : 201 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-faf9b0bc-7f71-4a39-b6ca-26b62a647163.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-faf9b0bc-7f71-4a39-b6ca-26b62a647163.json new file mode 100644 index 00000000..d5455d75 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/btql-faf9b0bc-7f71-4a39-b6ca-26b62a647163.json @@ -0,0 +1,42 @@ +{ + "id" : "faf9b0bc-7f71-4a39-b6ca-26b62a647163", + "name" : "btql", + "request" : { + "url" : "/btql", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"query\":{\"select\":[{\"op\":\"star\"}],\"from\":{\"name\":{\"op\":\"ident\",\"name\":[\"project_logs\"]},\"op\":\"function\",\"args\":[{\"op\":\"literal\",\"value\":\"6ae68365-7620-4630-921b-bac416634fc8\"}]},\"filter\":{\"right\":{\"right\":{\"op\":\"literal\",\"value\":null},\"left\":{\"op\":\"ident\",\"name\":[\"span_parents\"]},\"op\":\"ne\"},\"left\":{\"right\":{\"op\":\"literal\",\"value\":\"ee58e3ff2b397c9b7fa3e9f3a18faa0e\"},\"left\":{\"op\":\"ident\",\"name\":[\"root_span_id\"]},\"op\":\"eq\"},\"op\":\"and\"},\"sort\":[{\"expr\":{\"op\":\"ident\",\"name\":[\"created\"]},\"dir\":\"asc\"}],\"limit\":1000},\"use_columnstore\":true,\"use_brainstore\":true,\"brainstore_realtime\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "btql-faf9b0bc-7f71-4a39-b6ca-26b62a647163.json", + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkuFhJIAMEaNg=", + "vary" : "Origin", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "x-bt-brainstore-duration-ms" : "97", + "X-Amzn-Trace-Id" : "Root=1-69f40951-7ca1cb873305462b059c5029;Parent=22e5a4a184ee7dbd;Sampled=0;Lineage=1:24be3d11:0", + "x-bt-api-duration-ms" : "177", + "Date" : "Fri, 01 May 2026 02:00:49 GMT", + "Via" : "1.1 21c7c4234f218bb5110262cbbf01f870.cloudfront.net (CloudFront), 1.1 73b0c4a85645a8031ba157e0b3e28ffc.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4095100000000201265e64ab4c9cd", + "x-amzn-RequestId" : "1c1f566b-70c1-4b1f-a21e-3b23718298a7", + "X-Amz-Cf-Id" : "aoaGsbI5I12Ut91SiqTaU8-Ybh9492DjT_5NMoYElrlcU2qbfKCuDw==", + "Content-Type" : "application/json" + } + }, + "uuid" : "faf9b0bc-7f71-4a39-b6ca-26b62a647163", + "persistent" : true, + "insertionIndex" : 217 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-0dc779a9-c4c6-4d33-a27e-be1470d944d4.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-0dc779a9-c4c6-4d33-a27e-be1470d944d4.json new file mode 100644 index 00000000..822493b3 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-0dc779a9-c4c6-4d33-a27e-be1470d944d4.json @@ -0,0 +1,39 @@ +{ + "id" : "0dc779a9-c4c6-4d33-a27e-be1470d944d4", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CsUZCrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKNGAoRCg9icmFpbnRydXN0LWphdmES9xcKEBGA6i4xbCU7UHwxaNDtExQSCDganW4KxP6NIgj4x0JHSseb0CoJcmVzcG9uc2VzMAE5tjhdf4ROqxhBVu6fBYlOqxhK+xIKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S4BIK3RJbeyJpZCI6InJzXzA1OGYzNWVlMzUwYTk5OWIwMDY5ZjQwOTI5YWMzODgxOTNiOTU2OGNkZjcwYjAyYjU0IiwidHlwZSI6InJlYXNvbmluZyIsInN1bW1hcnkiOlt7InR5cGUiOiJzdW1tYXJ5X3RleHQiLCJ0ZXh0IjoiKipBbmFseXppbmcgYSBudW1iZXIgc2VxdWVuY2UqKlxuXG5UaGUgdXNlciBwcmVzZW50ZWQgbWUgd2l0aCBhIHNlcXVlbmNlOiAyLCA2LCAxMiwgMjAsIDMwLiBJJ20gdHJ5aW5nIHRvIGZpbmQgdGhlIHBhdHRlcm4gYW5kIGEgZm9ybXVsYSBmb3IgdGhlIG50aCB0ZXJtLiBJdCBsb29rcyBsaWtlIHRoZXNlIG51bWJlcnMgY29ycmVzcG9uZCB0byB0cmlhbmd1bGFyIG51bWJlcnMgbXVsdGlwbGllZCBieSAyLiBJbiBmYWN0LCB0aGV5IGZvbGxvdyB0aGUgZm9ybXVsYTogbihuICsgMSkgd2hpY2ggc2ltcGxpZmllcyB0byBuXjIgKyBuLiBKdXN0IHRvIGNsYXJpZnksIHRyaWFuZ3VsYXIgbnVtYmVycyBmb2xsb3cgdGhlIGZvcm11bGEgVF9uID0gbihuICsgMSkvMi4gQmFzZWQgb24gdGhpcywgSSBzZWUgdGhhdCB0aGUgZ2l2ZW4gc2VxdWVuY2UgaXMgZXNzZW50aWFsbHkgdHdpY2UgZWFjaCB0cmlhbmd1bGFyIG51bWJlci4ifSx7InR5cGUiOiJzdW1tYXJ5X3RleHQiLCJ0ZXh0IjoiKipDbGFyaWZ5aW5nIHRoZSBzZXF1ZW5jZSBwYXR0ZXJuKipcblxuSSdtIGJyZWFraW5nIGRvd24gdGhlIHNlcXVlbmNlIDIsIDYsIDEyLCAyMCwgMzAuIEkgc2VlIG5vdyB0aGF0IGl0IGVxdWFscyAyIHRpbWVzIHRoZSB0cmlhbmd1bGFyIG51bWJlcnM6IDIgPSAyw5cxLCA2ID0gMsOXMywgZXRjLiBUaGUgZm9ybXVsYSBmb3IgdGhlIG50aCB0ZXJtIGlzIGFfbiA9IG4obiArIDEpLCBhbmQgaXQgY2FuIGFsc28gYmUgZGVzY3JpYmVkIGJ5IG9ic2VydmluZyB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0ZXJtczogNCwgNiwgOCwgMTAsIHdoaWNoIGluY3JlYXNlIGJ5IDIgZWFjaCB0aW1lLiBUaGlzIGNvbnNpc3RlbmN5IGluZGljYXRlcyBpdCdzIGEgcXVhZHJhdGljIHNlcXVlbmNlLiBUaGUgZmluYWwgY29uY2x1c2lvbiBpcyB0aGF0IHRoZSBwYXR0ZXJuIHJlcHJlc2VudHMgcmVjdGFuZ3VsYXIgbnVtYmVycywgY29uZmlybWluZyB0aGUgZm9ybXVsYSBpcyBhX24gPSBuKG4gKyAxKS4ifSx7InR5cGUiOiJzdW1tYXJ5X3RleHQiLCJ0ZXh0IjoiKipTb2x2aW5nIGZvciB0aGUgc2VxdWVuY2UqKlxuXG5J4oCZbSB3b3JraW5nIG9uIHRoZSBzZXF1ZW5jZSBhbmQgc2V0dGluZyB1cCBlcXVhdGlvbnMgYmFzZWQgb24gdGhlIHJlbGF0aW9uc2hpcHMgSSBzZWUuIEkndmUgZXN0YWJsaXNoZWQgdGhhdCBiIGNhbiBiZSBleHByZXNzZWQgaW4gdGVybXMgb2YgYSBhbmQgZGVyaXZlZCBlcXVhdGlvbnMgdGhhdCBzaW1wbGlmeSBkb3duIHRvIGEgPSAxIGFuZCBiID0gMSwgd2l0aCBjIGVxdWFsaW5nIDAuIFNvLCBJJ3ZlIGRldGVybWluZWQgdGhlIG50aCB0ZXJtIGZvcm11bGEgaXMgYV9uID0gbihuICsgMSksIHdoaWNoIHJldmVhbHMgdGhlIHBhdHRlcm4gb2YgcHJvbmljIG51bWJlcnMsIGJlaW5nIHRoZSBwcm9kdWN0IG9mIHR3byBjb25zZWN1dGl2ZSBpbnRlZ2Vycywgc3BlY2lmaWNhbGx5OiAyLCA2LCAxMiwgMjAsIDMwLi4uIEp1c3QgdG8gY2xhcmlmeSwgdGhlIGZpbmFsIGZvcm11bGEgdXNpbmcgaW5kZXhpbmcgZnJvbSAxIGlzIGFfbiA9IG4obiArIDEpLiJ9XX0seyJpZCI6Im1zZ18wNThmMzVlZTM1MGE5OTliMDA2OWY0MDkzYWYxNTQ4MTkzOTc4M2U2MDBhNDNmNTEzMyIsInR5cGUiOiJtZXNzYWdlIiwic3RhdHVzIjoiY29tcGxldGVkIiwiY29udGVudCI6W3sidHlwZSI6Im91dHB1dF90ZXh0IiwiYW5ub3RhdGlvbnMiOltdLCJsb2dwcm9icyI6W10sInRleHQiOiJUaGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBzdWNjZXNzaXZlIHRlcm1zIGFyZVxuXG4gNuKAkzIgPSA0LCAgXG4xMuKAkzYgPSA2LCAgXG4yMOKAkzEyID0gOCwgIFxuMzDigJMyMCA9IDEwLCAgXG5cbnNvIHRoZSDigJxzdGVw4oCQc2l6ZXPigJ0gYXJlIHRoZSBldmVuIG51bWJlcnMgNCw2LDgsMTAs4oCmIChpLmUuIHRoZXkgaW5jcmVhc2UgYnkgMiBlYWNoIHRpbWUpLiAgQW55IHNlcXVlbmNlIHdob3NlIHNlY29uZCBkaWZmZXJlbmNlIGlzIGNvbnN0YW50IGlzIGEgcXVhZHJhdGljLCBhbmQgaW4gZmFjdCBvbmUgY2hlY2tzIHRoYXRcblxuIDIgPSAxwrcyLCAgXG4gNiA9IDLCtzMsICBcbjEyID0gM8K3NCwgIFxuMjAgPSA0wrc1LCAgXG4zMCA9IDXCtzYsXG5cbnNvIHRoZSBudGggdGVybSBpcyB0aGUgcHJvZHVjdCBvZiB0d28gY29uc2VjdXRpdmUgaW50ZWdlcnMuICBJZiB3ZSBzdGFydCBjb3VudGluZyBhdCBuPTEsIHRoZSBmb3JtdWxhIGlzXG5cbiAgYeKCmSA9IG7igIkobiArIDEpID0gbsKyICsgbi4ifV0sInJvbGUiOiJhc3Npc3RhbnQifV1KoQEKE2JyYWludHJ1c3QubWV0YWRhdGESiQEKhgF7InByb3ZpZGVyIjoib3BlbmFpIiwicmVxdWVzdF9wYXRoIjoicmVzcG9uc2VzIiwibW9kZWwiOiJvNC1taW5pIiwicmVxdWVzdF9iYXNlX3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6Mzk4OTMiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUqpAQoVYnJhaW50cnVzdC5pbnB1dF9qc29uEo8BCowBW3sicm9sZSI6InVzZXIiLCJjb250ZW50IjoiTG9vayBhdCB0aGlzIHNlcXVlbmNlOiAyLCA2LCAxMiwgMjAsIDMwLiBXaGF0IGlzIHRoZSBwYXR0ZXJuIGFuZCB3aGF0IHdvdWxkIGJlIHRoZSBmb3JtdWxhIGZvciB0aGUgbnRoIHRlcm0/XG4ifV1KdgoSYnJhaW50cnVzdC5tZXRyaWNzEmAKXnsiY29tcGxldGlvbl90b2tlbnMiOjE2MTEsInByb21wdF90b2tlbnMiOjQxLCJ0b2tlbnMiOjE2NTIsImNvbXBsZXRpb25fcmVhc29uaW5nX3Rva2VucyI6MTQwOH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAA=" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZhlEVYIAMEc6A=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4093c-25c852796a77af6f1a0360d3;Parent=50a62496a8f4149e;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 02:00:29 GMT", + "Via" : "1.1 2d0eb1433209b25c3712ac0793d56bc0.cloudfront.net (CloudFront), 1.1 ee5f8da78d4211a93c9dba8864a4067e.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4093c0000000079500891b1a40e14", + "x-amzn-RequestId" : "5126ef74-5aa3-417d-b327-c50991fe6cb0", + "X-Amz-Cf-Id" : "hP0Yr0fT3l99UodDz9C9q3uqJUr_WaJtadt5KaX0Cin6TX0q3dMBEw==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "0dc779a9-c4c6-4d33-a27e-be1470d944d4", + "persistent" : true, + "insertionIndex" : 233 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-24d38c9a-65ac-46b4-8a76-8361fcefb5eb.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-24d38c9a-65ac-46b4-8a76-8361fcefb5eb.json new file mode 100644 index 00000000..e8f5bd05 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-24d38c9a-65ac-46b4-8a76-8361fcefb5eb.json @@ -0,0 +1,39 @@ +{ + "id" : "24d38c9a-65ac-46b4-8a76-8361fcefb5eb", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CsIWCrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKKFQoRCg9icmFpbnRydXN0LWphdmES9BQKEFUIA07UWRlBaJcs5FWLUNgSCE2GHDqBuYKjIgg0J8g0+dVX2CoJcmVzcG9uc2VzMAE5rtS4uHlOqxhBSu5CQIJOqxhK+A8KFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S3Q8K2g9beyJpZCI6InJzXzBiYTQ2NDhmYmIyYTMyYWIwMDY5ZjQwOGZiMDdlNDgxOTVhOTljNjM0NjY2M2JjNDVhIiwidHlwZSI6InJlYXNvbmluZyIsInN1bW1hcnkiOlt7InR5cGUiOiJzdW1tYXJ5X3RleHQiLCJ0ZXh0IjoiKipBbmFseXppbmcgdGhlIHNlcXVlbmNlKipcblxuVGhlIHVzZXIgcHJlc2VudHMgdGhlIHNlcXVlbmNlOiAyLCA2LCAxMiwgMjAsIDMwLCB3aGljaCBjb3JyZXNwb25kcyB0byBwcm9uaWMgb3Igb2Jsb25nIG51bWJlcnMgZXhwcmVzc2VkIGFzIG4obisxKS4gRm9yIGV4YW1wbGUsIDEqMj0yLCAyKjM9NiwgMyo0PTEyLCBhbmQgc28gZm9ydGguIFRoZSBmb3JtdWxhIGZvciB0aGUgbnRoIHRlcm0gaXMgYShuKSA9IG4obisxKS4gSSBub3RpY2UgdGhhdCB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBjb25zZWN1dGl2ZSB0ZXJtcyAoNCwgNiwgOCwgMTApIGFyZSBldmVuIG51bWJlcnMgc3RhcnRpbmcgYXQgNCwgaW5kaWNhdGluZyBhIGNvbnNpc3RlbnQgaW5jcmVhc2UuIElmIG4gc3RhcnRzIGF0IDAsIHRoZW4gYShuKSA9IG4obisxKSwgd2hpY2ggcmVzdWx0cyBpbiAwIGF0IG49MC4ifSx7InR5cGUiOiJzdW1tYXJ5X3RleHQiLCJ0ZXh0IjoiKipFeHBsb3JpbmcgdGhlIHBhdHRlcm4gb2YgdGhlIHNlcXVlbmNlKipcblxuU3RhcnRpbmcgd2l0aCBuPTEsIHRoZSBwYXR0ZXJuIG1pcnJvcnMgbsKyK24sIGxlYWRpbmcgdG8gdGhlIGZvcm11bGEgYShuKSA9IG4obisxKSBmb3IgcHJvbmljIG51bWJlcnMuIFRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRlcm1zICg0LCA2LCA4LCAxMC4uLikgZm9ybSBhbiBhcml0aG1ldGljIHNlcXVlbmNlLCBpbmNyZWFzaW5nIGJ5IDIgZWFjaCB0aW1lLiBTbywgSSBjYW4gY2xlYXJseSBzdGF0ZSB0aGF0IHRoZSBudGggdGVybSBpcyB0aGUgcHJvZHVjdCBvZiBjb25zZWN1dGl2ZSBpbnRlZ2Vycywgd2l0aCBhIHNpbXBsZSBhbHRlcm5hdGl2ZSBleHByZXNzaW9uLiBXaGVuIGluZGV4ZWQgZnJvbSB6ZXJvLCB0aGUgZm9ybXVsYSBzaGlmdHMuIFVsdGltYXRlbHksIHdoYXQgc3RhbmRzIG91dCBpcyB0aGF0IGVhY2ggdGVybSBmb2xsb3dzIHRoZSByZWxhdGlvbnNoaXAgYV9uID0gbihuKzEpLiJ9LHsidHlwZSI6InN1bW1hcnlfdGV4dCIsInRleHQiOiIqKkRlZmluaW5nIHRoZSBzZXF1ZW5jZSBwYXR0ZXJuKipcblxuVGhlIHNlcXVlbmNlIHJlcHJlc2VudHMgcHJvbmljIG51bWJlcnMsIHdoZXJlIGVhY2ggdGVybSwgc3RhcnRpbmcgZnJvbSBuPTEsIGZvbGxvd3MgdGhlIGZvcm11bGEgYV9uID0gbihuKzEpLiBUaGVzZSBudW1iZXJzIGFyZSB0aGUgcHJvZHVjdHMgb2YgY29uc2VjdXRpdmUgaW50ZWdlcnM6IDIgYXMgMcOXMiwgNiBhcyAyw5czLCBhbmQgMTIgYXMgM8OXNC4gSWYgSSB1c2VkIGEgemVyby1iYXNlZCBpbmRleCwgSSdkIHNheSBhX24gPSBuKG4rMSkgcHJvZHVjZXMgYV8wPTAsIGJ1dCBzaW5jZSB0aGUgc2VxdWVuY2Ugc3RhcnRzIGF0IG49MSwgdGhlIGZpcnN0IHRlcm0gaXMgMi4gU28sIHRoZSBmaW5hbCBjb25jbHVzaW9uIGlzIHRoYXQgcHJvbmljIG51bWJlcnMgYXJlIGRlZmluZWQgYnkgYV9uID0gbihuKzEpLiJ9XX0seyJpZCI6Im1zZ18wYmE0NjQ4ZmJiMmEzMmFiMDA2OWY0MDkxOWNjNjA4MTk1YjBmYjg3NWQ4OGZkZDI4MCIsInR5cGUiOiJtZXNzYWdlIiwic3RhdHVzIjoiY29tcGxldGVkIiwiY29udGVudCI6W3sidHlwZSI6Im91dHB1dF90ZXh0IiwiYW5ub3RhdGlvbnMiOltdLCJsb2dwcm9icyI6W10sInRleHQiOiJFYWNoIHRlcm0gaXMgdGhlIHByb2R1Y3Qgb2YgdHdvIGNvbnNlY3V0aXZlIGludGVnZXJzOlxuXG4yID0gMcOXMiAgXG42ID0gMsOXMyAgXG4xMiA9IDPDlzQgIFxuMjAgPSA0w5c1ICBcbjMwID0gNcOXNiAgXG5cblNvIGlmIHlvdSBsYWJlbCB0aGUgdGVybXMgYeKCgSwgYeKCgiwgYeKCgywg4oCmIHRoZW5cblxu4oCDYeKCmSA9IG7igIkobisxKS5cblxuRXF1aXZhbGVudGx5LCBh4oKZID0gbsKyICsgbi4ifV0sInJvbGUiOiJhc3Npc3RhbnQifV1KoQEKE2JyYWludHJ1c3QubWV0YWRhdGESiQEKhgF7InByb3ZpZGVyIjoib3BlbmFpIiwicmVxdWVzdF9wYXRoIjoicmVzcG9uc2VzIiwibW9kZWwiOiJvNC1taW5pIiwicmVxdWVzdF9iYXNlX3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6Mzk4OTMiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUqpAQoVYnJhaW50cnVzdC5pbnB1dF9qc29uEo8BCowBW3sicm9sZSI6InVzZXIiLCJjb250ZW50IjoiTG9vayBhdCB0aGlzIHNlcXVlbmNlOiAyLCA2LCAxMiwgMjAsIDMwLiBXaGF0IGlzIHRoZSBwYXR0ZXJuIGFuZCB3aGF0IHdvdWxkIGJlIHRoZSBmb3JtdWxhIGZvciB0aGUgbnRoIHRlcm0/XG4ifV1KdgoSYnJhaW50cnVzdC5tZXRyaWNzEmAKXnsiY29tcGxldGlvbl90b2tlbnMiOjEyODYsInByb21wdF90b2tlbnMiOjQxLCJ0b2tlbnMiOjEzMjcsImNvbXBsZXRpb25fcmVhc29uaW5nX3Rva2VucyI6MTE1Mn1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAA=" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZdcFzyoAMEfqw=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f40922-70468c0e469cf9a626f381e1;Parent=7850182c85deb76d;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 02:00:02 GMT", + "Via" : "1.1 2d0eb1433209b25c3712ac0793d56bc0.cloudfront.net (CloudFront), 1.1 a624be98cd5b264f373d8ac17f78ee50.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40922000000002c5766c51deba7a7", + "x-amzn-RequestId" : "04e4807a-3caa-4277-9c01-9285f8340a85", + "X-Amz-Cf-Id" : "SdnDpAX9fvbo7mZF1KQ6tSpa6Zjq2BWzI9mFxVYKqHoEBWw7npoh5Q==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "24d38c9a-65ac-46b4-8a76-8361fcefb5eb", + "persistent" : true, + "insertionIndex" : 235 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-3b0b6a2c-c723-47e0-b2ad-850ffc55da6f.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-3b0b6a2c-c723-47e0-b2ad-850ffc55da6f.json new file mode 100644 index 00000000..e8904976 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-3b0b6a2c-c723-47e0-b2ad-850ffc55da6f.json @@ -0,0 +1,39 @@ +{ + "id" : "3b0b6a2c-c723-47e0-b2ad-850ffc55da6f", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CpApCrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKVAQoFCgNidHgSiwEKEHvspcvOshPQblJFio771qYSCAdwK7hcmaoYKglyZWFzb25pbmcwATm56s5FeE6rGEE+VSgogE6rGEoSCgZjbGllbnQSCAoGb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEsAmChEKD2JyYWludHJ1c3QtamF2YRKqJgoQe+yly86yE9BuUkWKjvvWphII3uJOmmmjYq4iCAdwK7hcmaoYKglyZXNwb25zZXMwATkE+YJhfE6rGEHsQCgngE6rGErCDgoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhKnDgqkDlt7ImlkIjoicnNfMDIyMjdkYTUxYzNmZDI1ODAwNjlmNDA5MDc5NmU4ODE5Njk3N2NiM2VjY2U5ZDk1NDUiLCJ0eXBlIjoicmVhc29uaW5nIiwic3VtbWFyeSI6W3sidHlwZSI6InN1bW1hcnlfdGV4dCIsInRleHQiOiIqKkNhbGN1bGF0aW5nIHRoZSAxMHRoIHRlcm0gYW5kIHRoZSBzdW0qKlxuXG5UaGUgdXNlciB3YW50cyB0byBrbm93IHRoZSAxMHRoIHRlcm0gb2YgdGhlIHNlcXVlbmNlIGFuZCB0aGUgc3VtIG9mIHRoZSBmaXJzdCAxMCB0ZXJtcy4gRnJvbSBvdXIgZWFybGllciB3b3JrLCB3ZSd2ZSBmaWd1cmVkIG91dCB0aGF0IHRoZSAxMHRoIHRlcm0gaXMgYV97MTB9ID0gMTAgKiAxMSA9IDExMC4gXG5cbkZvciB0aGUgc3VtIG9mIHRoZSBmaXJzdCAxMCB0ZXJtcywgd2UgY2FuIGNhbGN1bGF0ZSBpdCBkaXJlY3RseSwgZmluZGluZyB0aGF0IHRoZSByZXN1bHQgaXMgNDQwLiBBbHRlcm5hdGl2ZWx5LCB3ZSBkaXNjb3ZlcmVkIGEgbmVhdCBmb3JtdWxhIGZvciB0aGUgc3VtIG9mIHRoZSBmaXJzdCBuIHRlcm1zLCB3aGljaCBhbHNvIGdpdmVzIDQ0MCB3aGVuIG49MTAuIFNvLCB0aGUgZmluYWwgYW5zd2VycyBhcmU6IDEwdGggdGVybSA9IDExMCBhbmQgc3VtIG9mIGZpcnN0IDEwIHRlcm1zID0gNDQwLiJ9LHsidHlwZSI6InN1bW1hcnlfdGV4dCIsInRleHQiOiIqKkRlcml2aW5nIHRoZSAxMHRoIHRlcm0gYW5kIHN1bSoqXG5cbkxldCdzIHNob3cgdGhlIGRlcml2YXRpb24gY2xlYXJseS4gVGhlIGZvcm11bGEgZm9yIHRoZSBudGggdGVybSBpcyBhX24gPSBuKG4rMSkuIFNvLCBmb3IgdGhlIDEwdGggdGVybSwgd2UgY2FsY3VsYXRlIGFfezEwfSA9IDEwICogMTEgPSAxMTAuIFxuXG5Gb3IgdGhlIHN1bSBTXzEwIG9mIHRoZSBmaXJzdCAxMCB0ZXJtcywgd2UgaGF2ZSBTXzEwID0g4oiRbihuKzEpLCB3aGljaCBicmVha3MgZG93biBpbnRvIOKIkW5eMiArIOKIkW4gPSAzODUgKyA1NSA9IDQ0MC4gQWxzbywgSSBjYW4gcHJvdmlkZSB0aGUgZ2VuZXJhbCBmb3JtdWxhIGZvciB0aGUgc3VtOiDiiJFfe2s9MX1ebiBrKGsrMSkgPSBuKG4rMSkobisyKS8zLiBGb3Igbj0xMCwgd2UgZmluZCAxMCoxMSoxMi8zID0gNDQwLiBTbyB0aGUgYW5zd2VycyBhcmU6IDEwdGggdGVybSA9IDExMCwgc3VtIG9mIGZpcnN0IDEwID0gNDQwLiJ9XX0seyJpZCI6Im1zZ18wMjIyN2RhNTFjM2ZkMjU4MDA2OWY0MDkxNGMyM2M4MTk2OTc4YmM1MjhmNmM4MGZkYyIsInR5cGUiOiJtZXNzYWdlIiwic3RhdHVzIjoiY29tcGxldGVkIiwiY29udGVudCI6W3sidHlwZSI6Im91dHB1dF90ZXh0IiwiYW5ub3RhdGlvbnMiOltdLCJsb2dwcm9icyI6W10sInRleHQiOiJUaGUgbnRoIHRlcm0gaXMgIFxuICBh4oKZID0gbihuICsgMSkuICBcblxuU28gZm9yIG4gPSAxMDogIFxuICBh4oKB4oKAID0gMTDCtzExID0gMTEwLiAgXG5cblRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zIGlzICBcbiAgU+KCgeKCgCA9IOKIkeKCluKCjOKCgcK54oGwIGsoayArIDEpICBcbiAgICAgID0g4oiR4oKW4oKM4oKBwrnigbAgKGvCsiArIGspICBcbiAgICAgID0gKOKIkeKCluKCjOKCgcK54oGwIGvCsikgKyAo4oiR4oKW4oKM4oKBwrnigbAgaykgIFxuICAgICAgPSBbMTDCtzExwrcyMS82XSArIFsxMMK3MTEvMl0gIFxuICAgICAgPSAzODUgKyA1NSAgXG4gICAgICA9IDQ0MC4gIFxuXG5FcXVpdmFsZW50bHksIG9uZSBjYW4gdXNlIHRoZSBjbG9zZWTigJBmb3JtICBcbiAg4oiR4oKW4oKM4oKB4oG/IGsoayArIDEpID0gbihuICsgMSkobiArIDIpLzMgIFxuc28gZm9yIG49MTA6IDEwwrcxMcK3MTIvMyA9IDQ0MC4ifV0sInJvbGUiOiJhc3Npc3RhbnQifV1KoQEKE2JyYWludHJ1c3QubWV0YWRhdGESiQEKhgF7InByb3ZpZGVyIjoib3BlbmFpIiwicmVxdWVzdF9wYXRoIjoicmVzcG9uc2VzIiwibW9kZWwiOiJvNC1taW5pIiwicmVxdWVzdF9iYXNlX3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6Mzk4OTMiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUqXFAoVYnJhaW50cnVzdC5pbnB1dF9qc29uEv0TCvoTW3sicm9sZSI6InVzZXIiLCJjb250ZW50IjoiTG9vayBhdCB0aGlzIHNlcXVlbmNlOiAyLCA2LCAxMiwgMjAsIDMwLiBXaGF0IGlzIHRoZSBwYXR0ZXJuIGFuZCB3aGF0IHdvdWxkIGJlIHRoZSBmb3JtdWxhIGZvciB0aGUgbnRoIHRlcm0/XG4ifSx7ImlkIjoicnNfMDIyMjdkYTUxYzNmZDI1ODAwNjlmNDA4ZjU1NjQwODE5NmIyZGI2MWU3MzJhZDg2YTYiLCJzdW1tYXJ5IjpbeyJ0ZXh0IjoiKipBbmFseXppbmcgYSBudW1iZXIgc2VxdWVuY2UqKlxuXG5UaGUgdXNlciBwcm92aWRlZCB0aGUgc2VxdWVuY2U6IDIsIDYsIDEyLCAyMCwgMzAsIGFuZCBJJ20gdHJ5aW5nIHRvIGZpbmQgdGhlIHBhdHRlcm4gYW5kIGZvcm11bGEgZm9yIHRoZSBudGggdGVybS4gSSBub3RpY2UgdGhpcyBzZXF1ZW5jZSBzZWVtcyB0byBiZSB0d2ljZSB0aGUgdHJpYW5ndWxhciBudW1iZXJzLCB3aGljaCBhcmUgZ2VuZXJhdGVkIGJ5IHRoZSBmb3JtdWxhIG4obisxKS8yLiBXaGVuIEkgYXBwbHkgdGhhdCwgSSBzZWUgdGhhdCBlYWNoIHRlcm0gY29ycmVzcG9uZHMgdG8gdGhlIHRyaWFuZ3VsYXIgbnVtYmVyIG11bHRpcGxpZWQgYnkgMi4gQWRkaXRpb25hbGx5LCB0aGUgZGlmZmVyZW5jZXMgc3VnZ2VzdCBpdCdzIGEgcXVhZHJhdGljIHNlcXVlbmNlLCBjb25maXJtaW5nIHRoZSBudW1iZXJzIGFyZSBwcm9uaWMgbnVtYmVycywgcHJvZHVjdHMgb2YgY29uc2VjdXRpdmUgaW50ZWdlcnMuIiwidHlwZSI6InN1bW1hcnlfdGV4dCJ9LHsidGV4dCI6IioqRmluZGluZyB0aGUgdGVybSBmb3JtdWxhKipcblxuVGhlIGZvcm11bGEgZm9yIHRoZSBzZXF1ZW5jZSBpcyBhX24gPSBuKG4gKyAxKS4gV2hlbiBzdGFydGluZyBmcm9tIG49MSwgSSBzZWUgaXQgZ2l2ZXMgdGhlIGZpcnN0IHRlcm0sIDIuIFRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRlcm1zIGluY3JlYXNlIGJ5IDIgZWFjaCB0aW1lLCBjb25maXJtaW5nIHRoZXkgYXJlIHByb25pYyBudW1iZXJzLiBCeSBicmVha2luZyBpdCBkb3duIGZ1cnRoZXIsIEkgcmVhbGl6ZSB0aGVzZSBjYW4gYWxzbyBiZSBleHByZXNzZWQgYXMgdHdpY2UgdGhlIHRyaWFuZ3VsYXIgbnVtYmVycy4gVGhlIGRpZmZlcmVuY2Ugc2VxdWVuY2UgaXMgNCwgNiwgOCwgMTAsIHNob3dpbmcgaXQncyBxdWFkcmF0aWMuIFVsdGltYXRlbHksIEkgY29uY2x1ZGU6IGFfbiA9IG4obiArIDEpIGZvciB0aGUgc2VxdWVuY2UgMiwgNiwgMTIsIDIwLCAzMC4iLCJ0eXBlIjoic3VtbWFyeV90ZXh0In0seyJ0ZXh0IjoiKipTdW1tYXJpemluZyB0aGUgc2VxdWVuY2UgcGF0dGVybioqXG5cblRoZSBwYXR0ZXJuIGluIHRoaXMgc2VxdWVuY2UgaXMgZm91bmQgaW4gdGhlIHN1Y2Nlc3NpdmUgZGlmZmVyZW5jZXMsIHdoaWNoIGFyZSBldmVuIG51bWJlcnM6IDQsIDYsIDgsIDEwLiBUaGlzIGxlYWRzIHRvIHRoZSBjb25jbHVzaW9uIHRoYXQgYV9uID0gbl4yICsgbiwgb3IgbW9yZSBzaW1wbHksIGFfbiA9IG4obiArIDEpLiBBbHRob3VnaCB0aGVyZSdzIGEgY29uc2lkZXJhdGlvbiBmb3Igc3RhcnRpbmcgYXQgbj0wLCBpdCB0eXBpY2FsbHkgYmVnaW5zIGF0IG49MS4gSSBjYW4gYWxzbyBleHByZXNzIGl0IGFzIHR3aWNlIHRoZSB0cmlhbmd1bGFyIG51bWJlcnM6IGFfbiA9IDJUX24uIFVsdGltYXRlbHksIHRoZSBhbnN3ZXIgaXMgYV9uID0gbihuICsgMSkgZm9yIHRoZSB0ZXJtcyAyLCA2LCAxMiwgYW5kIHNvIG9uLiIsInR5cGUiOiJzdW1tYXJ5X3RleHQifV0sInR5cGUiOiJyZWFzb25pbmcifSx7ImlkIjoibXNnXzAyMjI3ZGE1MWMzZmQyNTgwMDY5ZjQwOTAyZDdlYzgxOTY4ZDExZDkxMjRiYjQwNDNlIiwiY29udGVudCI6W3siYW5ub3RhdGlvbnMiOltdLCJ0ZXh0IjoiVGhlIOKAnGdhcHPigJ0gYmV0d2VlbiB0ZXJtcyBhcmUgIFxuIDbiiJIyPTQsIDEy4oiSNj02LCAyMOKIkjEyPTgsIDMw4oiSMjA9MTAsIOKApiAgXG5pLmUuIHRoZSBkaWZmZXJlbmNlcyBhcmUgNCzigIk2LOKAiTgs4oCJMTAsIOKApiBzbyB0aGUgc2Vjb25kIGRpZmZlcmVuY2UgaXMgY29uc3RhbnQgKDIpIGFuZCB0aGUgc2VxdWVuY2UgaXMgcXVhZHJhdGljLiAgU29sdmluZyBvciBub3RpbmcgdGhhdCBpdOKAmXMgdHdpY2UgdGhlIHRyaWFuZ3VsYXIgbnVtYmVycyBnaXZlc1xuXG4gIGHigpkgPSAywrcobihuKzEpLzIpID0gbihuKzEpLlxuXG5JZiB5b3Ugc3RhcnQgY291bnRpbmcgYXQgbj0xIHRoaXMgaW5kZWVkIHlpZWxkcyAgXG4gIGHigoEgPSAxwrcyID0gMiwgIFxuICBh4oKCID0gMsK3MyA9IDYsICBcbiAgYeKCgyA9IDPCtzQgPSAxMiwgIOKApiAgXG5cblNvIHRoZSBudGggdGVybSBpcyAgYeKCmSA9IG4obisxKS4iLCJ0eXBlIjoib3V0cHV0X3RleHQiLCJsb2dwcm9icyI6W119XSwicm9sZSI6ImFzc2lzdGFudCIsInN0YXR1cyI6ImNvbXBsZXRlZCIsInR5cGUiOiJtZXNzYWdlIn0seyJyb2xlIjoidXNlciIsImNvbnRlbnQiOiJVc2luZyB0aGUgcGF0dGVybiB5b3UgZGlzY292ZXJlZCwgd2hhdCB3b3VsZCBiZSB0aGUgMTB0aCB0ZXJtPyBBbmQgY2FuIHlvdSBmaW5kIHRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zPyJ9XUp0ChJicmFpbnRydXN0Lm1ldHJpY3MSXgpceyJjb21wbGV0aW9uX3Rva2VucyI6Njk2LCJwcm9tcHRfdG9rZW5zIjoyNTgsInRva2VucyI6OTU0LCJjb21wbGV0aW9uX3JlYXNvbmluZ190b2tlbnMiOjQ0OH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAA=" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZb1GrZoAMEFqA=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f40918-03b036a6094b0fca3378742c;Parent=5384ca44a88e633b;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 01:59:52 GMT", + "Via" : "1.1 21c7c4234f218bb5110262cbbf01f870.cloudfront.net (CloudFront), 1.1 d9d466ed70d93f34739969f91577ec74.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40918000000006296838770277ebe", + "x-amzn-RequestId" : "b9cfdb28-ba12-43fe-aa1a-405fd5269dcd", + "X-Amz-Cf-Id" : "sQ3e8dgL3-jz8W1t-RrY_cwvdWVsOgMtKNQOyHw0eBHgJ4_sEwofuA==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "3b0b6a2c-c723-47e0-b2ad-850ffc55da6f", + "persistent" : true, + "insertionIndex" : 236 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-400677f9-7745-4316-8fcf-fc716be486e7.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-400677f9-7745-4316-8fcf-fc716be486e7.json new file mode 100644 index 00000000..daba11f1 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-400677f9-7745-4316-8fcf-fc716be486e7.json @@ -0,0 +1,39 @@ +{ + "id" : "400677f9-7745-4316-8fcf-fc716be486e7", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CtwMCrgBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAooCg9zZXJ2aWNlLnZlcnNpb24SFQoTMC4zLjQtYjIyODA5ZS1ESVJUWQogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKeCwoRCg9icmFpbnRydXN0LWphdmESiAsKENnFJ/2GwzzxQbJgt9yBvM8SCFFaMBC4w+RqKhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5bBJuzep/qxhB43i3e+t/qxhKyQUKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SrgUKqwV7ImlkIjoibXNnXzAxM3YzZmdzM01aUUNXUDZQMmpGdG9MbyIsImNvbnRlbnQiOlt7ImNpdGF0aW9ucyI6bnVsbCwidGV4dCI6IlRoZSBjYXBpdGFsIG9mIEZyYW5jZSBpcyAqKlBhcmlzKiouIEl0IGlzIGxvY2F0ZWQgaW4gdGhlIG5vcnRoLWNlbnRyYWwgcGFydCBvZiB0aGUgY291bnRyeSBhbG9uZyB0aGUgU2VpbmUgUml2ZXIgYW5kIGlzIHRoZSBsYXJnZXN0IGNpdHkgaW4gRnJhbmNlLiIsInR5cGUiOiJ0ZXh0IiwidmFsaWQiOnRydWV9XSwibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxIiwicm9sZSI6ImFzc2lzdGFudCIsInN0b3BfcmVhc29uIjoiZW5kX3R1cm4iLCJzdG9wX3NlcXVlbmNlIjpudWxsLCJ0eXBlIjoibWVzc2FnZSIsInVzYWdlIjp7ImNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMiOjAsImlucHV0X3Rva2VucyI6MTksIm91dHB1dF90b2tlbnMiOjM2LCJzZXJ2ZXJfdG9vbF91c2UiOm51bGwsInNlcnZpY2VfdGllciI6InN0YW5kYXJkIiwidmFsaWQiOnRydWUsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIiwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH19LCJ2YWxpZCI6dHJ1ZSwic3RvcF9kZXRhaWxzIjpudWxsfUqYAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKAAQp+eyJwcm92aWRlciI6ImFudGhyb3BpYyIsInJlcXVlc3RfcGF0aCI6InYxL21lc3NhZ2VzIiwibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01IiwicmVxdWVzdF9iYXNlX3VyaSI6IiIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SpEBChVicmFpbnRydXN0LmlucHV0X2pzb24SeAp2W3siY29udGVudCI6IldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlPyIsInJvbGUiOiJ1c2VyIn0seyJyb2xlIjoic3lzdGVtIiwiY29udGVudCI6IllvdSBhcmUgYSBoZWxwZnVsIGFzc2lzdGFudCJ9XUrTAQoSYnJhaW50cnVzdC5tZXRyaWNzErwBCrkBeyJjb21wbGV0aW9uX3Rva2VucyI6MzYsInByb21wdF90b2tlbnMiOjE5LCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fMWhfdG9rZW5zIjowLCJwcm9tcHRfY2FjaGVkX3Rva2VucyI6MCwidG9rZW5zIjo1NSwidGltZV90b19maXJzdF90b2tlbiI6MC4wMDgwOTIzOCwicHJvbXB0X2NhY2hlX2NyZWF0aW9uXzVtX3Rva2VucyI6MH1KLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAA=" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cseFsEM7IAMEbQw=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4dd57-35af459139022c3812d2e0b3;Parent=4f937720bf96e133;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 17:05:27 GMT", + "Via" : "1.1 487082619948f670d3b30fb3db8fbabc.cloudfront.net (CloudFront), 1.1 a40ac7dad0e348fc93799233c9af5960.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4dd5700000000788f3116ea724408", + "x-amzn-RequestId" : "0d1712f4-6515-493e-a9dd-802bf663c14c", + "X-Amz-Cf-Id" : "HVSEmI4hhIs0e6EaqekEbDaonQ6JIX3mk3HLceVUnoEaV8ZXAxgOZQ==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "400677f9-7745-4316-8fcf-fc716be486e7", + "persistent" : true, + "insertionIndex" : 245 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-42c4b63d-ce6a-4de4-964e-0b3295b9f697.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-42c4b63d-ce6a-4de4-964e-0b3295b9f697.json new file mode 100644 index 00000000..8a41601a --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-42c4b63d-ce6a-4de4-964e-0b3295b9f697.json @@ -0,0 +1,39 @@ +{ + "id" : "42c4b63d-ce6a-4de4-964e-0b3295b9f697", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CuM0CrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKDBwoFCgNidHgSkQEKENsONv0T0My7MjrXSCNI4LMSCKAMw/oJ4A2JKgV0b29sczABOfIRrNJ3TqsYQU0fgCF4TqsYShwKBmNsaWVudBISChBsYW5nY2hhaW4tb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEo0BChCCcp1mJ4Kyq+d5i0p+eokLEghcsTUN9zJKKSoLYXR0YWNobWVudHMwATlEwqzSd06rGEFTlgI3eE6rGEoSCgZjbGllbnQSCAoGZ29vZ2xlSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEpYBChDSIw/Bidfy1ev+8GE0EHRREgiP0H8/xdD6pyoLY29tcGxldGlvbnMwATnPEazSd06rGEECfMtFeE6rGEobCgZjbGllbnQSEQoPc3ByaW5nYWktb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEpABChDFfWJ0mNa9/VEhtesyM780Egik+tXT0y6CJSoFdG9vbHMwATmhpokheE6rGEH5/NxReE6rGEobCgZjbGllbnQSEQoPc3ByaW5nYWktb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEpIBChDuWOP/Kzl8m3+j6fOhj6oOEgjhrolF2mUVsioQZ2VuZXJhdGVfY29udGVudDABOVh3Bjd4TqsYQbA6SoF4TqsYShIKBmNsaWVudBIICgZnb29nbGVKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASlAEKEDgLmVfukX9YRf+dCRS304gSCA29p9svl+G2KglzdHJlYW1pbmcwATksEX9SeE6rGEEpkyvDeE6rGEobCgZjbGllbnQSEQoPc3ByaW5nYWktb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEqUsChEKD2JyYWludHJ1c3QtamF2YRLaBgoQ2w42/RPQzLsyOtdII0jgsxII7urnPzod5KwiCKAMw/oJ4A2JKg9DaGF0IENvbXBsZXRpb24wAzm8B1PXd06rGEEK8YQgeE6rGEq/AgoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhKkAgqhAlt7ImluZGV4IjowLCJtZXNzYWdlIjp7InJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZW50IjpudWxsLCJ0b29sX2NhbGxzIjpbeyJpZCI6ImNhbGxfZmFVTXZuR2RHcU56RzZHbzh6UWQ3VmdhIiwidHlwZSI6ImZ1bmN0aW9uIiwiZnVuY3Rpb24iOnsibmFtZSI6ImdldF93ZWF0aGVyIiwiYXJndW1lbnRzIjoie1wibG9jYXRpb25cIjpcIlBhcmlzLCBGcmFuY2VcIn0ifX1dLCJyZWZ1c2FsIjpudWxsLCJhbm5vdGF0aW9ucyI6W119LCJsb2dwcm9icyI6bnVsbCwiZmluaXNoX3JlYXNvbiI6InRvb2xfY2FsbHMifV1KpwEKE2JyYWludHJ1c3QubWV0YWRhdGESjwEKjAF7InByb3ZpZGVyIjoib3BlbmFpIiwicmVxdWVzdF9wYXRoIjoiY2hhdC9jb21wbGV0aW9ucyIsIm1vZGVsIjoiZ3B0LTRvIiwicmVxdWVzdF9iYXNlX3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6Mzk4OTMiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUpjChVicmFpbnRydXN0LmlucHV0X2pzb24SSgpIW3sicm9sZSI6InVzZXIiLCJjb250ZW50IjoiV2hhdCBpcyB0aGUgd2VhdGhlciBsaWtlIGluIFBhcmlzLCBGcmFuY2U/In1dSlAKEmJyYWludHJ1c3QubWV0cmljcxI6Cjh7ImNvbXBsZXRpb25fdG9rZW5zIjoxNiwicHJvbXB0X3Rva2VucyI6ODUsInRva2VucyI6MTAxfUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3RKLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn16AIUBAQEAABLOCQoQgnKdZieCsqvneYtKfnqJCxIIKgg1Xvc/5jYiCFyxNQ33MkopKhBnZW5lcmF0ZV9jb250ZW50MAM5lmpU13dOqxhB/tSBM3hOqxhKjwQKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S9AMK8QN7ImNhbmRpZGF0ZXMiOlt7ImNvbnRlbnQiOnsicGFydHMiOlt7InRleHQiOiJUaGUgY29sb3Igb2YgdGhlIGltYWdlIGlzIHJlZC4iLCJ0aG91Z2h0U2lnbmF0dXJlIjoiRWpRS01nRU1PZGJIRWxhaHM1U0RiTE1mYjNxbEt0a2cwdFloV1d0Q054djZ6YVFlbUo4YlVINWF3T3VkS0NvckJmYVBOTFlEIn1dLCJyb2xlIjoibW9kZWwifSwiZmluaXNoUmVhc29uIjoiU1RPUCIsImluZGV4IjowfV0sInVzYWdlTWV0YWRhdGEiOnsicHJvbXB0VG9rZW5Db3VudCI6MTA5NiwiY2FuZGlkYXRlc1Rva2VuQ291bnQiOjgsInRvdGFsVG9rZW5Db3VudCI6MTEwNCwicHJvbXB0VG9rZW5zRGV0YWlscyI6W3sibW9kYWxpdHkiOiJJTUFHRSIsInRva2VuQ291bnQiOjEwODl9LHsibW9kYWxpdHkiOiJURVhUIiwidG9rZW5Db3VudCI6N31dfSwibW9kZWxWZXJzaW9uIjoiZ2VtaW5pLTMuMS1mbGFzaC1saXRlLXByZXZpZXciLCJyZXNwb25zZUlkIjoiOHdqMGFjbmdLX1NVNmRrUF80YThzQWcifUpoChNicmFpbnRydXN0Lm1ldGFkYXRhElEKT3sicHJvdmlkZXIiOiJnZW1pbmkiLCJ0ZW1wZXJhdHVyZSI6MC4wLCJtb2RlbCI6ImdlbWluaS0zLjEtZmxhc2gtbGl0ZS1wcmV2aWV3In1KwQIKFWJyYWludHJ1c3QuaW5wdXRfanNvbhKnAgqkAnsiY29udGVudHMiOlt7InBhcnRzIjpbeyJ0ZXh0IjoiV2hhdCBjb2xvciBpcyB0aGlzIGltYWdlPyJ9LHsiaW5saW5lRGF0YSI6eyJkYXRhIjoiaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFFQUFBQUJDQVlBQUFBZkZjU0pBQUFBRFVsRVFWUjQybVA4ejhEd0h3QUZCUUlBWDhqeDBnQUFBQUJKUlU1RXJrSmdnZz09IiwibWltZVR5cGUiOiJpbWFnZS9wbmcifX1dLCJyb2xlIjoidXNlciJ9XSwibW9kZWwiOiJnZW1pbmktMy4xLWZsYXNoLWxpdGUtcHJldmlldyIsImNvbmZpZyI6eyJ0ZW1wZXJhdHVyZSI6MC4wfX1KUgoSYnJhaW50cnVzdC5tZXRyaWNzEjwKOnsiY29tcGxldGlvbl90b2tlbnMiOjgsInByb21wdF90b2tlbnMiOjEwOTYsInRva2VucyI6MTEwNH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egIYAYUBAQEAABKKBgoQ0iMPwYnX8tXr/vBhNBB0URIIg2q7WXoWYPYiCI/Qfz/F0PqnKg9DaGF0IENvbXBsZXRpb24wATkoNnsSeE6rGEF2nP9DeE6rGEq9AQoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhKiAQqfAVt7ImluZGV4IjowLCJtZXNzYWdlIjp7InJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZW50IjoiVGhlIGNhcGl0YWwgb2YgRnJhbmNlIGlzIFBhcmlzLiIsInJlZnVzYWwiOm51bGwsImFubm90YXRpb25zIjpbXX0sImxvZ3Byb2JzIjpudWxsLCJmaW5pc2hfcmVhc29uIjoic3RvcCJ9XUqsAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKUAQqRAXsicHJvdmlkZXIiOiJvcGVuYWkiLCJyZXF1ZXN0X3BhdGgiOiJjaGF0L2NvbXBsZXRpb25zIiwibW9kZWwiOiJncHQtNG8tbWluaSIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KkQEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJ4CnZbeyJjb250ZW50IjoieW91IGFyZSBhIGhlbHBmdWwgYXNzaXN0YW50Iiwicm9sZSI6InN5c3RlbSJ9LHsiY29udGVudCI6IldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlPyIsInJvbGUiOiJ1c2VyIn1dSk4KEmJyYWludHJ1c3QubWV0cmljcxI4CjZ7ImNvbXBsZXRpb25fdG9rZW5zIjo3LCJwcm9tcHRfdG9rZW5zIjoyMywidG9rZW5zIjozMH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAAS2gYKEMV9YnSY1r39USG16zIzvzQSCDsKsTEgGhKIIgik+tXT0y6CJSoPQ2hhdCBDb21wbGV0aW9uMAE5B2EtJHhOqxhBvuJWUHhOqxhKvwIKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SpAIKoQJbeyJpbmRleCI6MCwibWVzc2FnZSI6eyJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6bnVsbCwidG9vbF9jYWxscyI6W3siaWQiOiJjYWxsX0pzYWhSRFFFdkQ1bU1EOElxSmpKWkNpZiIsInR5cGUiOiJmdW5jdGlvbiIsImZ1bmN0aW9uIjp7Im5hbWUiOiJnZXRfd2VhdGhlciIsImFyZ3VtZW50cyI6IntcImxvY2F0aW9uXCI6XCJQYXJpcywgRnJhbmNlXCJ9In19XSwicmVmdXNhbCI6bnVsbCwiYW5ub3RhdGlvbnMiOltdfSwibG9ncHJvYnMiOm51bGwsImZpbmlzaF9yZWFzb24iOiJ0b29sX2NhbGxzIn1dSqcBChNicmFpbnRydXN0Lm1ldGFkYXRhEo8BCowBeyJwcm92aWRlciI6Im9wZW5haSIsInJlcXVlc3RfcGF0aCI6ImNoYXQvY29tcGxldGlvbnMiLCJtb2RlbCI6ImdwdC00byIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KYwoVYnJhaW50cnVzdC5pbnB1dF9qc29uEkoKSFt7ImNvbnRlbnQiOiJXaGF0IGlzIHRoZSB3ZWF0aGVyIGxpa2UgaW4gUGFyaXMsIEZyYW5jZT8iLCJyb2xlIjoidXNlciJ9XUpQChJicmFpbnRydXN0Lm1ldHJpY3MSOgo4eyJjb21wbGV0aW9uX3Rva2VucyI6MTYsInByb21wdF90b2tlbnMiOjg1LCJ0b2tlbnMiOjEwMX1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAASkQgKEO5Y4/8rOXybf6Pp86GPqg4SCAKGc3S1LsXwIgjhrolF2mUVsioQZ2VuZXJhdGVfY29udGVudDADOZ4lFjd4TqsYQa+NNoF4TqsYSuQDChZicmFpbnRydXN0Lm91dHB1dF9qc29uEskDCsYDeyJjYW5kaWRhdGVzIjpbeyJjb250ZW50Ijp7InBhcnRzIjpbeyJ0ZXh0IjoiVGhlIGNhcGl0YWwgb2YgRnJhbmNlIGlzIFBhcmlzLiIsInRob3VnaHRTaWduYXR1cmUiOiJFalFLTWdFTU9kYkhPV25ONDFTTTZBSXliNkdKNGZ4YnJWSTE0UzN4ampsMDFVaGQ1SmpsOTQrSWhocml2Q0ZYKzBhNzl1VHcifV0sInJvbGUiOiJtb2RlbCJ9LCJmaW5pc2hSZWFzb24iOiJTVE9QIiwiaW5kZXgiOjB9XSwidXNhZ2VNZXRhZGF0YSI6eyJwcm9tcHRUb2tlbkNvdW50Ijo4LCJjYW5kaWRhdGVzVG9rZW5Db3VudCI6NywidG90YWxUb2tlbkNvdW50IjoxNSwicHJvbXB0VG9rZW5zRGV0YWlscyI6W3sibW9kYWxpdHkiOiJURVhUIiwidG9rZW5Db3VudCI6OH1dfSwibW9kZWxWZXJzaW9uIjoiZ2VtaW5pLTMuMS1mbGFzaC1saXRlLXByZXZpZXciLCJyZXNwb25zZUlkIjoiOVFqMGFmQzFBX3FLbXRrUHdiaUd1QXMifUpoChNicmFpbnRydXN0Lm1ldGFkYXRhElEKT3sicHJvdmlkZXIiOiJnZW1pbmkiLCJ0ZW1wZXJhdHVyZSI6MC4wLCJtb2RlbCI6ImdlbWluaS0zLjEtZmxhc2gtbGl0ZS1wcmV2aWV3In1KtAEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhKaAQqXAXsiY29udGVudHMiOlt7InBhcnRzIjpbeyJ0ZXh0IjoiV2hhdCBpcyB0aGUgY2FwaXRhbCBvZiBGcmFuY2U/In1dLCJyb2xlIjoidXNlciJ9XSwibW9kZWwiOiJnZW1pbmktMy4xLWZsYXNoLWxpdGUtcHJldmlldyIsImNvbmZpZyI6eyJ0ZW1wZXJhdHVyZSI6MC4wfX1KTQoSYnJhaW50cnVzdC5tZXRyaWNzEjcKNXsiY29tcGxldGlvbl90b2tlbnMiOjcsInByb21wdF90b2tlbnMiOjgsInRva2VucyI6MTV9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoCGAGFAQEBAAAS4wYKEDgLmVfukX9YRf+dCRS304gSCEG7LdAP0A69IggNvafbL5fhtioPQ2hhdCBDb21wbGV0aW9uMAE53EBYWXhOqxhBK5Bsw3hOqxhK6AEKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SzQEKygFbeyJtZXNzYWdlIjp7InJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZW50IjoiU3VyZSEgSGVyZSB3ZSBnbzpcblxuMS4uLiAgXG4yLi4uICBcbjMuLi4gIFxuNC4uLiAgXG41Li4uICBcbjYuLi4gIFxuNy4uLiAgXG44Li4uICBcbjkuLi4gIFxuMTAuLi4gIFxuXG5UaGVyZSB5b3UgaGF2ZSBpdCEifSwiaW5kZXgiOjAsImZpbmlzaF9yZWFzb24iOiJzdG9wIn1dSrcBChNicmFpbnRydXN0Lm1ldGFkYXRhEp8BCpwBeyJwcm92aWRlciI6Im9wZW5haSIsInJlcXVlc3RfcGF0aCI6ImNoYXQvY29tcGxldGlvbnMiLCJtb2RlbCI6ImdwdC00by1taW5pLTIwMjQtMDctMTgiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdDozOTg5MyIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SpABChVicmFpbnRydXN0LmlucHV0X2pzb24Sdwp1W3siY29udGVudCI6InlvdSBhcmUgYSB0aG91Z2h0ZnVsIGFzc2lzdGFudCIsInJvbGUiOiJzeXN0ZW0ifSx7ImNvbnRlbnQiOiJDb3VudCBmcm9tIDEgdG8gMTAgc2xvd2x5LiIsInJvbGUiOiJ1c2VyIn1dSnAKEmJyYWludHJ1c3QubWV0cmljcxJaClh7ImNvbXBsZXRpb25fdG9rZW5zIjo0MSwicHJvbXB0X3Rva2VucyI6MjUsInRva2VucyI6NjYsInRpbWVfdG9fZmlyc3RfdG9rZW4iOjEuNzI3NTc4OTh9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifVABegCFAQEBAAA=" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZWqHxBoAMESxA=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f408f7-3b8f3a221a6fac600405e5f7;Parent=56c4c0adc911663c;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 01:59:19 GMT", + "Via" : "1.1 21c7c4234f218bb5110262cbbf01f870.cloudfront.net (CloudFront), 1.1 a53bab1af200813b8f27e3c0a28b4964.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f408f70000000056a29e9dc2ce0895", + "x-amzn-RequestId" : "14d85b3b-232d-461e-812b-b8f88ea2cfcc", + "X-Amz-Cf-Id" : "rEHQVZBCzRoaCx9zdiTRApl1v9nhjTfL3A5JyjFGqaPvFB0znROTWA==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "42c4b63d-ce6a-4de4-964e-0b3295b9f697", + "persistent" : true, + "insertionIndex" : 241 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-58354206-e4d1-4bd1-aec1-ed83cd4640e5.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-58354206-e4d1-4bd1-aec1-ed83cd4640e5.json new file mode 100644 index 00000000..5b5ddb27 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-58354206-e4d1-4bd1-aec1-ed83cd4640e5.json @@ -0,0 +1,39 @@ +{ + "id" : "58354206-e4d1-4bd1-aec1-ed83cd4640e5", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CpE/CrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKsCAoYChZicmFpbnRydXN0LWF3cy1iZWRyb2NrEo8IChC4a/CnTtvs+gmiykX4ybSYEghYAOHr8BXQ8CIIc2MdZn/iHt8qEGJlZHJvY2suY29udmVyc2UwATlX4ORCek6rGEHARhV4ek6rGEqLAgoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhLwAQrtAVt7ImNvbnRlbnQiOlt7InRleHQiOiJTb3JyeSwgSSBjYW5ub3QgcmVzcG9uZCB0byBxdWVzdGlvbnMgdGhhdCByZXF1aXJlIHZpc3VhbCBpbnB1dC4gSSBzdWdnZXN0IHVzaW5nIGEgY29sb3IgcGlja2VyIHRvb2wgb3IgY29uc3VsdGluZyB3aXRoIGEgcHJvZmVzc2lvbmFsIGRlc2lnbmVyIGZvciBhY2N1cmF0ZSBjb2xvciBpZGVudGlmaWNhdGlvbi4iLCJ0eXBlIjoidGV4dCJ9XSwicm9sZSI6ImFzc2lzdGFudCJ9XUrjAQoTYnJhaW50cnVzdC5tZXRhZGF0YRLLAQrIAXsiZW5kcG9pbnQiOiJjb252ZXJzZSIsInByb3ZpZGVyIjoiYmVkcm9jayIsInJlcXVlc3RfcGF0aCI6Im1vZGVsL3VzLmFtYXpvbi5ub3ZhLWxpdGUtdjElM0EwL2NvbnZlcnNlIiwibW9kZWwiOiJ1cy5hbWF6b24ubm92YS1saXRlLXYxOjAiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdCIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9So0CChVicmFpbnRydXN0LmlucHV0X2pzb24S8wEK8AFbeyJyb2xlIjoidXNlciIsImNvbnRlbnQiOlt7InRleHQiOiJXaGF0IGNvbG9yIGlzIHRoaXMgaW1hZ2U/IiwidHlwZSI6InRleHQifSx7ImltYWdlIjp7ImZvcm1hdCI6InBuZyIsInNvdXJjZSI6eyJieXRlcyI6ImlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBRUFBQUFCQ0FZQUFBQWZGY1NKQUFBQURVbEVRVlI0Mm1QOHo4RHdId0FGQlFJQVg4angwZ0FBQUFCSlJVNUVya0pnZ2c9PSJ9fSwidHlwZSI6ImltYWdlIn1dfV1KUQoSYnJhaW50cnVzdC5tZXRyaWNzEjsKOXsiY29tcGxldGlvbl90b2tlbnMiOjMyLCJwcm9tcHRfdG9rZW5zIjo1MzYsInRva2VucyI6NTY4fUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3RKLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn16AIUBAQEAABKgBwoFCgNidHgSlwEKEDgi4CQVCI4ATAIgNkcYyhQSCDdegrfDt3+uKglzdHJlYW1pbmcwATnEHxYCek6rGEGnZkpCek6rGEoeCgZjbGllbnQSFAoSc3ByaW5nYWktYW50aHJvcGljSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEo4BChC4a/CnTtvs+gmiykX4ybSYEghzYx1mf+Ie3yoLYXR0YWNobWVudHMwATm4LU1Cek6rGEH4lh54ek6rGEoTCgZjbGllbnQSCQoHYmVkcm9ja0oyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAABKfAQoQFJtKpJbYd2ge9i/J3W2SuBIIGpXsr16yuzoqEXByb21wdF9jYWNoaW5nXzVtMAE5Z3YieHpOqxhB94mhuXpOqxhKHgoGY2xpZW50EhQKEnNwcmluZ2FpLWFudGhyb3BpY0oyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAABKOAQoQSpbQ9BtTexF5aPQTsjTQKBIIme1HTPg2qucqCXN0cmVhbWluZzABOYVdpLl6TqsYQc5MzfF6TqsYShUKBmNsaWVudBILCglhbnRocm9waWNKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASnwEKENiA3U1PyQfAmgKs/VluEdYSCEFlowWGUTX5KhFwcm9tcHRfY2FjaGluZ18xaDABOaeez/F6TqsYQVyYSy97TqsYSh4KBmNsaWVudBIUChJzcHJpbmdhaS1hbnRocm9waWNKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASlgEKENah/Nv34E0KYbkwqR8PKuQSCI17ScQXwz+7KhFwcm9tcHRfY2FjaGluZ181bTABORNQTi97TqsYQbD7IXR7TqsYShUKBmNsaWVudBILCglhbnRocm9waWNKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAAShy4KEQoPYnJhaW50cnVzdC1qYXZhEroIChA4IuAkFQiOAEwCIDZHGMoUEggGQEsErQIreSIIN16Ct8O3f64qGWFudGhyb3BpYy5tZXNzYWdlcy5jcmVhdGUwATmc64MEek6rGEFaq0RCek6rGErZAgoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhK+Agq7Ansicm9sZSI6ImFzc2lzdGFudCIsImNvbnRlbnQiOlt7InR5cGUiOiJ0ZXh0IiwidGV4dCI6IjFcbjJcbjNcbjRcbjUifV0sInVzYWdlIjp7ImlucHV0X3Rva2VucyI6MjIsImNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMiOjAsImNhY2hlX2NyZWF0aW9uIjp7ImVwaGVtZXJhbF81bV9pbnB1dF90b2tlbnMiOjAsImVwaGVtZXJhbF8xaF9pbnB1dF90b2tlbnMiOjB9LCJvdXRwdXRfdG9rZW5zIjoxMywic2VydmljZV90aWVyIjoic3RhbmRhcmQiLCJpbmZlcmVuY2VfZ2VvIjoibm90X2F2YWlsYWJsZSJ9fUq4AQoTYnJhaW50cnVzdC5tZXRhZGF0YRKgAQqdAXsicHJvdmlkZXIiOiJhbnRocm9waWMiLCJyZXF1ZXN0X3BhdGgiOiJ2MS9tZXNzYWdlcyIsIm1vZGVsIjoiY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMSIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjQzMDYxIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KhgEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJtCmtbeyJjb250ZW50IjoiQ291bnQgZnJvbSAxIHRvIDUuIiwicm9sZSI6InVzZXIifSx7InJvbGUiOiJzeXN0ZW0iLCJjb250ZW50IjoiWW91IGFyZSBhIGhlbHBmdWwgYXNzaXN0YW50LiJ9XUrUAQoSYnJhaW50cnVzdC5tZXRyaWNzEr0BCroBeyJjb21wbGV0aW9uX3Rva2VucyI6MTMsInByb21wdF90b2tlbnMiOjIyLCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fMWhfdG9rZW5zIjowLCJwcm9tcHRfY2FjaGVkX3Rva2VucyI6MCwidG9rZW5zIjozNSwidGltZV90b19maXJzdF90b2tlbiI6MC45OTMxNTk0MDYsInByb21wdF9jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMiOjB9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifVABegCFAQEBAAASgwkKEBSbSqSW2HdoHvYvyd1tkrgSCLb9BTNN7IsTIggaleyvXrK7OioZYW50aHJvcGljLm1lc3NhZ2VzLmNyZWF0ZTABOQd6Lnl6TqsYQcszO7l6TqsYSvMDChZicmFpbnRydXN0Lm91dHB1dF9qc29uEtgDCtUDeyJtb2RlbCI6ImNsYXVkZS1zb25uZXQtNC01LTIwMjUwOTI5IiwiaWQiOiJtc2dfMDFIdDk3alpBTkJWSHJwdEZOVkdCUGloIiwidHlwZSI6Im1lc3NhZ2UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6W3sidHlwZSI6InRleHQiLCJ0ZXh0IjoiUGFyaXMuIn1dLCJzdG9wX3JlYXNvbiI6ImVuZF90dXJuIiwic3RvcF9zZXF1ZW5jZSI6bnVsbCwic3RvcF9kZXRhaWxzIjpudWxsLCJ1c2FnZSI6eyJpbnB1dF90b2tlbnMiOjEyLCJjYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMiOjEzNjgsImNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zIjowLCJjYWNoZV9jcmVhdGlvbiI6eyJlcGhlbWVyYWxfNW1faW5wdXRfdG9rZW5zIjoxMzY4LCJlcGhlbWVyYWxfMWhfaW5wdXRfdG9rZW5zIjowfSwib3V0cHV0X3Rva2VucyI6NSwic2VydmljZV90aWVyIjoic3RhbmRhcmQiLCJpbmZlcmVuY2VfZ2VvIjoibm90X2F2YWlsYWJsZSJ9fUq5AQoTYnJhaW50cnVzdC5tZXRhZGF0YRKhAQqeAXsicHJvdmlkZXIiOiJhbnRocm9waWMiLCJyZXF1ZXN0X3BhdGgiOiJ2MS9tZXNzYWdlcyIsIm1vZGVsIjoiY2xhdWRlLXNvbm5ldC00LTUtMjAyNTA5MjkiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdDo0MzA2MSIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SlcKFWJyYWludHJ1c3QuaW5wdXRfanNvbhI+CjxbeyJjb250ZW50IjoiV2hhdCBpcyB0aGUgY2FwaXRhbCBvZiBGcmFuY2U/Iiwicm9sZSI6InVzZXIifV1KtAEKEmJyYWludHJ1c3QubWV0cmljcxKdAQqaAXsiY29tcGxldGlvbl90b2tlbnMiOjUsInByb21wdF90b2tlbnMiOjEyLCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fMWhfdG9rZW5zIjowLCJwcm9tcHRfY2FjaGVkX3Rva2VucyI6MCwidG9rZW5zIjoxNywicHJvbXB0X2NhY2hlX2NyZWF0aW9uXzVtX3Rva2VucyI6MTM2OH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAASmQoKEEqW0PQbU3sReWj0E7I00CgSCAEEWHRiVIAmIgiZ7UdM+Daq5yoZYW50aHJvcGljLm1lc3NhZ2VzLmNyZWF0ZTABOTMmEr96TqsYQbQByvF6TqsYStAEChZicmFpbnRydXN0Lm91dHB1dF9qc29uErUECrIEeyJpZCI6Im1zZ18wMVFvV0g2dG9FWEJZRUJTeW1qbU5hWHEiLCJjb250ZW50IjpbeyJjaXRhdGlvbnMiOm51bGwsInRleHQiOiIxXG4yXG4zXG40XG41IiwidHlwZSI6InRleHQiLCJ2YWxpZCI6dHJ1ZX1dLCJtb2RlbCI6ImNsYXVkZS1oYWlrdS00LTUtMjAyNTEwMDEiLCJyb2xlIjoiYXNzaXN0YW50Iiwic3RvcF9yZWFzb24iOiJlbmRfdHVybiIsInN0b3Bfc2VxdWVuY2UiOm51bGwsInR5cGUiOiJtZXNzYWdlIiwidXNhZ2UiOnsiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwidmFsaWQiOnRydWV9LCJjYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMiOjAsImNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zIjowLCJpbnB1dF90b2tlbnMiOjIyLCJvdXRwdXRfdG9rZW5zIjoxMywic2VydmVyX3Rvb2xfdXNlIjpudWxsLCJzZXJ2aWNlX3RpZXIiOiJzdGFuZGFyZCIsInZhbGlkIjp0cnVlLCJpbmZlcmVuY2VfZ2VvIjoibm90X2F2YWlsYWJsZSJ9LCJ2YWxpZCI6dHJ1ZSwic3RvcF9kZXRhaWxzIjpudWxsfUqiAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKKAQqHAXsicHJvdmlkZXIiOiJhbnRocm9waWMiLCJyZXF1ZXN0X3BhdGgiOiJ2MS9tZXNzYWdlcyIsIm1vZGVsIjoiY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMSIsInJlcXVlc3RfYmFzZV91cmkiOiIiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUqGAQoVYnJhaW50cnVzdC5pbnB1dF9qc29uEm0Ka1t7ImNvbnRlbnQiOiJDb3VudCBmcm9tIDEgdG8gNS4iLCJyb2xlIjoidXNlciJ9LHsicm9sZSI6InN5c3RlbSIsImNvbnRlbnQiOiJZb3UgYXJlIGEgaGVscGZ1bCBhc3Npc3RhbnQuIn1dStQBChJicmFpbnRydXN0Lm1ldHJpY3MSvQEKugF7ImNvbXBsZXRpb25fdG9rZW5zIjoxMywicHJvbXB0X3Rva2VucyI6MjIsInByb21wdF9jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMiOjAsInByb21wdF9jYWNoZWRfdG9rZW5zIjowLCJ0b2tlbnMiOjM1LCJ0aW1lX3RvX2ZpcnN0X3Rva2VuIjowLjAwNTkyNzMwOCwicHJvbXB0X2NhY2hlX2NyZWF0aW9uXzVtX3Rva2VucyI6MH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAASogkKENiA3U1PyQfAmgKs/VluEdYSCJJhs9v6pnrHIghBZaMFhlE1+SoZYW50aHJvcGljLm1lc3NhZ2VzLmNyZWF0ZTABOdvjZPJ6TqsYQQMb4i57TqsYSpEEChZicmFpbnRydXN0Lm91dHB1dF9qc29uEvYDCvMDeyJtb2RlbCI6ImNsYXVkZS1zb25uZXQtNC01LTIwMjUwOTI5IiwiaWQiOiJtc2dfMDFRMWo5MUZFTmpjVVZNYVpwQ0VpUXRKIiwidHlwZSI6Im1lc3NhZ2UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6W3sidHlwZSI6InRleHQiLCJ0ZXh0IjoiVGhlIGNhcGl0YWwgb2YgRnJhbmNlIGlzICoqUGFyaXMqKi4ifV0sInN0b3BfcmVhc29uIjoiZW5kX3R1cm4iLCJzdG9wX3NlcXVlbmNlIjpudWxsLCJzdG9wX2RldGFpbHMiOm51bGwsInVzYWdlIjp7ImlucHV0X3Rva2VucyI6MTIsImNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyI6MTk5MywiY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMiOjAsImNhY2hlX2NyZWF0aW9uIjp7ImVwaGVtZXJhbF81bV9pbnB1dF90b2tlbnMiOjAsImVwaGVtZXJhbF8xaF9pbnB1dF90b2tlbnMiOjE5OTN9LCJvdXRwdXRfdG9rZW5zIjoxMSwic2VydmljZV90aWVyIjoic3RhbmRhcmQiLCJpbmZlcmVuY2VfZ2VvIjoibm90X2F2YWlsYWJsZSJ9fUq5AQoTYnJhaW50cnVzdC5tZXRhZGF0YRKhAQqeAXsicHJvdmlkZXIiOiJhbnRocm9waWMiLCJyZXF1ZXN0X3BhdGgiOiJ2MS9tZXNzYWdlcyIsIm1vZGVsIjoiY2xhdWRlLXNvbm5ldC00LTUtMjAyNTA5MjkiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdDo0MzA2MSIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SlcKFWJyYWludHJ1c3QuaW5wdXRfanNvbhI+CjxbeyJjb250ZW50IjoiV2hhdCBpcyB0aGUgY2FwaXRhbCBvZiBGcmFuY2U/Iiwicm9sZSI6InVzZXIifV1KtQEKEmJyYWludHJ1c3QubWV0cmljcxKeAQqbAXsiY29tcGxldGlvbl90b2tlbnMiOjExLCJwcm9tcHRfdG9rZW5zIjoxMiwicHJvbXB0X2NhY2hlX2NyZWF0aW9uXzFoX3Rva2VucyI6MTk5MywicHJvbXB0X2NhY2hlZF90b2tlbnMiOjAsInRva2VucyI6MjMsInByb21wdF9jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMiOjB9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAAEu0IChDWofzb9+BNCmG5MKkfDyrkEghTZhenTkjVhyIIjXtJxBfDP7sqGWFudGhyb3BpYy5tZXNzYWdlcy5jcmVhdGUwATk3SlAwe06rGEEgixx0e06rGErzAwoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhLYAwrVA3sibW9kZWwiOiJjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOSIsImlkIjoibXNnXzAxTGdGTjlzcGdnVFk4RXBKVTdEdHlIRSIsInR5cGUiOiJtZXNzYWdlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRlbnQiOlt7InR5cGUiOiJ0ZXh0IiwidGV4dCI6IlBhcmlzLiJ9XSwic3RvcF9yZWFzb24iOiJlbmRfdHVybiIsInN0b3Bfc2VxdWVuY2UiOm51bGwsInN0b3BfZGV0YWlscyI6bnVsbCwidXNhZ2UiOnsiaW5wdXRfdG9rZW5zIjoxMiwiY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zIjoxMzY1LCJjYWNoZV9yZWFkX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MTM2NSwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH0sIm91dHB1dF90b2tlbnMiOjUsInNlcnZpY2VfdGllciI6InN0YW5kYXJkIiwiaW5mZXJlbmNlX2dlbyI6Im5vdF9hdmFpbGFibGUifX1KowEKE2JyYWludHJ1c3QubWV0YWRhdGESiwEKiAF7InByb3ZpZGVyIjoiYW50aHJvcGljIiwicmVxdWVzdF9wYXRoIjoidjEvbWVzc2FnZXMiLCJtb2RlbCI6ImNsYXVkZS1zb25uZXQtNC01LTIwMjUwOTI5IiwicmVxdWVzdF9iYXNlX3VyaSI6IiIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SlcKFWJyYWludHJ1c3QuaW5wdXRfanNvbhI+CjxbeyJjb250ZW50IjoiV2hhdCBpcyB0aGUgY2FwaXRhbCBvZiBGcmFuY2U/Iiwicm9sZSI6InVzZXIifV1KtAEKEmJyYWludHJ1c3QubWV0cmljcxKdAQqaAXsiY29tcGxldGlvbl90b2tlbnMiOjUsInByb21wdF90b2tlbnMiOjEyLCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fMWhfdG9rZW5zIjowLCJwcm9tcHRfY2FjaGVkX3Rva2VucyI6MCwidG9rZW5zIjoxNywicHJvbXB0X2NhY2hlX2NyZWF0aW9uXzVtX3Rva2VucyI6MTM2NX1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAA=" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZYZG78oAMEhdw=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f40902-286ed71d4586e6ac609fe735;Parent=65f703ace37a5de6;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 01:59:30 GMT", + "Via" : "1.1 d08613e1dd8ad614e47875ae31a8af20.cloudfront.net (CloudFront), 1.1 96f6dcbb4d7267cad6eb0747bce72024.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f409020000000040db0310edf73ffb", + "x-amzn-RequestId" : "4575dbb9-a565-4e3c-bb32-181f3c7639ae", + "X-Amz-Cf-Id" : "9BsbRFGQsQ3OA8Y7TiFWjDp3k3RDRIHXGvebSoUIyu5QpDhsPN4RyA==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "58354206-e4d1-4bd1-aec1-ed83cd4640e5", + "persistent" : true, + "insertionIndex" : 239 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-61e2fe04-2f31-43e5-9b63-b6313e610d09.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-61e2fe04-2f31-43e5-9b63-b6313e610d09.json new file mode 100644 index 00000000..7ac9440b --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-61e2fe04-2f31-43e5-9b63-b6313e610d09.json @@ -0,0 +1,39 @@ +{ + "id" : "61e2fe04-2f31-43e5-9b63-b6313e610d09", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "Co1RCrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBL4BQoFCgNidHgSlgEKEPfhoAYSAIFN0I8xk0MPL/MSCL1SD1OlPw9AKghtZXNzYWdlczABOVlfJHR7TqsYQULeT6B7TqsYSh4KBmNsaWVudBIUChJzcHJpbmdhaS1hbnRocm9waWNKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASlgEKEFGgjMIw7kOWsvqpYC4AR9USCBY+T42CFGEoKhFwcm9tcHRfY2FjaGluZ18xaDABOXh0UqB7TqsYQVfC7+h7TqsYShUKBmNsaWVudBILCglhbnRocm9waWNKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASmQEKEGGH2IZwb4aSMNeM+e8+9akSCMB5dA33ur1LKgthdHRhY2htZW50czABOeij8uh7TqsYQbmZSiZ8TqsYSh4KBmNsaWVudBIUChJzcHJpbmdhaS1hbnRocm9waWNKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASjQEKEBIoxfHojgwywMirDGhImfQSCMTg25sBDzBdKghtZXNzYWdlczABOU3XTCZ8TqsYQddwnVB8TqsYShUKBmNsaWVudBILCglhbnRocm9waWNKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASkAEKEIi9JajIY1pGdAOkLc4UYsgSCPsoBnl6OJotKgthdHRhY2htZW50czABOXlboFB8TqsYQZUS3ql8TqsYShUKBmNsaWVudBILCglhbnRocm9waWNKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAAS2kkKEQoPYnJhaW50cnVzdC1qYXZhEs8JChD34aAGEgCBTdCPMZNDDy/zEggY6r7q+8DKjiIIvVIPU6U/D0AqGWFudGhyb3BpYy5tZXNzYWdlcy5jcmVhdGUwATm9RsV0e06rGEFIPfSfe06rGEqGBAoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhLrAwroA3sibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxIiwiaWQiOiJtc2dfMDFKeno5WkxjZU5FSEcxY2pGUUhpN0RBIiwidHlwZSI6Im1lc3NhZ2UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6W3sidHlwZSI6InRleHQiLCJ0ZXh0IjoiVGhlIGNhcGl0YWwgb2YgRnJhbmNlIGlzIFBhcmlzLiJ9XSwic3RvcF9yZWFzb24iOiJlbmRfdHVybiIsInN0b3Bfc2VxdWVuY2UiOm51bGwsInN0b3BfZGV0YWlscyI6bnVsbCwidXNhZ2UiOnsiaW5wdXRfdG9rZW5zIjoyMCwiY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zIjowLCJjYWNoZV9yZWFkX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH0sIm91dHB1dF90b2tlbnMiOjEwLCJzZXJ2aWNlX3RpZXIiOiJzdGFuZGFyZCIsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIn19SrgBChNicmFpbnRydXN0Lm1ldGFkYXRhEqABCp0BeyJwcm92aWRlciI6ImFudGhyb3BpYyIsInJlcXVlc3RfcGF0aCI6InYxL21lc3NhZ2VzIiwibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxIiwicmVxdWVzdF9iYXNlX3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDMwNjEiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUqSAQoVYnJhaW50cnVzdC5pbnB1dF9qc29uEnkKd1t7ImNvbnRlbnQiOiJXaGF0IGlzIHRoZSBjYXBpdGFsIG9mIEZyYW5jZT8iLCJyb2xlIjoidXNlciJ9LHsicm9sZSI6InN5c3RlbSIsImNvbnRlbnQiOiJZb3UgYXJlIGEgaGVscGZ1bCBhc3Npc3RhbnQuIn1dSrIBChJicmFpbnRydXN0Lm1ldHJpY3MSmwEKmAF7ImNvbXBsZXRpb25fdG9rZW5zIjoxMCwicHJvbXB0X3Rva2VucyI6MjAsInByb21wdF9jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMiOjAsInByb21wdF9jYWNoZWRfdG9rZW5zIjowLCJ0b2tlbnMiOjMwLCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zIjowfUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3RKLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn16AIUBAQEAABKMCQoQUaCMwjDuQ5ay+qlgLgBH1RIIMXJXZtWW0FsiCBY+T42CFGEoKhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5KW/IoHtOqxhBZqHq6HtOqxhKkQQKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S9gMK8wN7Im1vZGVsIjoiY2xhdWRlLXNvbm5ldC00LTUtMjAyNTA5MjkiLCJpZCI6Im1zZ18wMUhpRjhDYzgzbVRvaFA0NGRzOTlRYzgiLCJ0eXBlIjoibWVzc2FnZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZW50IjpbeyJ0eXBlIjoidGV4dCIsInRleHQiOiJUaGUgY2FwaXRhbCBvZiBGcmFuY2UgaXMgKipQYXJpcyoqLiJ9XSwic3RvcF9yZWFzb24iOiJlbmRfdHVybiIsInN0b3Bfc2VxdWVuY2UiOm51bGwsInN0b3BfZGV0YWlscyI6bnVsbCwidXNhZ2UiOnsiaW5wdXRfdG9rZW5zIjoxMiwiY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zIjoxOTkwLCJjYWNoZV9yZWFkX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MTk5MH0sIm91dHB1dF90b2tlbnMiOjExLCJzZXJ2aWNlX3RpZXIiOiJzdGFuZGFyZCIsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIn19SqMBChNicmFpbnRydXN0Lm1ldGFkYXRhEosBCogBeyJwcm92aWRlciI6ImFudGhyb3BpYyIsInJlcXVlc3RfcGF0aCI6InYxL21lc3NhZ2VzIiwibW9kZWwiOiJjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOSIsInJlcXVlc3RfYmFzZV91cmkiOiIiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUpXChVicmFpbnRydXN0LmlucHV0X2pzb24SPgo8W3siY29udGVudCI6IldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlPyIsInJvbGUiOiJ1c2VyIn1dSrUBChJicmFpbnRydXN0Lm1ldHJpY3MSngEKmwF7ImNvbXBsZXRpb25fdG9rZW5zIjoxMSwicHJvbXB0X3Rva2VucyI6MTIsInByb21wdF9jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMiOjE5OTAsInByb21wdF9jYWNoZWRfdG9rZW5zIjowLCJ0b2tlbnMiOjIzLCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zIjowfUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3RKLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn16AIUBAQEAABKfCwoQYYfYhnBvhpIw14z57z71qRIItIUdjoGW55kiCMB5dA33ur1LKhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5Px7C6XtOqxhB/fr1JXxOqxhKzAQKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SsQQKrgR7Im1vZGVsIjoiY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMSIsImlkIjoibXNnXzAxWUZhMWpTOUpMVVJSOXdwZnNLRDdXNSIsInR5cGUiOiJtZXNzYWdlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRlbnQiOlt7InR5cGUiOiJ0ZXh0IiwidGV4dCI6IlRoaXMgaW1hZ2UgaXMgKipyZWQqKi4gSXQgYXBwZWFycyB0byBiZSBhIHNtYWxsIHJlZCBkb3Qgb3IgY2lyY3VsYXIgc2hhcGUgYWdhaW5zdCBhIHdoaXRlIGJhY2tncm91bmQuIn1dLCJzdG9wX3JlYXNvbiI6ImVuZF90dXJuIiwic3RvcF9zZXF1ZW5jZSI6bnVsbCwic3RvcF9kZXRhaWxzIjpudWxsLCJ1c2FnZSI6eyJpbnB1dF90b2tlbnMiOjE3LCJjYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMiOjAsImNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zIjowLCJjYWNoZV9jcmVhdGlvbiI6eyJlcGhlbWVyYWxfNW1faW5wdXRfdG9rZW5zIjowLCJlcGhlbWVyYWxfMWhfaW5wdXRfdG9rZW5zIjowfSwib3V0cHV0X3Rva2VucyI6MjYsInNlcnZpY2VfdGllciI6InN0YW5kYXJkIiwiaW5mZXJlbmNlX2dlbyI6Im5vdF9hdmFpbGFibGUifX1KuAEKE2JyYWludHJ1c3QubWV0YWRhdGESoAEKnQF7InByb3ZpZGVyIjoiYW50aHJvcGljIiwicmVxdWVzdF9wYXRoIjoidjEvbWVzc2FnZXMiLCJtb2RlbCI6ImNsYXVkZS1oYWlrdS00LTUtMjAyNTEwMDEiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdDo0MzA2MSIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SpwCChVicmFpbnRydXN0LmlucHV0X2pzb24SggIK/wFbeyJjb250ZW50IjpbeyJ0eXBlIjoidGV4dCIsInRleHQiOiJXaGF0IGNvbG9yIGlzIHRoaXMgaW1hZ2U/In0seyJ0eXBlIjoiaW1hZ2UiLCJzb3VyY2UiOnsidHlwZSI6ImJhc2U2NCIsIm1lZGlhX3R5cGUiOiJpbWFnZS9wbmciLCJkYXRhIjoiaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFFQUFBQUJDQVlBQUFBZkZjU0pBQUFBRFVsRVFWUjQybVA4ejhEd0h3QUZCUUlBWDhqeDBnQUFBQUJKUlU1RXJrSmdnZz09In19XSwicm9sZSI6InVzZXIifV1KsgEKEmJyYWludHJ1c3QubWV0cmljcxKbAQqYAXsiY29tcGxldGlvbl90b2tlbnMiOjI2LCJwcm9tcHRfdG9rZW5zIjoxNywicHJvbXB0X2NhY2hlX2NyZWF0aW9uXzFoX3Rva2VucyI6MCwicHJvbXB0X2NhY2hlZF90b2tlbnMiOjAsInRva2VucyI6NDMsInByb21wdF9jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMiOjB9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAAErkJChASKMXx6I4MMsDIqwxoSJn0EghmN48sSOqk2iIIxODbmwEPMF0qGWFudGhyb3BpYy5tZXNzYWdlcy5jcmVhdGUwATnCH58mfE6rGEEGq5dQfE6rGEqGBAoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhLrAwroA3sibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxIiwiaWQiOiJtc2dfMDFVS2ZCbzRFNkJRRHZKZXNVVVdlUHRjIiwidHlwZSI6Im1lc3NhZ2UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6W3sidHlwZSI6InRleHQiLCJ0ZXh0IjoiVGhlIGNhcGl0YWwgb2YgRnJhbmNlIGlzIFBhcmlzLiJ9XSwic3RvcF9yZWFzb24iOiJlbmRfdHVybiIsInN0b3Bfc2VxdWVuY2UiOm51bGwsInN0b3BfZGV0YWlscyI6bnVsbCwidXNhZ2UiOnsiaW5wdXRfdG9rZW5zIjoyMCwiY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zIjowLCJjYWNoZV9yZWFkX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH0sIm91dHB1dF90b2tlbnMiOjEwLCJzZXJ2aWNlX3RpZXIiOiJzdGFuZGFyZCIsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIn19SqIBChNicmFpbnRydXN0Lm1ldGFkYXRhEooBCocBeyJwcm92aWRlciI6ImFudGhyb3BpYyIsInJlcXVlc3RfcGF0aCI6InYxL21lc3NhZ2VzIiwibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxIiwicmVxdWVzdF9iYXNlX3VyaSI6IiIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SpIBChVicmFpbnRydXN0LmlucHV0X2pzb24SeQp3W3siY29udGVudCI6IldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlPyIsInJvbGUiOiJ1c2VyIn0seyJyb2xlIjoic3lzdGVtIiwiY29udGVudCI6IllvdSBhcmUgYSBoZWxwZnVsIGFzc2lzdGFudC4ifV1KsgEKEmJyYWludHJ1c3QubWV0cmljcxKbAQqYAXsiY29tcGxldGlvbl90b2tlbnMiOjEwLCJwcm9tcHRfdG9rZW5zIjoyMCwicHJvbXB0X2NhY2hlX2NyZWF0aW9uXzFoX3Rva2VucyI6MCwicHJvbXB0X2NhY2hlZF90b2tlbnMiOjAsInRva2VucyI6MzAsInByb21wdF9jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMiOjB9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAAEv4WChB77KXLzrIT0G5SRYqO+9amEgiVbo/66AQAgiIIB3AruFyZqhgqCXJlc3BvbnNlczABOdTKQlF4TqsYQaCRwFx8TqsYSoISChZicmFpbnRydXN0Lm91dHB1dF9qc29uEucRCuQRW3siaWQiOiJyc18wMjIyN2RhNTFjM2ZkMjU4MDA2OWY0MDhmNTU2NDA4MTk2YjJkYjYxZTczMmFkODZhNiIsInR5cGUiOiJyZWFzb25pbmciLCJzdW1tYXJ5IjpbeyJ0eXBlIjoic3VtbWFyeV90ZXh0IiwidGV4dCI6IioqQW5hbHl6aW5nIGEgbnVtYmVyIHNlcXVlbmNlKipcblxuVGhlIHVzZXIgcHJvdmlkZWQgdGhlIHNlcXVlbmNlOiAyLCA2LCAxMiwgMjAsIDMwLCBhbmQgSSdtIHRyeWluZyB0byBmaW5kIHRoZSBwYXR0ZXJuIGFuZCBmb3JtdWxhIGZvciB0aGUgbnRoIHRlcm0uIEkgbm90aWNlIHRoaXMgc2VxdWVuY2Ugc2VlbXMgdG8gYmUgdHdpY2UgdGhlIHRyaWFuZ3VsYXIgbnVtYmVycywgd2hpY2ggYXJlIGdlbmVyYXRlZCBieSB0aGUgZm9ybXVsYSBuKG4rMSkvMi4gV2hlbiBJIGFwcGx5IHRoYXQsIEkgc2VlIHRoYXQgZWFjaCB0ZXJtIGNvcnJlc3BvbmRzIHRvIHRoZSB0cmlhbmd1bGFyIG51bWJlciBtdWx0aXBsaWVkIGJ5IDIuIEFkZGl0aW9uYWxseSwgdGhlIGRpZmZlcmVuY2VzIHN1Z2dlc3QgaXQncyBhIHF1YWRyYXRpYyBzZXF1ZW5jZSwgY29uZmlybWluZyB0aGUgbnVtYmVycyBhcmUgcHJvbmljIG51bWJlcnMsIHByb2R1Y3RzIG9mIGNvbnNlY3V0aXZlIGludGVnZXJzLiJ9LHsidHlwZSI6InN1bW1hcnlfdGV4dCIsInRleHQiOiIqKkZpbmRpbmcgdGhlIHRlcm0gZm9ybXVsYSoqXG5cblRoZSBmb3JtdWxhIGZvciB0aGUgc2VxdWVuY2UgaXMgYV9uID0gbihuICsgMSkuIFdoZW4gc3RhcnRpbmcgZnJvbSBuPTEsIEkgc2VlIGl0IGdpdmVzIHRoZSBmaXJzdCB0ZXJtLCAyLiBUaGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0ZXJtcyBpbmNyZWFzZSBieSAyIGVhY2ggdGltZSwgY29uZmlybWluZyB0aGV5IGFyZSBwcm9uaWMgbnVtYmVycy4gQnkgYnJlYWtpbmcgaXQgZG93biBmdXJ0aGVyLCBJIHJlYWxpemUgdGhlc2UgY2FuIGFsc28gYmUgZXhwcmVzc2VkIGFzIHR3aWNlIHRoZSB0cmlhbmd1bGFyIG51bWJlcnMuIFRoZSBkaWZmZXJlbmNlIHNlcXVlbmNlIGlzIDQsIDYsIDgsIDEwLCBzaG93aW5nIGl0J3MgcXVhZHJhdGljLiBVbHRpbWF0ZWx5LCBJIGNvbmNsdWRlOiBhX24gPSBuKG4gKyAxKSBmb3IgdGhlIHNlcXVlbmNlIDIsIDYsIDEyLCAyMCwgMzAuIn0seyJ0eXBlIjoic3VtbWFyeV90ZXh0IiwidGV4dCI6IioqU3VtbWFyaXppbmcgdGhlIHNlcXVlbmNlIHBhdHRlcm4qKlxuXG5UaGUgcGF0dGVybiBpbiB0aGlzIHNlcXVlbmNlIGlzIGZvdW5kIGluIHRoZSBzdWNjZXNzaXZlIGRpZmZlcmVuY2VzLCB3aGljaCBhcmUgZXZlbiBudW1iZXJzOiA0LCA2LCA4LCAxMC4gVGhpcyBsZWFkcyB0byB0aGUgY29uY2x1c2lvbiB0aGF0IGFfbiA9IG5eMiArIG4sIG9yIG1vcmUgc2ltcGx5LCBhX24gPSBuKG4gKyAxKS4gQWx0aG91Z2ggdGhlcmUncyBhIGNvbnNpZGVyYXRpb24gZm9yIHN0YXJ0aW5nIGF0IG49MCwgaXQgdHlwaWNhbGx5IGJlZ2lucyBhdCBuPTEuIEkgY2FuIGFsc28gZXhwcmVzcyBpdCBhcyB0d2ljZSB0aGUgdHJpYW5ndWxhciBudW1iZXJzOiBhX24gPSAyVF9uLiBVbHRpbWF0ZWx5LCB0aGUgYW5zd2VyIGlzIGFfbiA9IG4obiArIDEpIGZvciB0aGUgdGVybXMgMiwgNiwgMTIsIGFuZCBzbyBvbi4ifV19LHsiaWQiOiJtc2dfMDIyMjdkYTUxYzNmZDI1ODAwNjlmNDA5MDJkN2VjODE5NjhkMTFkOTEyNGJiNDA0M2UiLCJ0eXBlIjoibWVzc2FnZSIsInN0YXR1cyI6ImNvbXBsZXRlZCIsImNvbnRlbnQiOlt7InR5cGUiOiJvdXRwdXRfdGV4dCIsImFubm90YXRpb25zIjpbXSwibG9ncHJvYnMiOltdLCJ0ZXh0IjoiVGhlIOKAnGdhcHPigJ0gYmV0d2VlbiB0ZXJtcyBhcmUgIFxuIDbiiJIyPTQsIDEy4oiSNj02LCAyMOKIkjEyPTgsIDMw4oiSMjA9MTAsIOKApiAgXG5pLmUuIHRoZSBkaWZmZXJlbmNlcyBhcmUgNCzigIk2LOKAiTgs4oCJMTAsIOKApiBzbyB0aGUgc2Vjb25kIGRpZmZlcmVuY2UgaXMgY29uc3RhbnQgKDIpIGFuZCB0aGUgc2VxdWVuY2UgaXMgcXVhZHJhdGljLiAgU29sdmluZyBvciBub3RpbmcgdGhhdCBpdOKAmXMgdHdpY2UgdGhlIHRyaWFuZ3VsYXIgbnVtYmVycyBnaXZlc1xuXG4gIGHigpkgPSAywrcobihuKzEpLzIpID0gbihuKzEpLlxuXG5JZiB5b3Ugc3RhcnQgY291bnRpbmcgYXQgbj0xIHRoaXMgaW5kZWVkIHlpZWxkcyAgXG4gIGHigoEgPSAxwrcyID0gMiwgIFxuICBh4oKCID0gMsK3MyA9IDYsICBcbiAgYeKCgyA9IDPCtzQgPSAxMiwgIOKApiAgXG5cblNvIHRoZSBudGggdGVybSBpcyAgYeKCmSA9IG4obisxKS4ifV0sInJvbGUiOiJhc3Npc3RhbnQifV1KoQEKE2JyYWludHJ1c3QubWV0YWRhdGESiQEKhgF7InByb3ZpZGVyIjoib3BlbmFpIiwicmVxdWVzdF9wYXRoIjoicmVzcG9uc2VzIiwibW9kZWwiOiJvNC1taW5pIiwicmVxdWVzdF9iYXNlX3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6Mzk4OTMiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUqpAQoVYnJhaW50cnVzdC5pbnB1dF9qc29uEo8BCowBW3sicm9sZSI6InVzZXIiLCJjb250ZW50IjoiTG9vayBhdCB0aGlzIHNlcXVlbmNlOiAyLCA2LCAxMiwgMjAsIDMwLiBXaGF0IGlzIHRoZSBwYXR0ZXJuIGFuZCB3aGF0IHdvdWxkIGJlIHRoZSBmb3JtdWxhIGZvciB0aGUgbnRoIHRlcm0/XG4ifV1KdgoSYnJhaW50cnVzdC5tZXRyaWNzEmAKXnsiY29tcGxldGlvbl90b2tlbnMiOjEzMjYsInByb21wdF90b2tlbnMiOjQxLCJ0b2tlbnMiOjEzNjcsImNvbXBsZXRpb25fcmVhc29uaW5nX3Rva2VucyI6MTA4OH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAAShAsKEIi9JajIY1pGdAOkLc4UYsgSCJCNuF6D4U1/Igj7KAZ5ejiaLSoZYW50aHJvcGljLm1lc3NhZ2VzLmNyZWF0ZTABOboWaVJ8TqsYQZCc2ql8TqsYSscEChZicmFpbnRydXN0Lm91dHB1dF9qc29uEqwECqkEeyJtb2RlbCI6ImNsYXVkZS1oYWlrdS00LTUtMjAyNTEwMDEiLCJpZCI6Im1zZ18wMUVBZDhvdTlGNFRKRTNSMnFxQnZZMm8iLCJ0eXBlIjoibWVzc2FnZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZW50IjpbeyJ0eXBlIjoidGV4dCIsInRleHQiOiJUaGlzIGltYWdlIGlzICoqcmVkKiouIEl0IGFwcGVhcnMgdG8gYmUgYSBzbWFsbCByZWQgZG90IG9yIGNpcmN1bGFyIHNoYXBlIG9uIGEgd2hpdGUgYmFja2dyb3VuZC4ifV0sInN0b3BfcmVhc29uIjoiZW5kX3R1cm4iLCJzdG9wX3NlcXVlbmNlIjpudWxsLCJzdG9wX2RldGFpbHMiOm51bGwsInVzYWdlIjp7ImlucHV0X3Rva2VucyI6MTcsImNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMiOjAsImNhY2hlX2NyZWF0aW9uIjp7ImVwaGVtZXJhbF81bV9pbnB1dF90b2tlbnMiOjAsImVwaGVtZXJhbF8xaF9pbnB1dF90b2tlbnMiOjB9LCJvdXRwdXRfdG9rZW5zIjoyNiwic2VydmljZV90aWVyIjoic3RhbmRhcmQiLCJpbmZlcmVuY2VfZ2VvIjoibm90X2F2YWlsYWJsZSJ9fUqiAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKKAQqHAXsicHJvdmlkZXIiOiJhbnRocm9waWMiLCJyZXF1ZXN0X3BhdGgiOiJ2MS9tZXNzYWdlcyIsIm1vZGVsIjoiY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMSIsInJlcXVlc3RfYmFzZV91cmkiOiIiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUqcAgoVYnJhaW50cnVzdC5pbnB1dF9qc29uEoICCv8BW3siY29udGVudCI6W3sidGV4dCI6IldoYXQgY29sb3IgaXMgdGhpcyBpbWFnZT8iLCJ0eXBlIjoidGV4dCJ9LHsic291cmNlIjp7ImRhdGEiOiJpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQUVBQUFBQkNBWUFBQUFmRmNTSkFBQUFEVWxFUVZSNDJtUDh6OER3SHdBRkJRSUFYOGp4MGdBQUFBQkpSVTVFcmtKZ2dnPT0iLCJtZWRpYV90eXBlIjoiaW1hZ2UvcG5nIiwidHlwZSI6ImJhc2U2NCJ9LCJ0eXBlIjoiaW1hZ2UifV0sInJvbGUiOiJ1c2VyIn1dSrIBChJicmFpbnRydXN0Lm1ldHJpY3MSmwEKmAF7ImNvbXBsZXRpb25fdG9rZW5zIjoyNiwicHJvbXB0X3Rva2VucyI6MTcsInByb21wdF9jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMiOjAsInByb21wdF9jYWNoZWRfdG9rZW5zIjowLCJ0b2tlbnMiOjQzLCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zIjowfUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3RKLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn16AIUBAQEAAA==" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZZQHrcIAMEW_w=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f40907-3d1fc9771bb6e7d618438817;Parent=30b1a3138ab78064;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 01:59:35 GMT", + "Via" : "1.1 d6022fdb6e8ea3c6fe76398e42003fcc.cloudfront.net (CloudFront), 1.1 566cc276dff9847158a5a9854be4df42.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f40907000000004e277e1fd6cc5616", + "x-amzn-RequestId" : "7ae9f9d9-4c88-4fb7-9ee4-364dd03eb573", + "X-Amz-Cf-Id" : "8cvD0nq9BirOkpq2R3G0_YEhIlKjpxCFnrLoOA033Muq9zttzk-gVg==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "61e2fe04-2f31-43e5-9b63-b6313e610d09", + "persistent" : true, + "insertionIndex" : 238 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-90e0003e-1382-47dc-a394-cec76f5217e3.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-90e0003e-1382-47dc-a394-cec76f5217e3.json new file mode 100644 index 00000000..3eff557e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-90e0003e-1382-47dc-a394-cec76f5217e3.json @@ -0,0 +1,39 @@ +{ + "id" : "90e0003e-1382-47dc-a394-cec76f5217e3", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CuwLCrgBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAooCg9zZXJ2aWNlLnZlcnNpb24SFQoTMC4zLjQtYjIyODA5ZS1ESVJUWQogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKuCgoRCg9icmFpbnRydXN0LWphdmESmAoKENS8g0b56JwA0BMkHZk6oiwSCN8N7Ltl3bGfKhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5/PSXZep/qxhB+glHqOp/qxhK+gQKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S3wQK3AR7Im1vZGVsIjoiY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMSIsImlkIjoibXNnXzAxOVVHMTR2MWhnZkhHWWR0NEgzZEUydiIsInR5cGUiOiJtZXNzYWdlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRlbnQiOlt7InR5cGUiOiJ0ZXh0IiwidGV4dCI6IlRoZSBjYXBpdGFsIG9mIEZyYW5jZSBpcyAqKlBhcmlzKiouIEl0IGlzIGxvY2F0ZWQgaW4gdGhlIG5vcnRoLWNlbnRyYWwgcGFydCBvZiB0aGUgY291bnRyeSBhbG9uZyB0aGUgU2VpbmUgUml2ZXIgYW5kIGlzIHRoZSBsYXJnZXN0IGNpdHkgaW4gRnJhbmNlLiJ9XSwic3RvcF9yZWFzb24iOiJlbmRfdHVybiIsInN0b3Bfc2VxdWVuY2UiOm51bGwsInN0b3BfZGV0YWlscyI6bnVsbCwidXNhZ2UiOnsiaW5wdXRfdG9rZW5zIjoxOSwiY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zIjowLCJjYWNoZV9yZWFkX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH0sIm91dHB1dF90b2tlbnMiOjM2LCJzZXJ2aWNlX3RpZXIiOiJzdGFuZGFyZCIsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIn19SpgBChNicmFpbnRydXN0Lm1ldGFkYXRhEoABCn57InByb3ZpZGVyIjoiYW50aHJvcGljIiwicmVxdWVzdF9wYXRoIjoidjEvbWVzc2FnZXMiLCJtb2RlbCI6ImNsYXVkZS1oYWlrdS00LTUiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KkQEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJ4CnZbeyJjb250ZW50IjoiV2hhdCBpcyB0aGUgY2FwaXRhbCBvZiBGcmFuY2U/Iiwicm9sZSI6InVzZXIifSx7InJvbGUiOiJzeXN0ZW0iLCJjb250ZW50IjoiWW91IGFyZSBhIGhlbHBmdWwgYXNzaXN0YW50In1dSrIBChJicmFpbnRydXN0Lm1ldHJpY3MSmwEKmAF7ImNvbXBsZXRpb25fdG9rZW5zIjozNiwicHJvbXB0X3Rva2VucyI6MTksInByb21wdF9jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMiOjAsInByb21wdF9jYWNoZWRfdG9rZW5zIjowLCJ0b2tlbnMiOjU1LCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zIjowfUouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAAA==" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cseFIFYboAMEjbA=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4dd53-194defe53ad8c696383ea8d2;Parent=4c1246be9be3daf8;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 17:05:23 GMT", + "Via" : "1.1 21c7c4234f218bb5110262cbbf01f870.cloudfront.net (CloudFront), 1.1 0df7f27a01014ab815259ca2d88193c6.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4dd53000000001af60319527ae280", + "x-amzn-RequestId" : "d0f47664-3746-40d9-b560-ede1ddc66365", + "X-Amz-Cf-Id" : "op7pQRDM1-b4bFBMiYWHe5PdIivjcE4zQKForBqG09apkLqypJboPw==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "90e0003e-1382-47dc-a394-cec76f5217e3", + "persistent" : true, + "insertionIndex" : 246 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-9294f422-5552-4bdd-8d60-9a88fb07ae29.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-9294f422-5552-4bdd-8d60-9a88fb07ae29.json new file mode 100644 index 00000000..261a1337 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-9294f422-5552-4bdd-8d60-9a88fb07ae29.json @@ -0,0 +1,39 @@ +{ + "id" : "9294f422-5552-4bdd-8d60-9a88fb07ae29", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CtEkCrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKfAQoFCgNidHgSlQEKEFUIA07UWRlBaJcs5FWLUNgSCDQnyDT51VfYKglyZWFzb25pbmcwATn3mDC4eU6rGEG7cQ9/hE6rGEocCgZjbGllbnQSEgoQbGFuZ2NoYWluLW9wZW5haUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAABL3IQoRCg9icmFpbnRydXN0LWphdmES4SEKEFUIA07UWRlBaJcs5FWLUNgSCKL70XtpC8PBIgg0J8g0+dVX2CoJcmVzcG9uc2VzMAE5JJqQQYJOqxhBxOLjfYROqxhKggwKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S5wsK5AtbeyJpZCI6InJzXzBiYTQ2NDhmYmIyYTMyYWIwMDY5ZjQwOTFmOWYxODgxOTVhNjI0YWQ2MDU1MGQ3YjZlIiwidHlwZSI6InJlYXNvbmluZyIsInN1bW1hcnkiOlt7InR5cGUiOiJzdW1tYXJ5X3RleHQiLCJ0ZXh0IjoiKipDYWxjdWxhdGluZyBzZXF1ZW5jZSB0ZXJtcyBhbmQgc3VtcyoqXG5cblRoZSB1c2VyIGlzIGFza2luZyBmb3IgdGhlIDEwdGggdGVybSBhbmQgdGhlIHN1bSBvZiB0aGUgZmlyc3QgMTAgdGVybXMgb2YgdGhlIHNlcXVlbmNlIGRlZmluZWQgYXMgYV9uID0gbihuKzEpLiBJIGZpbmQgdGhhdCB0aGUgMTB0aCB0ZXJtIGlzIDExMC4gRm9yIHRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zLCBJIGNhbGN1bGF0ZSBpdCBhcyBTID0gc3VtIG9mIG5eMiArIHN1bSBvZiBuLCB3aGljaCBnaXZlcyBtZSA0NDAuIFNvLCB0aGUgMTB0aCB0ZXJtIGlzIDExMCwgYW5kIHRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zIGlzIDQ0MC4ifSx7InR5cGUiOiJzdW1tYXJ5X3RleHQiLCJ0ZXh0IjoiKipDYWxjdWxhdGluZyB0aGUgMTB0aCB0ZXJtIGFuZCBzdW0gb2YgdGVybXMqKlxuXG5J4oCZbSBwcm92aWRpbmcgdGhlIDEwdGggdGVybSBhbmQgdGhlIHN1bSBvZiB0aGUgZmlyc3QgMTAgdGVybXMgb2YgdGhlIHNlcXVlbmNlIGRlZmluZWQgYXMgYV9uID0gbihuKzEpLiBUaGUgMTB0aCB0ZXJtIGlzIGFfMTAgPSAxMCDDlyAxMSA9IDExMC4gRm9yIHRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zLCBJIGNhbGN1bGF0ZSBpdCBhcyBTID0g4oiRbihuKzEpID0gNDQwLCB1c2luZyBlaXRoZXIgdGhlIGRpcmVjdCBzdW1zICgzODUgKyA1NSkgb3IgdGhlIGNsb3NlZCBmb3JtIGZvcm11bGEuIFNvIHRoZSBhbnN3ZXJzIGFyZTogdGhlIDEwdGggdGVybSBpcyAxMTAgYW5kIHRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zIGlzIDQ0MC4ifV19LHsiaWQiOiJtc2dfMGJhNDY0OGZiYjJhMzJhYjAwNjlmNDA5MjdjZDc4ODE5NThjMjcwMDU1MGQ0YTE2MTkiLCJ0eXBlIjoibWVzc2FnZSIsInN0YXR1cyI6ImNvbXBsZXRlZCIsImNvbnRlbnQiOlt7InR5cGUiOiJvdXRwdXRfdGV4dCIsImFubm90YXRpb25zIjpbXSwibG9ncHJvYnMiOltdLCJ0ZXh0IjoiVGhlIDEwdGggdGVybSBpcyAgXG4gIGHigoHigoAgPSAxMMK3KDEwKzEpID0gMTDCtzExID0gMTEwLiAgXG5cblRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zIGlzICBcbiAgU+KCgeKCgCA9IOKIkeKCmeKCjOKCgcK54oGwIG4obisxKSA9IOKIkeKCmeKCjOKCgcK54oGwIG7CsiArIOKIkeKCmeKCjOKCgcK54oGwIG4gIFxuICAgICAgPSAoMTDCtzExwrcyMSkvNiArICgxMMK3MTEpLzIgIFxuICAgICAgPSAzODUgKyA1NSAgXG4gICAgICA9IDQ0MC4gIFxuXG5FcXVpdmFsZW50bHksIG9uZSBjYW4gdXNlIHRoZSBjbG9zZWTigJBmb3JtICBcbiAgU+KCmSA9IG4obisxKShuKzIpLzMgIFxuc28gIFxuICBT4oKB4oKAID0gMTDCtzExwrcxMi8zID0gNDQwLiJ9XSwicm9sZSI6ImFzc2lzdGFudCJ9XUqhAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKJAQqGAXsicHJvdmlkZXIiOiJvcGVuYWkiLCJyZXF1ZXN0X3BhdGgiOiJyZXNwb25zZXMiLCJtb2RlbCI6Im80LW1pbmkiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdDozOTg5MyIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9So0SChVicmFpbnRydXN0LmlucHV0X2pzb24S8xEK8BFbeyJyb2xlIjoidXNlciIsImNvbnRlbnQiOiJMb29rIGF0IHRoaXMgc2VxdWVuY2U6IDIsIDYsIDEyLCAyMCwgMzAuIFdoYXQgaXMgdGhlIHBhdHRlcm4gYW5kIHdoYXQgd291bGQgYmUgdGhlIGZvcm11bGEgZm9yIHRoZSBudGggdGVybT9cbiJ9LHsiaWQiOiJyc18wYmE0NjQ4ZmJiMmEzMmFiMDA2OWY0MDhmYjA3ZTQ4MTk1YTk5YzYzNDY2NjNiYzQ1YSIsInN1bW1hcnkiOlt7InRleHQiOiIqKkFuYWx5emluZyB0aGUgc2VxdWVuY2UqKlxuXG5UaGUgdXNlciBwcmVzZW50cyB0aGUgc2VxdWVuY2U6IDIsIDYsIDEyLCAyMCwgMzAsIHdoaWNoIGNvcnJlc3BvbmRzIHRvIHByb25pYyBvciBvYmxvbmcgbnVtYmVycyBleHByZXNzZWQgYXMgbihuKzEpLiBGb3IgZXhhbXBsZSwgMSoyPTIsIDIqMz02LCAzKjQ9MTIsIGFuZCBzbyBmb3J0aC4gVGhlIGZvcm11bGEgZm9yIHRoZSBudGggdGVybSBpcyBhKG4pID0gbihuKzEpLiBJIG5vdGljZSB0aGF0IHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGNvbnNlY3V0aXZlIHRlcm1zICg0LCA2LCA4LCAxMCkgYXJlIGV2ZW4gbnVtYmVycyBzdGFydGluZyBhdCA0LCBpbmRpY2F0aW5nIGEgY29uc2lzdGVudCBpbmNyZWFzZS4gSWYgbiBzdGFydHMgYXQgMCwgdGhlbiBhKG4pID0gbihuKzEpLCB3aGljaCByZXN1bHRzIGluIDAgYXQgbj0wLiIsInR5cGUiOiJzdW1tYXJ5X3RleHQifSx7InRleHQiOiIqKkV4cGxvcmluZyB0aGUgcGF0dGVybiBvZiB0aGUgc2VxdWVuY2UqKlxuXG5TdGFydGluZyB3aXRoIG49MSwgdGhlIHBhdHRlcm4gbWlycm9ycyBuwrIrbiwgbGVhZGluZyB0byB0aGUgZm9ybXVsYSBhKG4pID0gbihuKzEpIGZvciBwcm9uaWMgbnVtYmVycy4gVGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGVybXMgKDQsIDYsIDgsIDEwLi4uKSBmb3JtIGFuIGFyaXRobWV0aWMgc2VxdWVuY2UsIGluY3JlYXNpbmcgYnkgMiBlYWNoIHRpbWUuIFNvLCBJIGNhbiBjbGVhcmx5IHN0YXRlIHRoYXQgdGhlIG50aCB0ZXJtIGlzIHRoZSBwcm9kdWN0IG9mIGNvbnNlY3V0aXZlIGludGVnZXJzLCB3aXRoIGEgc2ltcGxlIGFsdGVybmF0aXZlIGV4cHJlc3Npb24uIFdoZW4gaW5kZXhlZCBmcm9tIHplcm8sIHRoZSBmb3JtdWxhIHNoaWZ0cy4gVWx0aW1hdGVseSwgd2hhdCBzdGFuZHMgb3V0IGlzIHRoYXQgZWFjaCB0ZXJtIGZvbGxvd3MgdGhlIHJlbGF0aW9uc2hpcCBhX24gPSBuKG4rMSkuIiwidHlwZSI6InN1bW1hcnlfdGV4dCJ9LHsidGV4dCI6IioqRGVmaW5pbmcgdGhlIHNlcXVlbmNlIHBhdHRlcm4qKlxuXG5UaGUgc2VxdWVuY2UgcmVwcmVzZW50cyBwcm9uaWMgbnVtYmVycywgd2hlcmUgZWFjaCB0ZXJtLCBzdGFydGluZyBmcm9tIG49MSwgZm9sbG93cyB0aGUgZm9ybXVsYSBhX24gPSBuKG4rMSkuIFRoZXNlIG51bWJlcnMgYXJlIHRoZSBwcm9kdWN0cyBvZiBjb25zZWN1dGl2ZSBpbnRlZ2VyczogMiBhcyAxw5cyLCA2IGFzIDLDlzMsIGFuZCAxMiBhcyAzw5c0LiBJZiBJIHVzZWQgYSB6ZXJvLWJhc2VkIGluZGV4LCBJJ2Qgc2F5IGFfbiA9IG4obisxKSBwcm9kdWNlcyBhXzA9MCwgYnV0IHNpbmNlIHRoZSBzZXF1ZW5jZSBzdGFydHMgYXQgbj0xLCB0aGUgZmlyc3QgdGVybSBpcyAyLiBTbywgdGhlIGZpbmFsIGNvbmNsdXNpb24gaXMgdGhhdCBwcm9uaWMgbnVtYmVycyBhcmUgZGVmaW5lZCBieSBhX24gPSBuKG4rMSkuIiwidHlwZSI6InN1bW1hcnlfdGV4dCJ9XSwidHlwZSI6InJlYXNvbmluZyJ9LHsiaWQiOiJtc2dfMGJhNDY0OGZiYjJhMzJhYjAwNjlmNDA5MTljYzYwODE5NWIwZmI4NzVkODhmZGQyODAiLCJjb250ZW50IjpbeyJhbm5vdGF0aW9ucyI6W10sInRleHQiOiJFYWNoIHRlcm0gaXMgdGhlIHByb2R1Y3Qgb2YgdHdvIGNvbnNlY3V0aXZlIGludGVnZXJzOlxuXG4yID0gMcOXMiAgXG42ID0gMsOXMyAgXG4xMiA9IDPDlzQgIFxuMjAgPSA0w5c1ICBcbjMwID0gNcOXNiAgXG5cblNvIGlmIHlvdSBsYWJlbCB0aGUgdGVybXMgYeKCgSwgYeKCgiwgYeKCgywg4oCmIHRoZW5cblxu4oCDYeKCmSA9IG7igIkobisxKS5cblxuRXF1aXZhbGVudGx5LCBh4oKZID0gbsKyICsgbi4iLCJ0eXBlIjoib3V0cHV0X3RleHQiLCJsb2dwcm9icyI6W119XSwicm9sZSI6ImFzc2lzdGFudCIsInN0YXR1cyI6ImNvbXBsZXRlZCIsInR5cGUiOiJtZXNzYWdlIn0seyJyb2xlIjoidXNlciIsImNvbnRlbnQiOiJVc2luZyB0aGUgcGF0dGVybiB5b3UgZGlzY292ZXJlZCwgd2hhdCB3b3VsZCBiZSB0aGUgMTB0aCB0ZXJtPyBBbmQgY2FuIHlvdSBmaW5kIHRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zPyJ9XUp1ChJicmFpbnRydXN0Lm1ldHJpY3MSXwpdeyJjb21wbGV0aW9uX3Rva2VucyI6OTUxLCJwcm9tcHRfdG9rZW5zIjoxNjgsInRva2VucyI6MTExOSwiY29tcGxldGlvbl9yZWFzb25pbmdfdG9rZW5zIjo3Njh9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAA" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZfKGCxIAMEmYw=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4092d-264a5082478230ac4ca2a86d;Parent=389ea40374e1c39a;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 02:00:13 GMT", + "Via" : "1.1 4c9457912580c6114eec78b8fa604a20.cloudfront.net (CloudFront), 1.1 7605973575a3551426b82751020317de.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4092d000000002fbeda8ee12dba14", + "x-amzn-RequestId" : "a1690264-7aad-4df3-be78-1eab889ea2c6", + "X-Amz-Cf-Id" : "yw5o6mwxvPALrpZVrIWVssFzDuGArBsaQ4WbWzLC2k5LHZFAtAT99g==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "9294f422-5552-4bdd-8d60-9a88fb07ae29", + "persistent" : true, + "insertionIndex" : 234 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-97f73962-c2ec-4c5b-9d6d-d6b18be33c71.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-97f73962-c2ec-4c5b-9d6d-d6b18be33c71.json new file mode 100644 index 00000000..461cabc7 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-97f73962-c2ec-4c5b-9d6d-d6b18be33c71.json @@ -0,0 +1,39 @@ +{ + "id" : "97f73962-c2ec-4c5b-9d6d-d6b18be33c71", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "Ct0MCrgBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAooCg9zZXJ2aWNlLnZlcnNpb24SFQoTMC4zLjQtYjIyODA5ZS1ESVJUWQogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKfCwoRCg9icmFpbnRydXN0LWphdmESiQsKEJSQ1ZkBA+/Kdev5AQoDAFYSCNrtP+4HF+/9KhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5e0ZP4el/qxhBw8nxS+p/qxhKyQUKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SrgUKqwV7ImlkIjoibXNnXzAxNTZWMmZxcW1HZVp3eGRIOTRhWUxCMyIsImNvbnRlbnQiOlt7ImNpdGF0aW9ucyI6bnVsbCwidGV4dCI6IlRoZSBjYXBpdGFsIG9mIEZyYW5jZSBpcyAqKlBhcmlzKiouIEl0IGlzIGxvY2F0ZWQgaW4gdGhlIG5vcnRoLWNlbnRyYWwgcGFydCBvZiB0aGUgY291bnRyeSBhbG9uZyB0aGUgU2VpbmUgUml2ZXIgYW5kIGlzIHRoZSBsYXJnZXN0IGNpdHkgaW4gRnJhbmNlLiIsInR5cGUiOiJ0ZXh0IiwidmFsaWQiOnRydWV9XSwibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxIiwicm9sZSI6ImFzc2lzdGFudCIsInN0b3BfcmVhc29uIjoiZW5kX3R1cm4iLCJzdG9wX3NlcXVlbmNlIjpudWxsLCJ0eXBlIjoibWVzc2FnZSIsInVzYWdlIjp7ImNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMiOjAsImlucHV0X3Rva2VucyI6MTksIm91dHB1dF90b2tlbnMiOjM2LCJzZXJ2ZXJfdG9vbF91c2UiOm51bGwsInNlcnZpY2VfdGllciI6InN0YW5kYXJkIiwidmFsaWQiOnRydWUsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIiwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH19LCJ2YWxpZCI6dHJ1ZSwic3RvcF9kZXRhaWxzIjpudWxsfUqYAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKAAQp+eyJwcm92aWRlciI6ImFudGhyb3BpYyIsInJlcXVlc3RfcGF0aCI6InYxL21lc3NhZ2VzIiwibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01IiwicmVxdWVzdF9iYXNlX3VyaSI6IiIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SpEBChVicmFpbnRydXN0LmlucHV0X2pzb24SeAp2W3siY29udGVudCI6IldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlPyIsInJvbGUiOiJ1c2VyIn0seyJyb2xlIjoic3lzdGVtIiwiY29udGVudCI6IllvdSBhcmUgYSBoZWxwZnVsIGFzc2lzdGFudCJ9XUrUAQoSYnJhaW50cnVzdC5tZXRyaWNzEr0BCroBeyJjb21wbGV0aW9uX3Rva2VucyI6MzYsInByb21wdF90b2tlbnMiOjE5LCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fMWhfdG9rZW5zIjowLCJwcm9tcHRfY2FjaGVkX3Rva2VucyI6MCwidG9rZW5zIjo1NSwidGltZV90b19maXJzdF90b2tlbiI6MC4wMjQxMDQ5MTgsInByb21wdF9jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMiOjB9Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAA" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cseE5HTOoAMEVvg=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4dd52-75e08f477e28e3e26be1db0f;Parent=38904f26485a8cc6;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 17:05:22 GMT", + "Via" : "1.1 b7d7903ada432685f0e90f0ca261d864.cloudfront.net (CloudFront), 1.1 0df7f27a01014ab815259ca2d88193c6.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4dd52000000002eee535e020d29df", + "x-amzn-RequestId" : "8217c8d4-7e51-4984-8b66-a438a812b4cf", + "X-Amz-Cf-Id" : "42X5huKjnCjai2cFQ-Tg9I94uo1Ye-abilhf3LbIr_6nd_Sg0ehOAQ==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "97f73962-c2ec-4c5b-9d6d-d6b18be33c71", + "persistent" : true, + "insertionIndex" : 247 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-98d8a3f8-bee0-4a83-818d-889dab9996ef.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-98d8a3f8-bee0-4a83-818d-889dab9996ef.json new file mode 100644 index 00000000..38c59bdc --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-98d8a3f8-bee0-4a83-818d-889dab9996ef.json @@ -0,0 +1,39 @@ +{ + "id" : "98d8a3f8-bee0-4a83-818d-889dab9996ef", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CuwLCrgBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAooCg9zZXJ2aWNlLnZlcnNpb24SFQoTMC4zLjQtYjIyODA5ZS1ESVJUWQogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKuCgoRCg9icmFpbnRydXN0LWphdmESmAoKEBwmK54e+T1rZTkAL9YBmUoSCKuzLcxdvbWMKhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5Ixk2qOt/qxhBQjKd5et/qxhK+gQKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S3wQK3AR7Im1vZGVsIjoiY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMSIsImlkIjoibXNnXzAxR01jY3B6VTV3RWtQZ3U5V0N4dUt4aSIsInR5cGUiOiJtZXNzYWdlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRlbnQiOlt7InR5cGUiOiJ0ZXh0IiwidGV4dCI6IlRoZSBjYXBpdGFsIG9mIEZyYW5jZSBpcyAqKlBhcmlzKiouIEl0IGlzIGxvY2F0ZWQgaW4gdGhlIG5vcnRoLWNlbnRyYWwgcGFydCBvZiB0aGUgY291bnRyeSBhbG9uZyB0aGUgU2VpbmUgUml2ZXIgYW5kIGlzIHRoZSBsYXJnZXN0IGNpdHkgaW4gRnJhbmNlLiJ9XSwic3RvcF9yZWFzb24iOiJlbmRfdHVybiIsInN0b3Bfc2VxdWVuY2UiOm51bGwsInN0b3BfZGV0YWlscyI6bnVsbCwidXNhZ2UiOnsiaW5wdXRfdG9rZW5zIjoxOSwiY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zIjowLCJjYWNoZV9yZWFkX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH0sIm91dHB1dF90b2tlbnMiOjM2LCJzZXJ2aWNlX3RpZXIiOiJzdGFuZGFyZCIsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIn19SpgBChNicmFpbnRydXN0Lm1ldGFkYXRhEoABCn57InByb3ZpZGVyIjoiYW50aHJvcGljIiwicmVxdWVzdF9wYXRoIjoidjEvbWVzc2FnZXMiLCJtb2RlbCI6ImNsYXVkZS1oYWlrdS00LTUiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KkQEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJ4CnZbeyJjb250ZW50IjoiV2hhdCBpcyB0aGUgY2FwaXRhbCBvZiBGcmFuY2U/Iiwicm9sZSI6InVzZXIifSx7InJvbGUiOiJzeXN0ZW0iLCJjb250ZW50IjoiWW91IGFyZSBhIGhlbHBmdWwgYXNzaXN0YW50In1dSrIBChJicmFpbnRydXN0Lm1ldHJpY3MSmwEKmAF7ImNvbXBsZXRpb25fdG9rZW5zIjozNiwicHJvbXB0X3Rva2VucyI6MTksInByb21wdF9jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMiOjAsInByb21wdF9jYWNoZWRfdG9rZW5zIjowLCJ0b2tlbnMiOjU1LCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zIjowfUouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAAA==" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cseF9ETVoAMEByA=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4dd58-045ed44a01ead96857b7e4bb;Parent=7d8907d03a95a71d;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 17:05:29 GMT", + "Via" : "1.1 2be627c4e85d6d9d9e32a7523e1b67ee.cloudfront.net (CloudFront), 1.1 ee5f8da78d4211a93c9dba8864a4067e.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4dd58000000004f40388e25f54801", + "x-amzn-RequestId" : "31f744f6-b574-43e9-9196-86ec5fe188c9", + "X-Amz-Cf-Id" : "7Wv1z-ND0XXD5TP71OAjWDjIkoZUI2wp1jko2WFFFY4jvX6P9dNA1w==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "98d8a3f8-bee0-4a83-818d-889dab9996ef", + "persistent" : true, + "insertionIndex" : 244 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-9d6140bf-20ba-46d9-bf52-04252f2cfeb8.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-9d6140bf-20ba-46d9-bf52-04252f2cfeb8.json new file mode 100644 index 00000000..8802589e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-9d6140bf-20ba-46d9-bf52-04252f2cfeb8.json @@ -0,0 +1,39 @@ +{ + "id" : "9d6140bf-20ba-46d9-bf52-04252f2cfeb8", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CuwLCrgBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAooCg9zZXJ2aWNlLnZlcnNpb24SFQoTMC4zLjQtYjIyODA5ZS1ESVJUWQogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKuCgoRCg9icmFpbnRydXN0LWphdmESmAoKEEJXwqVRV8/KmKwe93zIJ/MSCMb7idgXlfFCKhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5f2gyCux/qxhBOSJER+x/qxhK+gQKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S3wQK3AR7Im1vZGVsIjoiY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMSIsImlkIjoibXNnXzAxTTlFQURwTjg1S3gxNU1mRmdWb3UzaiIsInR5cGUiOiJtZXNzYWdlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRlbnQiOlt7InR5cGUiOiJ0ZXh0IiwidGV4dCI6IlRoZSBjYXBpdGFsIG9mIEZyYW5jZSBpcyAqKlBhcmlzKiouIEl0IGlzIGxvY2F0ZWQgaW4gdGhlIG5vcnRoLWNlbnRyYWwgcGFydCBvZiB0aGUgY291bnRyeSBhbG9uZyB0aGUgU2VpbmUgUml2ZXIgYW5kIGlzIHRoZSBsYXJnZXN0IGNpdHkgaW4gRnJhbmNlLiJ9XSwic3RvcF9yZWFzb24iOiJlbmRfdHVybiIsInN0b3Bfc2VxdWVuY2UiOm51bGwsInN0b3BfZGV0YWlscyI6bnVsbCwidXNhZ2UiOnsiaW5wdXRfdG9rZW5zIjoxOSwiY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zIjowLCJjYWNoZV9yZWFkX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH0sIm91dHB1dF90b2tlbnMiOjM2LCJzZXJ2aWNlX3RpZXIiOiJzdGFuZGFyZCIsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIn19SpgBChNicmFpbnRydXN0Lm1ldGFkYXRhEoABCn57InByb3ZpZGVyIjoiYW50aHJvcGljIiwicmVxdWVzdF9wYXRoIjoidjEvbWVzc2FnZXMiLCJtb2RlbCI6ImNsYXVkZS1oYWlrdS00LTUiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KkQEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJ4CnZbeyJjb250ZW50IjoiV2hhdCBpcyB0aGUgY2FwaXRhbCBvZiBGcmFuY2U/Iiwicm9sZSI6InVzZXIifSx7InJvbGUiOiJzeXN0ZW0iLCJjb250ZW50IjoiWW91IGFyZSBhIGhlbHBmdWwgYXNzaXN0YW50In1dSrIBChJicmFpbnRydXN0Lm1ldHJpY3MSmwEKmAF7ImNvbXBsZXRpb25fdG9rZW5zIjozNiwicHJvbXB0X3Rva2VucyI6MTksInByb21wdF9jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMiOjAsInByb21wdF9jYWNoZWRfdG9rZW5zIjowLCJ0b2tlbnMiOjU1LCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zIjowfUouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAAA==" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cseGOFGiIAMEdXw=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4dd5a-73d0b6ff3bc2504676decda9;Parent=5cb2fd591711c13c;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 17:05:30 GMT", + "Via" : "1.1 d118b2ea8414d381f46f91331ab67f02.cloudfront.net (CloudFront), 1.1 ee5f8da78d4211a93c9dba8864a4067e.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4dd5a000000002d951f3871f5cdca", + "x-amzn-RequestId" : "174bb784-1138-4cf0-80aa-33472e82b69c", + "X-Amz-Cf-Id" : "U3iYZEMDnN6WkK8otECcOR_2wEVX5SzlnUtXDSkmsIoe6W1KECKQVQ==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "9d6140bf-20ba-46d9-bf52-04252f2cfeb8", + "persistent" : true, + "insertionIndex" : 243 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-c13ae131-4f12-40a1-ab09-647658eb0bc3.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-c13ae131-4f12-40a1-ab09-647658eb0bc3.json new file mode 100644 index 00000000..7e700772 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-c13ae131-4f12-40a1-ab09-647658eb0bc3.json @@ -0,0 +1,39 @@ +{ + "id" : "c13ae131-4f12-40a1-ab09-647658eb0bc3", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CtgKCrgBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAooCg9zZXJ2aWNlLnZlcnNpb24SFQoTMC4zLjQtYjIyODA5ZS1ESVJUWQogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKaCQoRCg9icmFpbnRydXN0LWphdmEShAkKECRIpVlolhZqJqJYYazH7NkSCJ8eV996EPX5KhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5BKiZC+l/qxhB/WBLpOl/qxhKkAQKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24S9QMK8gN7Im1vZGVsIjoiY2xhdWRlLXNvbm5ldC00LTUtMjAyNTA5MjkiLCJpZCI6Im1zZ18wMTRCaTRZV3ZDSkxrcWNYc0o1RXFkZ2MiLCJ0eXBlIjoibWVzc2FnZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZW50IjpbeyJ0eXBlIjoidGV4dCIsInRleHQiOiJUaGUgY2FwaXRhbCBvZiBGcmFuY2UgaXMgUGFyaXMuIn1dLCJzdG9wX3JlYXNvbiI6ImVuZF90dXJuIiwic3RvcF9zZXF1ZW5jZSI6bnVsbCwic3RvcF9kZXRhaWxzIjpudWxsLCJ1c2FnZSI6eyJpbnB1dF90b2tlbnMiOjEyLCJjYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMiOjc0MjUsImNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zIjowLCJjYWNoZV9jcmVhdGlvbiI6eyJlcGhlbWVyYWxfNW1faW5wdXRfdG9rZW5zIjozNzEwLCJlcGhlbWVyYWxfMWhfaW5wdXRfdG9rZW5zIjozNzE1fSwib3V0cHV0X3Rva2VucyI6MTAsInNlcnZpY2VfdGllciI6InN0YW5kYXJkIiwiaW5mZXJlbmNlX2dlbyI6Im5vdF9hdmFpbGFibGUifX1KowEKE2JyYWludHJ1c3QubWV0YWRhdGESiwEKiAF7InByb3ZpZGVyIjoiYW50aHJvcGljIiwicmVxdWVzdF9wYXRoIjoidjEvbWVzc2FnZXMiLCJtb2RlbCI6ImNsYXVkZS1zb25uZXQtNC01LTIwMjUwOTI5IiwicmVxdWVzdF9iYXNlX3VyaSI6IiIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SlcKFWJyYWludHJ1c3QuaW5wdXRfanNvbhI+CjxbeyJjb250ZW50IjoiV2hhdCBpcyB0aGUgY2FwaXRhbCBvZiBGcmFuY2U/Iiwicm9sZSI6InVzZXIifV1KuAEKEmJyYWludHJ1c3QubWV0cmljcxKhAQqeAXsiY29tcGxldGlvbl90b2tlbnMiOjEwLCJwcm9tcHRfdG9rZW5zIjoxMiwicHJvbXB0X2NhY2hlX2NyZWF0aW9uXzFoX3Rva2VucyI6MzcxNSwicHJvbXB0X2NhY2hlZF90b2tlbnMiOjAsInRva2VucyI6MjIsInByb21wdF9jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMiOjM3MTB9Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAA" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cseEeEqSIAMEnQg=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4dd4f-0078f8c618f258e9039f7961;Parent=360ca855d5e4d60e;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 17:05:19 GMT", + "Via" : "1.1 9257f9c4051fe8bd6cc4a09855b66350.cloudfront.net (CloudFront), 1.1 a40ac7dad0e348fc93799233c9af5960.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4dd4f0000000021bd7e2acd5662f0", + "x-amzn-RequestId" : "edd69fb6-c6ad-4934-9be0-fc038866a148", + "X-Amz-Cf-Id" : "pX7jRpcl0r55aLbaj4nEkBicsT_lb-AAW1JHzEmGHPVJQe0MUAaTKA==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "c13ae131-4f12-40a1-ab09-647658eb0bc3", + "persistent" : true, + "insertionIndex" : 248 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-d6d01c21-41ac-4abe-b193-c8570176e7d8.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-d6d01c21-41ac-4abe-b193-c8570176e7d8.json new file mode 100644 index 00000000..8c9ad4f7 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-d6d01c21-41ac-4abe-b193-c8570176e7d8.json @@ -0,0 +1,39 @@ +{ + "id" : "d6d01c21-41ac-4abe-b193-c8570176e7d8", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "Ct0MCrgBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAooCg9zZXJ2aWNlLnZlcnNpb24SFQoTMC4zLjQtYjIyODA5ZS1ESVJUWQogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKfCwoRCg9icmFpbnRydXN0LWphdmESiQsKEDDQG8QvAUj4xEjA73mpOF0SCA4IzpMFaJEwKhlhbnRocm9waWMubWVzc2FnZXMuY3JlYXRlMAE5YABPaex/qxhBOZbNnex/qxhKyQUKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SrgUKqwV7ImlkIjoibXNnXzAxQmtoQ3M3b3pxWXBpWlBZUEJRMW5kTiIsImNvbnRlbnQiOlt7ImNpdGF0aW9ucyI6bnVsbCwidGV4dCI6IlRoZSBjYXBpdGFsIG9mIEZyYW5jZSBpcyAqKlBhcmlzKiouIEl0IGlzIGxvY2F0ZWQgaW4gdGhlIG5vcnRoLWNlbnRyYWwgcGFydCBvZiB0aGUgY291bnRyeSBhbG9uZyB0aGUgU2VpbmUgUml2ZXIgYW5kIGlzIHRoZSBsYXJnZXN0IGNpdHkgaW4gRnJhbmNlLiIsInR5cGUiOiJ0ZXh0IiwidmFsaWQiOnRydWV9XSwibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxIiwicm9sZSI6ImFzc2lzdGFudCIsInN0b3BfcmVhc29uIjoiZW5kX3R1cm4iLCJzdG9wX3NlcXVlbmNlIjpudWxsLCJ0eXBlIjoibWVzc2FnZSIsInVzYWdlIjp7ImNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyI6MCwiY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMiOjAsImlucHV0X3Rva2VucyI6MTksIm91dHB1dF90b2tlbnMiOjM2LCJzZXJ2ZXJfdG9vbF91c2UiOm51bGwsInNlcnZpY2VfdGllciI6InN0YW5kYXJkIiwidmFsaWQiOnRydWUsImluZmVyZW5jZV9nZW8iOiJub3RfYXZhaWxhYmxlIiwiY2FjaGVfY3JlYXRpb24iOnsiZXBoZW1lcmFsXzVtX2lucHV0X3Rva2VucyI6MCwiZXBoZW1lcmFsXzFoX2lucHV0X3Rva2VucyI6MH19LCJ2YWxpZCI6dHJ1ZSwic3RvcF9kZXRhaWxzIjpudWxsfUqYAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKAAQp+eyJwcm92aWRlciI6ImFudGhyb3BpYyIsInJlcXVlc3RfcGF0aCI6InYxL21lc3NhZ2VzIiwibW9kZWwiOiJjbGF1ZGUtaGFpa3UtNC01IiwicmVxdWVzdF9iYXNlX3VyaSI6IiIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SpEBChVicmFpbnRydXN0LmlucHV0X2pzb24SeAp2W3siY29udGVudCI6IldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlPyIsInJvbGUiOiJ1c2VyIn0seyJyb2xlIjoic3lzdGVtIiwiY29udGVudCI6IllvdSBhcmUgYSBoZWxwZnVsIGFzc2lzdGFudCJ9XUrUAQoSYnJhaW50cnVzdC5tZXRyaWNzEr0BCroBeyJjb21wbGV0aW9uX3Rva2VucyI6MzYsInByb21wdF90b2tlbnMiOjE5LCJwcm9tcHRfY2FjaGVfY3JlYXRpb25fMWhfdG9rZW5zIjowLCJwcm9tcHRfY2FjaGVkX3Rva2VucyI6MCwidG9rZW5zIjo1NSwidGltZV90b19maXJzdF90b2tlbiI6MC4wMDU0NDMxOTgsInByb21wdF9jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMiOjB9Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAA" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cseGcEKNoAMEnng=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4dd5c-7dd541fb4ded191b52feb320;Parent=6fcf029ac18791b2;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 17:05:32 GMT", + "Via" : "1.1 c9f68a0c96944962731456040c591f26.cloudfront.net (CloudFront), 1.1 4ac8d091dce10e726cfc5404bfed72b8.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4dd5c000000001841a520c0f52dc3", + "x-amzn-RequestId" : "d734ce80-35a4-4160-a313-780165dc1aa2", + "X-Amz-Cf-Id" : "nWVjPERm8srxLZs3zbwDXNZCZ7qXI-xHtAFVgSgA4Kq99DX45HXNlA==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "d6d01c21-41ac-4abe-b193-c8570176e7d8", + "persistent" : true, + "insertionIndex" : 242 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-d95535f4-bef1-4619-a985-dcd995c550d6.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-d95535f4-bef1-4619-a985-dcd995c550d6.json new file mode 100644 index 00000000..6368317b --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-d95535f4-bef1-4619-a985-dcd995c550d6.json @@ -0,0 +1,39 @@ +{ + "id" : "d95535f4-bef1-4619-a985-dcd995c550d6", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "Cp4qCrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBL0BQoFCgNidHgSlwEKEHvPMgfk+Pldcj70GBARyncSCNkXOsWPfFGbKgthdHRhY2htZW50czABORIn4al8TqsYQQQ0Ue98TqsYShwKBmNsaWVudBISChBsYW5nY2hhaW4tb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEpYBChC2MmU3crwvf8h/HGgRheJZEghcFtXZmaf7kioLYXR0YWNobWVudHMwATkK/1LvfE6rGEHOeztLfU6rGEobCgZjbGllbnQSEQoPc3ByaW5nYWktb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEo0BChDsz6ifrF7i5HgGMWXhFesPEgjspbr+zTx6HSoLYXR0YWNobWVudHMwATmCVz5LfU6rGEHanMF7fU6rGEoSCgZjbGllbnQSCAoGb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEo0BChCyKnBk2Vf5033JNwIFoBSaEggG4ORdiFZBfyoLY29tcGxldGlvbnMwATmUz8d7fU6rGEHHJFisfU6rGEoSCgZjbGllbnQSCAoGb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEpcBChA9ARfjIYF+UAd9qTtAG03/EgiATEINbTFNcyoLY29tcGxldGlvbnMwATl1f1qsfU6rGEGsukTdfU6rGEocCgZjbGllbnQSEgoQbGFuZ2NoYWluLW9wZW5haUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAABLvIgoRCg9icmFpbnRydXN0LWphdmESuAcKEHvPMgfk+Pldcj70GBARyncSCJW0zWN3/ZUtIgjZFzrFj3xRmyoPQ2hhdCBDb21wbGV0aW9uMAM5roqOqnxOqxhB3shM73xOqxhKrwEKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SlAEKkQFbeyJpbmRleCI6MCwibWVzc2FnZSI6eyJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6IlRoZSBpbWFnZSBpcyByZWQuIiwicmVmdXNhbCI6bnVsbCwiYW5ub3RhdGlvbnMiOltdfSwibG9ncHJvYnMiOm51bGwsImZpbmlzaF9yZWFzb24iOiJzdG9wIn1dSqwBChNicmFpbnRydXN0Lm1ldGFkYXRhEpQBCpEBeyJwcm92aWRlciI6Im9wZW5haSIsInJlcXVlc3RfcGF0aCI6ImNoYXQvY29tcGxldGlvbnMiLCJtb2RlbCI6ImdwdC00by1taW5pIiwicmVxdWVzdF9iYXNlX3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6Mzk4OTMiLCJyZXF1ZXN0X21ldGhvZCI6IlBPU1QifUrJAgoVYnJhaW50cnVzdC5pbnB1dF9qc29uEq8CCqwCW3sicm9sZSI6InN5c3RlbSIsImNvbnRlbnQiOiJ5b3UgYXJlIGEgaGVscGZ1bCBhc3Npc3RhbnQifSx7InJvbGUiOiJ1c2VyIiwiY29udGVudCI6W3sidHlwZSI6InRleHQiLCJ0ZXh0IjoiV2hhdCBjb2xvciBpcyB0aGlzIGltYWdlPyJ9LHsidHlwZSI6ImltYWdlX3VybCIsImltYWdlX3VybCI6eyJ1cmwiOiJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFFQUFBQUJDQVlBQUFBZkZjU0pBQUFBRFVsRVFWUjQybVA4ejhEd0h3QUZCUUlBWDhqeDBnQUFBQUJKUlU1RXJrSmdnZz09In19XX1dSlIKEmJyYWludHJ1c3QubWV0cmljcxI8Cjp7ImNvbXBsZXRpb25fdG9rZW5zIjo1LCJwcm9tcHRfdG9rZW5zIjo4NTIyLCJ0b2tlbnMiOjg1Mjd9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAAErgHChC2MmU3crwvf8h/HGgRheJZEggc5PhaUVffYyIIXBbV2Zmn+5IqD0NoYXQgQ29tcGxldGlvbjABOYatEPB8TqsYQb+hy0p9TqsYSq8BChZicmFpbnRydXN0Lm91dHB1dF9qc29uEpQBCpEBW3siaW5kZXgiOjAsIm1lc3NhZ2UiOnsicm9sZSI6ImFzc2lzdGFudCIsImNvbnRlbnQiOiJUaGUgaW1hZ2UgaXMgcmVkLiIsInJlZnVzYWwiOm51bGwsImFubm90YXRpb25zIjpbXX0sImxvZ3Byb2JzIjpudWxsLCJmaW5pc2hfcmVhc29uIjoic3RvcCJ9XUqsAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKUAQqRAXsicHJvdmlkZXIiOiJvcGVuYWkiLCJyZXF1ZXN0X3BhdGgiOiJjaGF0L2NvbXBsZXRpb25zIiwibW9kZWwiOiJncHQtNG8tbWluaSIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KyQIKFWJyYWludHJ1c3QuaW5wdXRfanNvbhKvAgqsAlt7ImNvbnRlbnQiOiJ5b3UgYXJlIGEgaGVscGZ1bCBhc3Npc3RhbnQiLCJyb2xlIjoic3lzdGVtIn0seyJjb250ZW50IjpbeyJ0eXBlIjoidGV4dCIsInRleHQiOiJXaGF0IGNvbG9yIGlzIHRoaXMgaW1hZ2U/In0seyJ0eXBlIjoiaW1hZ2VfdXJsIiwiaW1hZ2VfdXJsIjp7InVybCI6ImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQUVBQUFBQkNBWUFBQUFmRmNTSkFBQUFEVWxFUVZSNDJtUDh6OER3SHdBRkJRSUFYOGp4MGdBQUFBQkpSVTVFcmtKZ2dnPT0ifX1dLCJyb2xlIjoidXNlciJ9XUpSChJicmFpbnRydXN0Lm1ldHJpY3MSPAo6eyJjb21wbGV0aW9uX3Rva2VucyI6NSwicHJvbXB0X3Rva2VucyI6ODUyMiwidG9rZW5zIjo4NTI3fUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3RKLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn16AIUBAQEAABLJBwoQ7M+on6xe4uR4BjFl4RXrDxIInOv3KFoF+wQiCOyluv7NPHodKg9DaGF0IENvbXBsZXRpb24wATm5125MfU6rGEEYNrx7fU6rGErAAQoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhKlAQqiAVt7ImluZGV4IjowLCJtZXNzYWdlIjp7InJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZW50IjoiVGhlIGltYWdlIGlzIGEgc29saWQgc2hhZGUgb2YgcmVkLiIsInJlZnVzYWwiOm51bGwsImFubm90YXRpb25zIjpbXX0sImxvZ3Byb2JzIjpudWxsLCJmaW5pc2hfcmVhc29uIjoic3RvcCJ9XUqsAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKUAQqRAXsicHJvdmlkZXIiOiJvcGVuYWkiLCJyZXF1ZXN0X3BhdGgiOiJjaGF0L2NvbXBsZXRpb25zIiwibW9kZWwiOiJncHQtNG8tbWluaSIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KyQIKFWJyYWludHJ1c3QuaW5wdXRfanNvbhKvAgqsAlt7ImNvbnRlbnQiOiJ5b3UgYXJlIGEgaGVscGZ1bCBhc3Npc3RhbnQiLCJyb2xlIjoic3lzdGVtIn0seyJjb250ZW50IjpbeyJ0ZXh0IjoiV2hhdCBjb2xvciBpcyB0aGlzIGltYWdlPyIsInR5cGUiOiJ0ZXh0In0seyJpbWFnZV91cmwiOnsidXJsIjoiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBRUFBQUFCQ0FZQUFBQWZGY1NKQUFBQURVbEVRVlI0Mm1QOHo4RHdId0FGQlFJQVg4angwZ0FBQUFCSlJVNUVya0pnZ2c9PSJ9LCJ0eXBlIjoiaW1hZ2VfdXJsIn1dLCJyb2xlIjoidXNlciJ9XUpSChJicmFpbnRydXN0Lm1ldHJpY3MSPAo6eyJjb21wbGV0aW9uX3Rva2VucyI6OSwicHJvbXB0X3Rva2VucyI6ODUyMiwidG9rZW5zIjo4NTMxfUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3RKLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn16AIUBAQEAABKKBgoQsipwZNlX+dN9yTcCBaAUmhIITxEUKxX6rRgiCAbg5F2IVkF/Kg9DaGF0IENvbXBsZXRpb24wATm8Mlp8fU6rGEFgKlSsfU6rGEq9AQoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhKiAQqfAVt7ImluZGV4IjowLCJtZXNzYWdlIjp7InJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZW50IjoiVGhlIGNhcGl0YWwgb2YgRnJhbmNlIGlzIFBhcmlzLiIsInJlZnVzYWwiOm51bGwsImFubm90YXRpb25zIjpbXX0sImxvZ3Byb2JzIjpudWxsLCJmaW5pc2hfcmVhc29uIjoic3RvcCJ9XUqsAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKUAQqRAXsicHJvdmlkZXIiOiJvcGVuYWkiLCJyZXF1ZXN0X3BhdGgiOiJjaGF0L2NvbXBsZXRpb25zIiwibW9kZWwiOiJncHQtNG8tbWluaSIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KkQEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJ4CnZbeyJjb250ZW50IjoieW91IGFyZSBhIGhlbHBmdWwgYXNzaXN0YW50Iiwicm9sZSI6InN5c3RlbSJ9LHsiY29udGVudCI6IldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlPyIsInJvbGUiOiJ1c2VyIn1dSk4KEmJyYWludHJ1c3QubWV0cmljcxI4CjZ7ImNvbXBsZXRpb25fdG9rZW5zIjo3LCJwcm9tcHRfdG9rZW5zIjoyMywidG9rZW5zIjozMH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAASigYKED0BF+MhgX5QB32pO0AbTf8SCI5qmhGRVdoSIgiATEINbTFNcyoPQ2hhdCBDb21wbGV0aW9uMAM5qaeLrH1OqxhBUYFA3X1OqxhKvQEKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SogEKnwFbeyJpbmRleCI6MCwibWVzc2FnZSI6eyJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6IlRoZSBjYXBpdGFsIG9mIEZyYW5jZSBpcyBQYXJpcy4iLCJyZWZ1c2FsIjpudWxsLCJhbm5vdGF0aW9ucyI6W119LCJsb2dwcm9icyI6bnVsbCwiZmluaXNoX3JlYXNvbiI6InN0b3AifV1KrAEKE2JyYWludHJ1c3QubWV0YWRhdGESlAEKkQF7InByb3ZpZGVyIjoib3BlbmFpIiwicmVxdWVzdF9wYXRoIjoiY2hhdC9jb21wbGV0aW9ucyIsIm1vZGVsIjoiZ3B0LTRvLW1pbmkiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdDozOTg5MyIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SpEBChVicmFpbnRydXN0LmlucHV0X2pzb24SeAp2W3sicm9sZSI6InN5c3RlbSIsImNvbnRlbnQiOiJ5b3UgYXJlIGEgaGVscGZ1bCBhc3Npc3RhbnQifSx7InJvbGUiOiJ1c2VyIiwiY29udGVudCI6IldoYXQgaXMgdGhlIGNhcGl0YWwgb2YgRnJhbmNlPyJ9XUpOChJicmFpbnRydXN0Lm1ldHJpY3MSOAo2eyJjb21wbGV0aW9uX3Rva2VucyI6NywicHJvbXB0X3Rva2VucyI6MjMsInRva2VucyI6MzB9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAA" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZaIFreIAMEA9w=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4090d-3f3f39b50ba700de323ffa1b;Parent=183c55d7b3e59f46;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 01:59:41 GMT", + "Via" : "1.1 b7d7903ada432685f0e90f0ca261d864.cloudfront.net (CloudFront), 1.1 fbb003dfc0617e3e058e3dac791dfd5a.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4090d0000000020450c542c10d558", + "x-amzn-RequestId" : "72deb0b3-3aa1-4309-97c1-64042a7b0b2c", + "X-Amz-Cf-Id" : "8Vr9lIG9I6WkIX9E7dJXPlZ8caYaotkV1MR5SbJ82JRgwiijKO4rFg==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "d95535f4-bef1-4619-a985-dcd995c550d6", + "persistent" : true, + "insertionIndex" : 237 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-eab030fd-4e00-4af8-b5a6-2759e4759e9f.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-eab030fd-4e00-4af8-b5a6-2759e4759e9f.json new file mode 100644 index 00000000..7a8afee5 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-eab030fd-4e00-4af8-b5a6-2759e4759e9f.json @@ -0,0 +1,39 @@ +{ + "id" : "eab030fd-4e00-4af8-b5a6-2759e4759e9f", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CowzCrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKKFwoYChZicmFpbnRydXN0LWF3cy1iZWRyb2NrEt4PChCs0o61e3smoIhfHLxtu/wHEghbRsx184O6RCIINny8Q4m05CEqEGJlZHJvY2suY29udmVyc2UwATkb/l+ZeE6rGEFV6qImeU6rGEr5CgoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhLeCgrbClt7ImNvbnRlbnQiOlt7InRleHQiOiJUaGUgY2FwaXRhbCBvZiBGcmFuY2UgaXMgUGFyaXMuIEl0IGlzIG5vdCBvbmx5IHRoZSBjYXBpdGFsIGJ1dCBhbHNvIHRoZSBsYXJnZXN0IGNpdHkgaW4gdGhlIGNvdW50cnksIGtub3duIGZvciBpdHMgcmljaCBoaXN0b3J5LCBjdWx0dXJlLCBhbmQgbGFuZG1hcmtzLiBQYXJpcyBpcyBvZnRlbiByZWZlcnJlZCB0byBhcyBcIlRoZSBDaXR5IG9mIExpZ2h0XCIgKExhIFZpbGxlIEx1bWnDqHJlKSBhbmQgXCJUaGUgQ2l0eSBvZiBMb3ZlXCIgKExhIFZpbGxlIGVuIFJvc2UpIGR1ZSB0byBpdHMgY29udHJpYnV0aW9ucyB0byBhcnQsIGN1bHR1cmUsIGFuZCByb21hbmNlLlxuXG5QYXJpcyBpcyBkaXZpZGVkIGludG8gMjAgYWRtaW5pc3RyYXRpdmUgYXJyb25kaXNzZW1lbnRzIChtdW5pY2lwYWxpdGllcykgYW5kIGlzIGxvY2F0ZWQgaW4gdGhlIG5vcnRoLWNlbnRyYWwgcGFydCBvZiBGcmFuY2UsIGFsb25nIHRoZSBTZWluZSBSaXZlci4gSXQgaGFzIGEgcG9wdWxhdGlvbiBvZiBhcHByb3hpbWF0ZWx5IDIuMSBtaWxsaW9uIHBlb3BsZSB3aXRoaW4gaXRzIGNpdHkgbGltaXRzLCBhbmQgdGhlIGdyZWF0ZXIgUGFyaXMgbWV0cm9wb2xpdGFuIGFyZWEgaXMgaG9tZSB0byBvdmVyIDEyIG1pbGxpb24gcGVvcGxlLlxuXG5UaGUgY2l0eSBpcyByZW5vd25lZCBmb3IgaXRzIGljb25pYyBsYW5kbWFya3MsIHN1Y2ggYXMgdGhlIEVpZmZlbCBUb3dlciwgdGhlIE5vdHJlLURhbWUgQ2F0aGVkcmFsLCB0aGUgTG91dnJlIE11c2V1bSwgdGhlIENoYW1wcy3DiWx5c8OpZXMsIHRoZSBBcmMgZGUgVHJpb21waGUsIGFuZCB0aGUgQmFzaWxpY2Egb2YgdGhlIFNhY3LDqS1DxZN1ci4gUGFyaXMgaXMgYWxzbyBmYW1vdXMgZm9yIGl0cyBjdWlzaW5lLCBmYXNoaW9uLCBhcnQsIGFuZCBpdHMgcm9sZSBpbiB0aGUgZGV2ZWxvcG1lbnQgb2YgbW9kZXJuIHBoaWxvc29waHkgYW5kIHBvbGl0aWNhbCB0aG91Z2h0LlxuXG5UaHJvdWdob3V0IGl0cyBoaXN0b3J5LCBQYXJpcyBoYXMgYmVlbiBhIGNlbnRlciBvZiBlZHVjYXRpb24sIGFydHMsIGFuZCBjdWx0dXJlLCBob3N0aW5nIG51bWVyb3VzIGZhbW91cyBhcnRpc3RzLCB3cml0ZXJzLCBhbmQgdGhpbmtlcnMsIHN1Y2ggYXMgTGVvbmFyZG8gZGEgVmluY2ksIE1hcmNlbCBQcm91c3QsIFBhYmxvIFBpY2Fzc28sIGFuZCBBbGJlcnQgRWluc3RlaW4uIEl0IGlzIGEgbWFqb3IgZ2xvYmFsIGNpdHksIGEgc2lnbmlmaWNhbnQgaHViIGZvciBkaXBsb21hY3ksIGFuZCBhIHRvcCB0b3VyaXN0IGRlc3RpbmF0aW9uLCBhdHRyYWN0aW5nIG1pbGxpb25zIG9mIHZpc2l0b3JzIGVhY2ggeWVhci4iLCJ0eXBlIjoidGV4dCJ9XSwicm9sZSI6ImFzc2lzdGFudCJ9XUrjAQoTYnJhaW50cnVzdC5tZXRhZGF0YRLLAQrIAXsiZW5kcG9pbnQiOiJjb252ZXJzZSIsInByb3ZpZGVyIjoiYmVkcm9jayIsInJlcXVlc3RfcGF0aCI6Im1vZGVsL3VzLmFtYXpvbi5ub3ZhLWxpdGUtdjElM0EwL2NvbnZlcnNlIiwibW9kZWwiOiJ1cy5hbWF6b24ubm92YS1saXRlLXYxOjAiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdCIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SnAKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJXClVbeyJyb2xlIjoidXNlciIsImNvbnRlbnQiOlt7InRleHQiOiJXaGF0IGlzIHRoZSBjYXBpdGFsIG9mIEZyYW5jZT8iLCJ0eXBlIjoidGV4dCJ9XX1dSlAKEmJyYWludHJ1c3QubWV0cmljcxI6Cjh7ImNvbXBsZXRpb25fdG9rZW5zIjoyODcsInByb21wdF90b2tlbnMiOjcsInRva2VucyI6Mjk0fUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3RKLgoaYnJhaW50cnVzdC5zcGFuX2F0dHJpYnV0ZXMSEAoOeyJ0eXBlIjoibGxtIn16AIUBAQEAABKMBwoQv3JGLG4f78cbr/QPe6CcDxIIlB3LJ7sURu0iCCRTqObwxPhDKhdiZWRyb2NrLmNvbnZlcnNlLXN0cmVhbTABObK02it5TqsYQeWqLH55TqsYSv4BChZicmFpbnRydXN0Lm91dHB1dF9qc29uEuMBCuABW3sicm9sZSI6ImFzc2lzdGFudCIsImNvbnRlbnQiOlt7InRleHQiOiJTdXJlLCBJJ2xsIGNvdW50IHRvIDEwIHNsb3dseSBmb3IgeW91OlxuXG4xLi4uIFxuMi4uLlxuMy4uLlxuNC4uLlxuNS4uLlxuNi4uLlxuNy4uLlxuOC4uLlxuOS4uLlxuMTAuLi5cblxuVGhlcmUgeW91IGdvISBJZiB5b3UgbmVlZCBhbnl0aGluZyBlbHNlLCBmZWVsIGZyZWUgdG8gYXNrLiIsInR5cGUiOiJ0ZXh0In1dfV1K8QEKE2JyYWludHJ1c3QubWV0YWRhdGES2QEK1gF7ImVuZHBvaW50IjoiY29udmVyc2Utc3RyZWFtIiwicHJvdmlkZXIiOiJiZWRyb2NrIiwicmVxdWVzdF9wYXRoIjoibW9kZWwvdXMuYW1hem9uLm5vdmEtbGl0ZS12MSUzQTAvY29udmVyc2Utc3RyZWFtIiwibW9kZWwiOiJ1cy5hbWF6b24ubm92YS1saXRlLXYxOjAiLCJyZXF1ZXN0X2Jhc2VfdXJpIjoiaHR0cDovL2xvY2FsaG9zdCIsInJlcXVlc3RfbWV0aG9kIjoiUE9TVCJ9SmQKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJLCklbeyJyb2xlIjoidXNlciIsImNvbnRlbnQiOlt7InRleHQiOiJjb3VudCB0byAxMCBzbG93bHkiLCJ0eXBlIjoidGV4dCJ9XX1dSnAKEmJyYWludHJ1c3QubWV0cmljcxJaClh7ImNvbXBsZXRpb25fdG9rZW5zIjo1MiwicHJvbXB0X3Rva2VucyI6NiwidG9rZW5zIjo1OCwidGltZV90b19maXJzdF90b2tlbiI6MC4wMDk5NDU0MDJ9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAAEtoFCgUKA2J0eBKHAQoQNN66GiwEkDaQYc7Xk/j5kRIIqn/jL/qWYj4qBXRvb2xzMAE58+Auw3hOqxhB23+y+3hOqxhKEgoGY2xpZW50EggKBm9wZW5haUoyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAABKLAQoQrNKOtXt7JqCIXxy8bbv8BxIINny8Q4m05CEqCGNvbnZlcnNlMAE5qtROgXhOqxhBu6u7JnlOqxhKEwoGY2xpZW50EgkKB2JlZHJvY2tKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASiwEKEFncL3aBKWyDgZYYz0u9SUoSCNVo8Iobn9o2KglzdHJlYW1pbmcwATn6rbX7eE6rGEGQaGpSeU6rGEoSCgZjbGllbnQSCAoGb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEpUBChCJwROsc3U9Uj18QdI/bKVREgh5kPg/SZVeXCoJc3RyZWFtaW5nMAE5GhlsUnlOqxhBu4osuHlOqxhKHAoGY2xpZW50EhIKEGxhbmdjaGFpbi1vcGVuYWlKMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0egCFAQEBAAASkgEKEL9yRixuH+/HG6/0D3ugnA8SCCRTqObwxPhDKg9jb252ZXJzZV9zdHJlYW0wATlYV74meU6rGEGifxACek6rGEoTCgZjbGllbnQSCQoHYmVkcm9ja0oyChFicmFpbnRydXN0LnBhcmVudBIdChtwcm9qZWN0X25hbWU6amF2YS11bml0LXRlc3R6AIUBAQEAABLqFAoRCg9icmFpbnRydXN0LWphdmES2gYKEDTeuhosBJA2kGHO15P4+ZESCKdwX0TPRCkCIgiqf+Mv+pZiPioPQ2hhdCBDb21wbGV0aW9uMAE5+CBkyXhOqxhBmqOj+3hOqxhKvwIKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SpAIKoQJbeyJpbmRleCI6MCwibWVzc2FnZSI6eyJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6bnVsbCwidG9vbF9jYWxscyI6W3siaWQiOiJjYWxsX09maTZzWmtaREY0TU1TbWZXODV5RkljdCIsInR5cGUiOiJmdW5jdGlvbiIsImZ1bmN0aW9uIjp7Im5hbWUiOiJnZXRfd2VhdGhlciIsImFyZ3VtZW50cyI6IntcImxvY2F0aW9uXCI6XCJQYXJpcywgRnJhbmNlXCJ9In19XSwicmVmdXNhbCI6bnVsbCwiYW5ub3RhdGlvbnMiOltdfSwibG9ncHJvYnMiOm51bGwsImZpbmlzaF9yZWFzb24iOiJ0b29sX2NhbGxzIn1dSqcBChNicmFpbnRydXN0Lm1ldGFkYXRhEo8BCowBeyJwcm92aWRlciI6Im9wZW5haSIsInJlcXVlc3RfcGF0aCI6ImNoYXQvY29tcGxldGlvbnMiLCJtb2RlbCI6ImdwdC00byIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KYwoVYnJhaW50cnVzdC5pbnB1dF9qc29uEkoKSFt7ImNvbnRlbnQiOiJXaGF0IGlzIHRoZSB3ZWF0aGVyIGxpa2UgaW4gUGFyaXMsIEZyYW5jZT8iLCJyb2xlIjoidXNlciJ9XUpQChJicmFpbnRydXN0Lm1ldHJpY3MSOgo4eyJjb21wbGV0aW9uX3Rva2VucyI6MTYsInByb21wdF90b2tlbnMiOjg1LCJ0b2tlbnMiOjEwMX1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAASnQcKEFncL3aBKWyDgZYYz0u9SUoSCFVxBwosMULuIgjVaPCKG5/aNioPQ2hhdCBDb21wbGV0aW9uMAE52p04/XhOqxhBU11nUnlOqxhKrgIKFmJyYWludHJ1c3Qub3V0cHV0X2pzb24SkwIKkAJbeyJmaW5pc2hfcmVhc29uIjoic3RvcCIsImluZGV4IjowLCJsb2dwcm9icyI6bnVsbCwibWVzc2FnZSI6eyJjb250ZW50IjoiU3VyZSEgSGVyZSB3ZSBnbzpcblxuMS4uLiAgXG4yLi4uICBcbjMuLi4gIFxuNC4uLiAgXG41Li4uICBcbjYuLi4gIFxuNy4uLiAgXG44Li4uICBcbjkuLi4gIFxuMTAuLi4gIFxuXG5UYWtlIHlvdXIgdGltZSEiLCJyZWZ1c2FsIjpudWxsLCJyb2xlIjoiYXNzaXN0YW50IiwidG9vbF9jYWxscyI6W10sInZhbGlkIjp0cnVlfSwidmFsaWQiOnRydWV9XUqsAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKUAQqRAXsicHJvdmlkZXIiOiJvcGVuYWkiLCJyZXF1ZXN0X3BhdGgiOiJjaGF0L2NvbXBsZXRpb25zIiwibW9kZWwiOiJncHQtNG8tbWluaSIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KkAEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJ3CnVbeyJjb250ZW50IjoieW91IGFyZSBhIHRob3VnaHRmdWwgYXNzaXN0YW50Iiwicm9sZSI6InN5c3RlbSJ9LHsiY29udGVudCI6IkNvdW50IGZyb20gMSB0byAxMCBzbG93bHkuIiwicm9sZSI6InVzZXIifV1KcQoSYnJhaW50cnVzdC5tZXRyaWNzElsKWXsiY29tcGxldGlvbl90b2tlbnMiOjQwLCJwcm9tcHRfdG9rZW5zIjoyNSwidG9rZW5zIjo2NSwidGltZV90b19maXJzdF90b2tlbiI6MC4wMTA4MjE5Nzh9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAAEtcGChCJwROsc3U9Uj18QdI/bKVREgid1Vc2dsMl0iIIeZD4P0mVXlwqD0NoYXQgQ29tcGxldGlvbjADOfyBFlN5TqsYQSCXMrh5TqsYSugBChZicmFpbnRydXN0Lm91dHB1dF9qc29uEs0BCsoBW3siaW5kZXgiOjAsImZpbmlzaF9yZWFzb24iOiJzdG9wIiwibWVzc2FnZSI6eyJyb2xlIjoiYXNzaXN0YW50IiwiY29udGVudCI6IlN1cmUhIEhlcmUgd2UgZ286XG5cbjEuLi4gIFxuMi4uLiAgXG4zLi4uICBcbjQuLi4gIFxuNS4uLiAgXG42Li4uICBcbjcuLi4gIFxuOC4uLiAgXG45Li4uICBcbjEwLi4uICBcblxuVGhlcmUgeW91IGhhdmUgaXQhIn19XUqsAQoTYnJhaW50cnVzdC5tZXRhZGF0YRKUAQqRAXsicHJvdmlkZXIiOiJvcGVuYWkiLCJyZXF1ZXN0X3BhdGgiOiJjaGF0L2NvbXBsZXRpb25zIiwibW9kZWwiOiJncHQtNG8tbWluaSIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KkAEKFWJyYWludHJ1c3QuaW5wdXRfanNvbhJ3CnVbeyJyb2xlIjoic3lzdGVtIiwiY29udGVudCI6InlvdSBhcmUgYSB0aG91Z2h0ZnVsIGFzc2lzdGFudCJ9LHsicm9sZSI6InVzZXIiLCJjb250ZW50IjoiQ291bnQgZnJvbSAxIHRvIDEwIHNsb3dseS4ifV1KcQoSYnJhaW50cnVzdC5tZXRyaWNzElsKWXsiY29tcGxldGlvbl90b2tlbnMiOjQxLCJwcm9tcHRfdG9rZW5zIjoyNSwidG9rZW5zIjo2NiwidGltZV90b19maXJzdF90b2tlbiI6MS42ODYyMDY1MzF9SjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdEouChpicmFpbnRydXN0LnNwYW5fYXR0cmlidXRlcxIQCg57InR5cGUiOiJsbG0ifXoAhQEBAQAA" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZXjGd3oAMEB_A=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f408fc-6672bcf7223a54ac34a5c484;Parent=1bb1410113bd85e6;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 01:59:24 GMT", + "Via" : "1.1 e1832834d17ab65dd955f4e68cc524e6.cloudfront.net (CloudFront), 1.1 74e8c76139b8c7f9b11d5e4441c2a7a2.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f408fc000000005f55eb177bdacde2", + "x-amzn-RequestId" : "969805cb-28c2-4901-b3aa-a562348da4a0", + "X-Amz-Cf-Id" : "QySVXgvAVV7mVard1JArPs8VDS5T77pjTVwfHCsZePI_xMXzNTVSzg==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "eab030fd-4e00-4af8-b5a6-2759e4759e9f", + "persistent" : true, + "insertionIndex" : 240 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-fc78d31e-39cf-4add-8cb5-365ed3658189.json b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-fc78d31e-39cf-4add-8cb5-365ed3658189.json new file mode 100644 index 00000000..87dd0d9f --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/braintrust/mappings/otel_v1_traces-fc78d31e-39cf-4add-8cb5-365ed3658189.json @@ -0,0 +1,39 @@ +{ + "id" : "fc78d31e-39cf-4add-8cb5-365ed3658189", + "name" : "otel_v1_traces", + "request" : { + "url" : "/otel/v1/traces", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/x-protobuf" + } + }, + "bodyPatterns" : [ { + "binaryEqualTo" : "CsMpCrIBCiAKDHNlcnZpY2UubmFtZRIQCg5icmFpbnRydXN0LWFwcAoiCg9zZXJ2aWNlLnZlcnNpb24SDwoNMC4zLjQtZDkwZTNmOAogChZ0ZWxlbWV0cnkuc2RrLmxhbmd1YWdlEgYKBGphdmEKJQoSdGVsZW1ldHJ5LnNkay5uYW1lEg8KDW9wZW50ZWxlbWV0cnkKIQoVdGVsZW1ldHJ5LnNkay52ZXJzaW9uEggKBjEuNTkuMBKeAQoFCgNidHgSlAEKEBGA6i4xbCU7UHwxaNDtExQSCPjHQkdKx5vQKglyZWFzb25pbmcwATliYBJ/hE6rGEGQcKXvi06rGEobCgZjbGllbnQSEQoPc3ByaW5nYWktb3BlbmFpSjIKEWJyYWludHJ1c3QucGFyZW50Eh0KG3Byb2plY3RfbmFtZTpqYXZhLXVuaXQtdGVzdHoAhQEBAQAAEuomChEKD2JyYWludHJ1c3QtamF2YRLUJgoQEYDqLjFsJTtQfDFo0O0TFBIIramB9VYyWw8iCPjHQkdKx5vQKglyZXNwb25zZXMwATk27MUGiU6rGEER7Mvui06rGEryDQoWYnJhaW50cnVzdC5vdXRwdXRfanNvbhLXDQrUDVt7ImlkIjoicnNfMDU4ZjM1ZWUzNTBhOTk5YjAwNjlmNDA5M2Q1OTQ4ODE5MzljZTJiMGYwY2M1ZmE5NzMiLCJ0eXBlIjoicmVhc29uaW5nIiwic3VtbWFyeSI6W3sidHlwZSI6InN1bW1hcnlfdGV4dCIsInRleHQiOiIqKkNhbGN1bGF0aW5nIHRlcm1zIGFuZCBzdW1zKipcblxuVGhlIHVzZXIgaXMgYXNraW5nIGZvciB0aGUgMTB0aCB0ZXJtIGFuZCB0aGUgc3VtIG9mIHRoZSBmaXJzdCAxMCB0ZXJtcyBiYXNlZCBvbiB0aGUgcGF0dGVybiB3ZSBkaXNjb3ZlcmVkLiBUaGUgbnRoIHRlcm0gaXMgY2FsY3VsYXRlZCBhcyBhX24gPSBuKG4rMSksIHNvIHRoZSAxMHRoIHRlcm0gYV8xMCBjb21lcyBvdXQgdG8gYmUgMTEwLiBcblxuVG8gZmluZCB0aGUgc3VtIG9mIHRoZSBmaXJzdCAxMCB0ZXJtcywgd2UgYnJlYWsgaXQgZG93biBpbnRvIHRoZSBzdW0gb2Ygc3F1YXJlcyBhbmQgdGhlIHN1bSBvZiBuLiBUaGUgZmluYWwgY2FsY3VsYXRpb25zIHNob3cgdGhhdCB0aGUgc3VtIG9mIHRoZSBmaXJzdCAxMCB0ZXJtcyBpcyA0NDAsIHdoaWNoIGNvbWJpbmVzIHRoZSBzdW0gb2Ygc3F1YXJlcyAoMzg1KSBhbmQgdGhlIHN1bSBvZiBuICg1NSkuIn0seyJ0eXBlIjoic3VtbWFyeV90ZXh0IiwidGV4dCI6IioqUHJvdmlkaW5nIHRoZSBhbnN3ZXJzIGNsZWFybHkqKlxuXG5XZSBjYW4gcmVzcG9uZCB0byB0aGUgdXNlcidzIHF1ZXN0aW9uIGRpcmVjdGx5LiBUaGUgMTB0aCB0ZXJtLCBjYWxjdWxhdGVkIGZyb20gdGhlIGRpc2NvdmVyZWQgcGF0dGVybiwgaXMgYV8xMCA9IDEwICogMTEsIHdoaWNoIGVxdWFscyAxMTAuIFRoZSBzdW0gb2YgdGhlIGZpcnN0IDEwIHRlcm1zIGlzIDQ0MC4gXG5cblRvIHByb3ZpZGUgbW9yZSBjbGFyaXR5LCBJIGNhbiBzaG93IHRoZSBzdGVwczogXG5cbkZpcnN0LCBhXzEwID0gMTAgKiAxMSA9IDExMC4gXG5cbk5leHQsIHN1bW1pbmcgdGhlIHRlcm1zIGludm9sdmVzIGNhbGN1bGF0aW5nIM6jIG4obisxKSBmb3IgbiBmcm9tIDEgdG8gMTAsIHdoaWNoIGdpdmVzIHVzIDQ0MC4gXG5cbkkgc2hvdWxkIGFsc28gbWVudGlvbiB0aGUgZ2VuZXJhbCBzdW0gZm9ybXVsYSBmb3IgZnV0dXJlIHJlZmVyZW5jZSwgYnV0IGZvciBub3csIEknbGwgaW5jbHVkZSBib3RoIG1ldGhvZHMgY2xlYXJseSBpbiBteSByZXNwb25zZS4ifV19LHsiaWQiOiJtc2dfMDU4ZjM1ZWUzNTBhOTk5YjAwNjlmNDA5NDc2NWY0ODE5Mzg4MTI0MmQ2NGRjNDFmNGYiLCJ0eXBlIjoibWVzc2FnZSIsInN0YXR1cyI6ImNvbXBsZXRlZCIsImNvbnRlbnQiOlt7InR5cGUiOiJvdXRwdXRfdGV4dCIsImFubm90YXRpb25zIjpbXSwibG9ncHJvYnMiOltdLCJ0ZXh0IjoiVGhlIG50aCB0ZXJtIGlzIGHigpkgPSBuKG4rMSkuICBcblNvXG5cbuKAoiBUaGUgMTB0aCB0ZXJtIGlzICBcbuKAg2HigoHigoAgPSAxMMK3MTEgPSAxMTAuXG5cbuKAoiBUaGUgc3VtIG9mIHRoZSBmaXJzdCAxMCB0ZXJtcyBpcyAgXG7igINT4oKB4oKAID0g4oiR4oKZ4oKM4oKBwrnigbAgbihuKzEpICBcbuKAg+KAgz0g4oiRbsKyICsg4oiRbiAgXG7igIPigIM9ICgxMMK3MTHCtzIxKS82ICsgKDEwwrcxMSkvMiAgXG7igIPigIM9IDM4NSArIDU1ID0gNDQwLiAgXG5cbkVxdWl2YWxlbnRseSwgb25lIGNhbiB1c2UgdGhlIGNsb3NlZOKAkGZvcm0gIFxu4oCD4oiR4oKZ4oKM4oKB4bS6IG4obisxKSA9IE4oTisxKShOKzIpLzMsICBcbnNvIGZvciBOPTEwOiAxMMK3MTHCtzEyLzMgPSA0NDAuIn1dLCJyb2xlIjoiYXNzaXN0YW50In1dSqEBChNicmFpbnRydXN0Lm1ldGFkYXRhEokBCoYBeyJwcm92aWRlciI6Im9wZW5haSIsInJlcXVlc3RfcGF0aCI6InJlc3BvbnNlcyIsIm1vZGVsIjoibzQtbWluaSIsInJlcXVlc3RfYmFzZV91cmkiOiJodHRwOi8vbG9jYWxob3N0OjM5ODkzIiwicmVxdWVzdF9tZXRob2QiOiJQT1NUIn1KkBUKFWJyYWludHJ1c3QuaW5wdXRfanNvbhL2FArzFFt7InJvbGUiOiJ1c2VyIiwiY29udGVudCI6Ikxvb2sgYXQgdGhpcyBzZXF1ZW5jZTogMiwgNiwgMTIsIDIwLCAzMC4gV2hhdCBpcyB0aGUgcGF0dGVybiBhbmQgd2hhdCB3b3VsZCBiZSB0aGUgZm9ybXVsYSBmb3IgdGhlIG50aCB0ZXJtP1xuIn0seyJpZCI6InJzXzA1OGYzNWVlMzUwYTk5OWIwMDY5ZjQwOTI5YWMzODgxOTNiOTU2OGNkZjcwYjAyYjU0Iiwic3VtbWFyeSI6W3sidGV4dCI6IioqQW5hbHl6aW5nIGEgbnVtYmVyIHNlcXVlbmNlKipcblxuVGhlIHVzZXIgcHJlc2VudGVkIG1lIHdpdGggYSBzZXF1ZW5jZTogMiwgNiwgMTIsIDIwLCAzMC4gSSdtIHRyeWluZyB0byBmaW5kIHRoZSBwYXR0ZXJuIGFuZCBhIGZvcm11bGEgZm9yIHRoZSBudGggdGVybS4gSXQgbG9va3MgbGlrZSB0aGVzZSBudW1iZXJzIGNvcnJlc3BvbmQgdG8gdHJpYW5ndWxhciBudW1iZXJzIG11bHRpcGxpZWQgYnkgMi4gSW4gZmFjdCwgdGhleSBmb2xsb3cgdGhlIGZvcm11bGE6IG4obiArIDEpIHdoaWNoIHNpbXBsaWZpZXMgdG8gbl4yICsgbi4gSnVzdCB0byBjbGFyaWZ5LCB0cmlhbmd1bGFyIG51bWJlcnMgZm9sbG93IHRoZSBmb3JtdWxhIFRfbiA9IG4obiArIDEpLzIuIEJhc2VkIG9uIHRoaXMsIEkgc2VlIHRoYXQgdGhlIGdpdmVuIHNlcXVlbmNlIGlzIGVzc2VudGlhbGx5IHR3aWNlIGVhY2ggdHJpYW5ndWxhciBudW1iZXIuIiwidHlwZSI6InN1bW1hcnlfdGV4dCJ9LHsidGV4dCI6IioqQ2xhcmlmeWluZyB0aGUgc2VxdWVuY2UgcGF0dGVybioqXG5cbkknbSBicmVha2luZyBkb3duIHRoZSBzZXF1ZW5jZSAyLCA2LCAxMiwgMjAsIDMwLiBJIHNlZSBub3cgdGhhdCBpdCBlcXVhbHMgMiB0aW1lcyB0aGUgdHJpYW5ndWxhciBudW1iZXJzOiAyID0gMsOXMSwgNiA9IDLDlzMsIGV0Yy4gVGhlIGZvcm11bGEgZm9yIHRoZSBudGggdGVybSBpcyBhX24gPSBuKG4gKyAxKSwgYW5kIGl0IGNhbiBhbHNvIGJlIGRlc2NyaWJlZCBieSBvYnNlcnZpbmcgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGVybXM6IDQsIDYsIDgsIDEwLCB3aGljaCBpbmNyZWFzZSBieSAyIGVhY2ggdGltZS4gVGhpcyBjb25zaXN0ZW5jeSBpbmRpY2F0ZXMgaXQncyBhIHF1YWRyYXRpYyBzZXF1ZW5jZS4gVGhlIGZpbmFsIGNvbmNsdXNpb24gaXMgdGhhdCB0aGUgcGF0dGVybiByZXByZXNlbnRzIHJlY3Rhbmd1bGFyIG51bWJlcnMsIGNvbmZpcm1pbmcgdGhlIGZvcm11bGEgaXMgYV9uID0gbihuICsgMSkuIiwidHlwZSI6InN1bW1hcnlfdGV4dCJ9LHsidGV4dCI6IioqU29sdmluZyBmb3IgdGhlIHNlcXVlbmNlKipcblxuSeKAmW0gd29ya2luZyBvbiB0aGUgc2VxdWVuY2UgYW5kIHNldHRpbmcgdXAgZXF1YXRpb25zIGJhc2VkIG9uIHRoZSByZWxhdGlvbnNoaXBzIEkgc2VlLiBJJ3ZlIGVzdGFibGlzaGVkIHRoYXQgYiBjYW4gYmUgZXhwcmVzc2VkIGluIHRlcm1zIG9mIGEgYW5kIGRlcml2ZWQgZXF1YXRpb25zIHRoYXQgc2ltcGxpZnkgZG93biB0byBhID0gMSBhbmQgYiA9IDEsIHdpdGggYyBlcXVhbGluZyAwLiBTbywgSSd2ZSBkZXRlcm1pbmVkIHRoZSBudGggdGVybSBmb3JtdWxhIGlzIGFfbiA9IG4obiArIDEpLCB3aGljaCByZXZlYWxzIHRoZSBwYXR0ZXJuIG9mIHByb25pYyBudW1iZXJzLCBiZWluZyB0aGUgcHJvZHVjdCBvZiB0d28gY29uc2VjdXRpdmUgaW50ZWdlcnMsIHNwZWNpZmljYWxseTogMiwgNiwgMTIsIDIwLCAzMC4uLiBKdXN0IHRvIGNsYXJpZnksIHRoZSBmaW5hbCBmb3JtdWxhIHVzaW5nIGluZGV4aW5nIGZyb20gMSBpcyBhX24gPSBuKG4gKyAxKS4iLCJ0eXBlIjoic3VtbWFyeV90ZXh0In1dLCJ0eXBlIjoicmVhc29uaW5nIn0seyJpZCI6Im1zZ18wNThmMzVlZTM1MGE5OTliMDA2OWY0MDkzYWYxNTQ4MTkzOTc4M2U2MDBhNDNmNTEzMyIsImNvbnRlbnQiOlt7ImFubm90YXRpb25zIjpbXSwidGV4dCI6IlRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHN1Y2Nlc3NpdmUgdGVybXMgYXJlXG5cbiA24oCTMiA9IDQsICBcbjEy4oCTNiA9IDYsICBcbjIw4oCTMTIgPSA4LCAgXG4zMOKAkzIwID0gMTAsICBcblxuc28gdGhlIOKAnHN0ZXDigJBzaXplc+KAnSBhcmUgdGhlIGV2ZW4gbnVtYmVycyA0LDYsOCwxMCzigKYgKGkuZS4gdGhleSBpbmNyZWFzZSBieSAyIGVhY2ggdGltZSkuICBBbnkgc2VxdWVuY2Ugd2hvc2Ugc2Vjb25kIGRpZmZlcmVuY2UgaXMgY29uc3RhbnQgaXMgYSBxdWFkcmF0aWMsIGFuZCBpbiBmYWN0IG9uZSBjaGVja3MgdGhhdFxuXG4gMiA9IDHCtzIsICBcbiA2ID0gMsK3MywgIFxuMTIgPSAzwrc0LCAgXG4yMCA9IDTCtzUsICBcbjMwID0gNcK3Nixcblxuc28gdGhlIG50aCB0ZXJtIGlzIHRoZSBwcm9kdWN0IG9mIHR3byBjb25zZWN1dGl2ZSBpbnRlZ2Vycy4gIElmIHdlIHN0YXJ0IGNvdW50aW5nIGF0IG49MSwgdGhlIGZvcm11bGEgaXNcblxuICBh4oKZID0gbuKAiShuICsgMSkgPSBuwrIgKyBuLiIsInR5cGUiOiJvdXRwdXRfdGV4dCIsImxvZ3Byb2JzIjpbXX1dLCJyb2xlIjoiYXNzaXN0YW50Iiwic3RhdHVzIjoiY29tcGxldGVkIiwidHlwZSI6Im1lc3NhZ2UifSx7InJvbGUiOiJ1c2VyIiwiY29udGVudCI6IlVzaW5nIHRoZSBwYXR0ZXJuIHlvdSBkaXNjb3ZlcmVkLCB3aGF0IHdvdWxkIGJlIHRoZSAxMHRoIHRlcm0/IEFuZCBjYW4geW91IGZpbmQgdGhlIHN1bSBvZiB0aGUgZmlyc3QgMTAgdGVybXM/In1dSnUKEmJyYWludHJ1c3QubWV0cmljcxJfCl17ImNvbXBsZXRpb25fdG9rZW5zIjo4ODAsInByb21wdF90b2tlbnMiOjI1NSwidG9rZW5zIjoxMTM1LCJjb21wbGV0aW9uX3JlYXNvbmluZ190b2tlbnMiOjY0MH1KMgoRYnJhaW50cnVzdC5wYXJlbnQSHQobcHJvamVjdF9uYW1lOmphdmEtdW5pdC10ZXN0Si4KGmJyYWludHJ1c3Quc3Bhbl9hdHRyaWJ1dGVzEhAKDnsidHlwZSI6ImxsbSJ9egCFAQEBAAA=" + } ] + }, + "response" : { + "status" : 200, + "headers" : { + "X-Cache" : "Miss from cloudfront", + "x-amz-apigw-id" : "cqZkDFrmIAMENwA=", + "vary" : "Origin", + "x-amzn-Remapped-content-length" : "0", + "X-Amz-Cf-Pop" : [ "SEA900-P1", "SEA900-P10" ], + "X-Amzn-Trace-Id" : "Root=1-69f4094c-2d10cb1c1a2813ed5911d64a;Parent=0f28d3f26e4b10c4;Sampled=0;Lineage=1:24be3d11:0", + "Date" : "Fri, 01 May 2026 02:00:45 GMT", + "Via" : "1.1 724581b48d733e53834b535d2a623034.cloudfront.net (CloudFront), 1.1 fbb003dfc0617e3e058e3dac791dfd5a.cloudfront.net (CloudFront)", + "access-control-expose-headers" : "x-bt-cursor,x-bt-found-existing,x-bt-query-plan,x-bt-api-duration-ms,x-bt-brainstore-duration-ms,x-bt-internal-trace-id", + "access-control-allow-credentials" : "true", + "x-bt-internal-trace-id" : "69f4094c000000001e6a52a920029db4", + "x-amzn-RequestId" : "1ddae7a9-6b6b-4d8e-820e-e10fb98bd7b0", + "X-Amz-Cf-Id" : "S8PIcvl8lXZwXMts32FsRKL02D7tmEvYauQ89AjWc3KJRi0nceS95w==", + "etag" : "W/\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"", + "Content-Type" : "application/x-protobuf" + } + }, + "uuid" : "fc78d31e-39cf-4add-8cb5-365ed3658189", + "persistent" : true, + "insertionIndex" : 225 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/google/__files/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-562490b6-de95-4c70-b1e7-311ae3ca8db0.json b/test-harness/src/testFixtures/resources/cassettes/google/__files/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-562490b6-de95-4c70-b1e7-311ae3ca8db0.json new file mode 100644 index 00000000..ee25c6de --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/google/__files/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-562490b6-de95-4c70-b1e7-311ae3ca8db0.json @@ -0,0 +1,30 @@ +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "The capital of France is Paris.", + "thoughtSignature": "EjQKMgEMOdbHOWnN41SM6AIyb6GJ4fxbrVI14S3xjjl01Uhd5Jjl94+IhhrivCFX+0a79uTw" + } + ], + "role": "model" + }, + "finishReason": "STOP", + "index": 0 + } + ], + "usageMetadata": { + "promptTokenCount": 8, + "candidatesTokenCount": 7, + "totalTokenCount": 15, + "promptTokensDetails": [ + { + "modality": "TEXT", + "tokenCount": 8 + } + ] + }, + "modelVersion": "gemini-3.1-flash-lite-preview", + "responseId": "9Qj0afC1A_qKmtkPwbiGuAs" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/google/__files/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-96a8e8e9-7983-4368-ace6-679ea8a5e339.json b/test-harness/src/testFixtures/resources/cassettes/google/__files/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-96a8e8e9-7983-4368-ace6-679ea8a5e339.json new file mode 100644 index 00000000..2975c8b1 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/google/__files/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-96a8e8e9-7983-4368-ace6-679ea8a5e339.json @@ -0,0 +1,34 @@ +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "The color of the image is red.", + "thoughtSignature": "EjQKMgEMOdbHElahs5SDbLMfb3qlKtkg0tYhWWtCNxv6zaQemJ8bUH5awOudKCorBfaPNLYD" + } + ], + "role": "model" + }, + "finishReason": "STOP", + "index": 0 + } + ], + "usageMetadata": { + "promptTokenCount": 1096, + "candidatesTokenCount": 8, + "totalTokenCount": 1104, + "promptTokensDetails": [ + { + "modality": "IMAGE", + "tokenCount": 1089 + }, + { + "modality": "TEXT", + "tokenCount": 7 + } + ] + }, + "modelVersion": "gemini-3.1-flash-lite-preview", + "responseId": "8wj0acngK_SU6dkP_4a8sAg" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/google/mappings/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-562490b6-de95-4c70-b1e7-311ae3ca8db0.json b/test-harness/src/testFixtures/resources/cassettes/google/mappings/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-562490b6-de95-4c70-b1e7-311ae3ca8db0.json new file mode 100644 index 00000000..9b2b8684 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/google/mappings/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-562490b6-de95-4c70-b1e7-311ae3ca8db0.json @@ -0,0 +1,37 @@ +{ + "id" : "562490b6-de95-4c70-b1e7-311ae3ca8db0", + "name" : "v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent", + "request" : { + "url" : "/v1beta/models/gemini-3.1-flash-lite-preview:generateContent", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json; charset=UTF-8" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"contents\":[{\"parts\":[{\"text\":\"What is the capital of France?\"}],\"role\":\"user\"}],\"generationConfig\":{\"temperature\":0.0}}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-562490b6-de95-4c70-b1e7-311ae3ca8db0.json", + "headers" : { + "X-Frame-Options" : "SAMEORIGIN", + "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", + "Server" : "scaffolding on HTTPServer2", + "X-Content-Type-Options" : "nosniff", + "Server-Timing" : "gfet4t7; dur=1128", + "Vary" : [ "Origin", "X-Origin", "Referer" ], + "X-Gemini-Service-Tier" : "standard", + "X-XSS-Protection" : "0", + "Date" : "Fri, 01 May 2026 01:59:17 GMT", + "Content-Type" : "application/json; charset=UTF-8" + } + }, + "uuid" : "562490b6-de95-4c70-b1e7-311ae3ca8db0", + "persistent" : true, + "insertionIndex" : 7 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/google/mappings/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-96a8e8e9-7983-4368-ace6-679ea8a5e339.json b/test-harness/src/testFixtures/resources/cassettes/google/mappings/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-96a8e8e9-7983-4368-ace6-679ea8a5e339.json new file mode 100644 index 00000000..6eef7a71 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/google/mappings/v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-96a8e8e9-7983-4368-ace6-679ea8a5e339.json @@ -0,0 +1,37 @@ +{ + "id" : "96a8e8e9-7983-4368-ace6-679ea8a5e339", + "name" : "v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent", + "request" : { + "url" : "/v1beta/models/gemini-3.1-flash-lite-preview:generateContent", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json; charset=UTF-8" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"contents\":[{\"parts\":[{\"text\":\"What color is this image?\"},{\"inlineData\":{\"data\":\"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==\",\"mimeType\":\"image/png\"}}],\"role\":\"user\"}],\"generationConfig\":{\"temperature\":0.0}}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "v1beta_models_gemini-3.1-flash-lite-previewgeneratecontent-96a8e8e9-7983-4368-ace6-679ea8a5e339.json", + "headers" : { + "X-Frame-Options" : "SAMEORIGIN", + "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", + "Server" : "scaffolding on HTTPServer2", + "X-Content-Type-Options" : "nosniff", + "Server-Timing" : "gfet4t7; dur=1083", + "Vary" : [ "Origin", "X-Origin", "Referer" ], + "X-Gemini-Service-Tier" : "standard", + "X-XSS-Protection" : "0", + "Date" : "Fri, 01 May 2026 01:59:15 GMT", + "Content-Type" : "application/json; charset=UTF-8" + } + }, + "uuid" : "96a8e8e9-7983-4368-ace6-679ea8a5e339", + "persistent" : true, + "insertionIndex" : 8 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-248df310-4730-4cdf-a61e-f086ebb7a7f1.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-248df310-4730-4cdf-a61e-f086ebb7a7f1.json new file mode 100644 index 00000000..a881d530 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-248df310-4730-4cdf-a61e-f086ebb7a7f1.json @@ -0,0 +1,36 @@ +{ + "id": "chatcmpl-DaXSEbj3W29Ih5mNgQWOE1cBVWLlB", + "object": "chat.completion", + "created": 1777600778, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The capital of France is Paris.", + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 23, + "completion_tokens": 7, + "total_tokens": 30, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_c7625e91ee" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-33ce4449-9151-4981-bfc0-56957ddb31ac.txt b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-33ce4449-9151-4981-bfc0-56957ddb31ac.txt new file mode 100644 index 00000000..7f7b8168 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-33ce4449-9151-4981-bfc0-56957ddb31ac.txt @@ -0,0 +1,90 @@ +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"gP1erUAid"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"Sure"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"uWuX9PO"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"nNYfkGLmeL"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" Here"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Kek22K"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" we"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"EJxdPw2g"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"VaO7kcjV"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":":\n\n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jrcHgO"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"eJFOl6E6hn"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xMu50kvJ"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"H3Fdh8I"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"2"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"k2G3x8Wf9c"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"w1BhelJ5"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2GeXlvu"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"3"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"VszXEvnJZE"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"0kVKdbiD"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"XRGlR9i"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"4"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ldNPIABiFo"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"QC2OOiKD"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"RtDiTrv"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"5"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"iOZKzslkmz"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"0sZhPOnx"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"gRoUdNJ"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"6"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"YRKGjokros"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"lNRK8MBA"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Po4oxsF"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"7"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZRyGHnFI8e"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"o4CRcFaB"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2exQ5Ny"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"8"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zC9QQq4OBA"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tIU20ZZn"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jXPorIJ"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"9"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UHbK04Jp5I"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"SxDZfqY7"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"9uJUJKc"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"10"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"lrpjas5SB"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"nI1c6kWk"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n\n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"B2KkL"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"There"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Dr28Ih"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"uW6Bg0k"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" have"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"iubkG3"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" it"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"BFOh39W2"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"0b5q0InQs9"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"1v5SQ"} + +data: {"id":"chatcmpl-DaXRw0sbAoxPrfWaRKXbwxCpSzf61","object":"chat.completion.chunk","created":1777600760,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[],"usage":{"prompt_tokens":25,"completion_tokens":41,"total_tokens":66,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"aBlu86Em4Y"} + +data: [DONE] + diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-4ccc9540-2427-46bf-b755-41635e27c89b.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-4ccc9540-2427-46bf-b755-41635e27c89b.json new file mode 100644 index 00000000..96f45ab7 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-4ccc9540-2427-46bf-b755-41635e27c89b.json @@ -0,0 +1,46 @@ +{ + "id": "chatcmpl-DaXRqeLBKWBIddC4WxdWRWgcYfkZw", + "object": "chat.completion", + "created": 1777600754, + "model": "gpt-4o-2024-08-06", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_faUMvnGdGqNzG6Go8zQd7Vga", + "type": "function", + "function": { + "name": "get_weather", + "arguments": "{\"location\":\"Paris, France\"}" + } + } + ], + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "tool_calls" + } + ], + "usage": { + "prompt_tokens": 85, + "completion_tokens": 16, + "total_tokens": 101, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_fab7bd3a94" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-55b2dc03-8f20-4ef1-9d28-fc013869181f.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-55b2dc03-8f20-4ef1-9d28-fc013869181f.json new file mode 100644 index 00000000..1cbe475e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-55b2dc03-8f20-4ef1-9d28-fc013869181f.json @@ -0,0 +1,36 @@ +{ + "id": "chatcmpl-DaXSCbtsJXEBvGcb7Dwc99tvTZsqB", + "object": "chat.completion", + "created": 1777600776, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The image is red.", + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 8522, + "completion_tokens": 5, + "total_tokens": 8527, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_5652201947" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-95657ac6-2e20-443c-8ba7-09b79ac752b5.txt b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-95657ac6-2e20-443c-8ba7-09b79ac752b5.txt new file mode 100644 index 00000000..26db8790 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-95657ac6-2e20-443c-8ba7-09b79ac752b5.txt @@ -0,0 +1,90 @@ +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tmGLlO6IT"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"Sure"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HURoUnF"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"8WVQFa4IK2"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" Here"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"umkgHs"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" we"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GrQtJbC2"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MGvUW0CB"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":":\n\n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"x9dDkF"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"AL1OAPeD0p"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"IcDKWNiD"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HeGCz81"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"2"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zg5wpj9EjD"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"H1Kl5DJy"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"4b1JN7A"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"3"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"WXgnR2aXf0"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"B0g2B7cF"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"4IPgie5"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"4"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fmu4SweKtq"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2FfkT3Tc"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"dG9lDcb"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"5"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jo6jHLHjJV"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PJqjzmq8"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"E2gF8ko"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"6"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"JVG2Let6ou"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"v7YckcCo"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ciH0R91"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"7"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"h821k2QGZg"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"VZFrCGAB"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"aDMladd"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"8"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"c2Wp9I3TRH"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"TEbSSjCX"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Jpn54YZ"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"9"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"SgK6bgZdaa"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"kCQfAd6K"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"A9vt2Ob"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"10"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"obv5OO4U4"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"hc1Glc6K"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n\n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"bFC9Y"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"There"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"S7OSpm"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Q7VOoSj"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" have"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"99PeGl"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" it"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"7h98BEM1"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"OSg1YNhsMn"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"YilvM"} + +data: {"id":"chatcmpl-DaXRsxA4sHGIAndklndV0MAyP0ekC","object":"chat.completion.chunk","created":1777600756,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[],"usage":{"prompt_tokens":25,"completion_tokens":41,"total_tokens":66,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"o1sQEI2bUw"} + +data: [DONE] + diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-a40abba8-2ec4-42b2-a922-bace293d5f60.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-a40abba8-2ec4-42b2-a922-bace293d5f60.json new file mode 100644 index 00000000..4e8b44d0 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-a40abba8-2ec4-42b2-a922-bace293d5f60.json @@ -0,0 +1,46 @@ +{ + "id": "chatcmpl-DaXRuARewzYiKAIzAw57f05WdcgVW", + "object": "chat.completion", + "created": 1777600758, + "model": "gpt-4o-2024-08-06", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_Ofi6sZkZDF4MMSmfW85yFIct", + "type": "function", + "function": { + "name": "get_weather", + "arguments": "{\"location\":\"Paris, France\"}" + } + } + ], + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "tool_calls" + } + ], + "usage": { + "prompt_tokens": 85, + "completion_tokens": 16, + "total_tokens": 101, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_fab7bd3a94" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3.json new file mode 100644 index 00000000..281a61d9 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3.json @@ -0,0 +1,46 @@ +{ + "id": "chatcmpl-DaXRrlfbSFW8JFpEeNLo8BX7zv7Yn", + "object": "chat.completion", + "created": 1777600755, + "model": "gpt-4o-2024-08-06", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_JsahRDQEvD5mMD8IqJjJZCif", + "type": "function", + "function": { + "name": "get_weather", + "arguments": "{\"location\":\"Paris, France\"}" + } + } + ], + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "tool_calls" + } + ], + "usage": { + "prompt_tokens": 85, + "completion_tokens": 16, + "total_tokens": 101, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_99b75f7468" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-c85a7df0-c9d1-43e3-9243-6c9f08168a9a.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-c85a7df0-c9d1-43e3-9243-6c9f08168a9a.json new file mode 100644 index 00000000..5c46d585 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-c85a7df0-c9d1-43e3-9243-6c9f08168a9a.json @@ -0,0 +1,36 @@ +{ + "id": "chatcmpl-DaXSF4r0gKxHgWLYqATFCe7tFVSI4", + "object": "chat.completion", + "created": 1777600779, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The capital of France is Paris.", + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 23, + "completion_tokens": 7, + "total_tokens": 30, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_c7625e91ee" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-d9ab1761-3428-4e23-9ca4-8bc3d8d909e8.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-d9ab1761-3428-4e23-9ca4-8bc3d8d909e8.json new file mode 100644 index 00000000..6a116847 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-d9ab1761-3428-4e23-9ca4-8bc3d8d909e8.json @@ -0,0 +1,36 @@ +{ + "id": "chatcmpl-DaXSEyllDJHDXqQzusREvb0PJuxrY", + "object": "chat.completion", + "created": 1777600778, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The image is a solid shade of red.", + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 8522, + "completion_tokens": 9, + "total_tokens": 8531, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_5652201947" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-ed6872f2-4f70-495b-b6a0-c16db1f524a7.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-ed6872f2-4f70-495b-b6a0-c16db1f524a7.json new file mode 100644 index 00000000..f7f7e17c --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-ed6872f2-4f70-495b-b6a0-c16db1f524a7.json @@ -0,0 +1,36 @@ +{ + "id": "chatcmpl-DaXSBpVxqepUEaVNtJQYfrqO072yg", + "object": "chat.completion", + "created": 1777600775, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The image is red.", + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 8522, + "completion_tokens": 5, + "total_tokens": 8527, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_ed279b101f" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-f0745444-cdb9-4620-80fe-c3536a7e644b.txt b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-f0745444-cdb9-4620-80fe-c3536a7e644b.txt new file mode 100644 index 00000000..7f7dfc2f --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-f0745444-cdb9-4620-80fe-c3536a7e644b.txt @@ -0,0 +1,88 @@ +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oM48GqD8h"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"Sure"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wYAaD3Q"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"nfEr1PDYiM"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" Here"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"sKJzP1"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" we"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"XaN3GAxH"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Asu7hjNn"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":":\n\n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fB5cJJ"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UpbVKHddtH"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"mNm0xxEU"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"EeWvAFA"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"2"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"pUVwgkLXFz"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Mtwv7AEG"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"7VSFRZl"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"3"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vsDuumUvtX"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"alSLgLtn"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"de8j2g3"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"4"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZQN3LgNmXP"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"LkOQRSCr"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Fli5T99"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"5"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"kJSbxafpbm"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"y90xN9jd"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"upbYKYc"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"6"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"QvGhiWzznn"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"FaDCiehe"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"sfMvTGd"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"7"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"aAfYRMSaU4"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wrIK1FGu"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"d4koH7f"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"8"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"cKHqdkwVwy"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vAEaACdX"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"qJwKaW2"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"9"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"0a2VrjNM3Y"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oBDuiDTU"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ON3vgOl"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"10"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"yZmPkixlo"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"..."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wB2w7wC4"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" \n\n"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"mlwdy"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"Take"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"auOerdH"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" your"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"DzAMxq"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":" time"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ysFcAy"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vgZasQHOUY"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"48meq"} + +data: {"id":"chatcmpl-DaXRvzcC4mVupCTcAPqerO08qmo3b","object":"chat.completion.chunk","created":1777600759,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_0628d073e2","choices":[],"usage":{"prompt_tokens":25,"completion_tokens":40,"total_tokens":65,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"qiZ3oxVN8a"} + +data: [DONE] + diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-f72c5404-04da-4a59-9543-59097541dc1e.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-f72c5404-04da-4a59-9543-59097541dc1e.json new file mode 100644 index 00000000..e3452f28 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/chat_completions-f72c5404-04da-4a59-9543-59097541dc1e.json @@ -0,0 +1,36 @@ +{ + "id": "chatcmpl-DaXRri5e4MVTmCjTpebBLaSUHYwVU", + "object": "chat.completion", + "created": 1777600755, + "model": "gpt-4o-mini-2024-07-18", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The capital of France is Paris.", + "refusal": null, + "annotations": [] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 23, + "completion_tokens": 7, + "total_tokens": 30, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "service_tier": "default", + "system_fingerprint": "fp_c7625e91ee" +} diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3.json new file mode 100644 index 00000000..b52a34c7 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3.json @@ -0,0 +1,86 @@ +{ + "id": "resp_0ba4648fbb2a32ab0069f4091f333c81958ac57858573caf13", + "object": "response", + "created_at": 1777600799, + "status": "completed", + "background": false, + "billing": { + "payer": "developer" + }, + "completed_at": 1777600808, + "error": null, + "frequency_penalty": 0.0, + "incomplete_details": null, + "instructions": null, + "max_output_tokens": null, + "max_tool_calls": null, + "model": "o4-mini-2025-04-16", + "moderation": null, + "output": [ + { + "id": "rs_0ba4648fbb2a32ab0069f4091f9f188195a624ad60550d7b6e", + "type": "reasoning", + "summary": [ + { + "type": "summary_text", + "text": "**Calculating sequence terms and sums**\n\nThe user is asking for the 10th term and the sum of the first 10 terms of the sequence defined as a_n = n(n+1). I find that the 10th term is 110. For the sum of the first 10 terms, I calculate it as S = sum of n^2 + sum of n, which gives me 440. So, the 10th term is 110, and the sum of the first 10 terms is 440." + }, + { + "type": "summary_text", + "text": "**Calculating the 10th term and sum of terms**\n\nI\u2019m providing the 10th term and the sum of the first 10 terms of the sequence defined as a_n = n(n+1). The 10th term is a_10 = 10 \u00d7 11 = 110. For the sum of the first 10 terms, I calculate it as S = \u2211n(n+1) = 440, using either the direct sums (385 + 55) or the closed form formula. So the answers are: the 10th term is 110 and the sum of the first 10 terms is 440." + } + ] + }, + { + "id": "msg_0ba4648fbb2a32ab0069f40927cd7881958c2700550d4a1619", + "type": "message", + "status": "completed", + "content": [ + { + "type": "output_text", + "annotations": [], + "logprobs": [], + "text": "The 10th term is \n a\u2081\u2080 = 10\u00b7(10+1) = 10\u00b711 = 110. \n\nThe sum of the first 10 terms is \n S\u2081\u2080 = \u2211\u2099\u208c\u2081\u00b9\u2070 n(n+1) = \u2211\u2099\u208c\u2081\u00b9\u2070 n\u00b2 + \u2211\u2099\u208c\u2081\u00b9\u2070 n \n = (10\u00b711\u00b721)/6 + (10\u00b711)/2 \n = 385 + 55 \n = 440. \n\nEquivalently, one can use the closed\u2010form \n S\u2099 = n(n+1)(n+2)/3 \nso \n S\u2081\u2080 = 10\u00b711\u00b712/3 = 440." + } + ], + "role": "assistant" + } + ], + "parallel_tool_calls": true, + "presence_penalty": 0.0, + "previous_response_id": null, + "prompt_cache_key": null, + "prompt_cache_retention": "in_memory", + "reasoning": { + "effort": "high", + "summary": "detailed" + }, + "safety_identifier": null, + "service_tier": "default", + "store": true, + "temperature": 1.0, + "text": { + "format": { + "type": "text" + }, + "verbosity": "medium" + }, + "tool_choice": "auto", + "tools": [], + "top_logprobs": 0, + "top_p": 1.0, + "truncation": "disabled", + "usage": { + "input_tokens": 168, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 951, + "output_tokens_details": { + "reasoning_tokens": 768 + }, + "total_tokens": 1119 + }, + "user": null, + "metadata": {} +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-47aabefa-78d5-429e-b491-ccada4c9be78.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-47aabefa-78d5-429e-b491-ccada4c9be78.json new file mode 100644 index 00000000..68dd1851 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-47aabefa-78d5-429e-b491-ccada4c9be78.json @@ -0,0 +1,86 @@ +{ + "id": "resp_058f35ee350a999b0069f4093c42c08193a9ddb3c93e0c22bd", + "object": "response", + "created_at": 1777600828, + "status": "completed", + "background": false, + "billing": { + "payer": "developer" + }, + "completed_at": 1777600840, + "error": null, + "frequency_penalty": 0.0, + "incomplete_details": null, + "instructions": null, + "max_output_tokens": null, + "max_tool_calls": null, + "model": "o4-mini-2025-04-16", + "moderation": null, + "output": [ + { + "id": "rs_058f35ee350a999b0069f4093d594881939ce2b0f0cc5fa973", + "type": "reasoning", + "summary": [ + { + "type": "summary_text", + "text": "**Calculating terms and sums**\n\nThe user is asking for the 10th term and the sum of the first 10 terms based on the pattern we discovered. The nth term is calculated as a_n = n(n+1), so the 10th term a_10 comes out to be 110. \n\nTo find the sum of the first 10 terms, we break it down into the sum of squares and the sum of n. The final calculations show that the sum of the first 10 terms is 440, which combines the sum of squares (385) and the sum of n (55)." + }, + { + "type": "summary_text", + "text": "**Providing the answers clearly**\n\nWe can respond to the user's question directly. The 10th term, calculated from the discovered pattern, is a_10 = 10 * 11, which equals 110. The sum of the first 10 terms is 440. \n\nTo provide more clarity, I can show the steps: \n\nFirst, a_10 = 10 * 11 = 110. \n\nNext, summing the terms involves calculating \u03a3 n(n+1) for n from 1 to 10, which gives us 440. \n\nI should also mention the general sum formula for future reference, but for now, I'll include both methods clearly in my response." + } + ] + }, + { + "id": "msg_058f35ee350a999b0069f4094765f48193881242d64dc41f4f", + "type": "message", + "status": "completed", + "content": [ + { + "type": "output_text", + "annotations": [], + "logprobs": [], + "text": "The nth term is a\u2099 = n(n+1). \nSo\n\n\u2022 The 10th term is \n\u2003a\u2081\u2080 = 10\u00b711 = 110.\n\n\u2022 The sum of the first 10 terms is \n\u2003S\u2081\u2080 = \u2211\u2099\u208c\u2081\u00b9\u2070 n(n+1) \n\u2003\u2003= \u2211n\u00b2 + \u2211n \n\u2003\u2003= (10\u00b711\u00b721)/6 + (10\u00b711)/2 \n\u2003\u2003= 385 + 55 = 440. \n\nEquivalently, one can use the closed\u2010form \n\u2003\u2211\u2099\u208c\u2081\u1d3a n(n+1) = N(N+1)(N+2)/3, \nso for N=10: 10\u00b711\u00b712/3 = 440." + } + ], + "role": "assistant" + } + ], + "parallel_tool_calls": true, + "presence_penalty": 0.0, + "previous_response_id": null, + "prompt_cache_key": null, + "prompt_cache_retention": "in_memory", + "reasoning": { + "effort": "high", + "summary": "detailed" + }, + "safety_identifier": null, + "service_tier": "default", + "store": true, + "temperature": 1.0, + "text": { + "format": { + "type": "text" + }, + "verbosity": "medium" + }, + "tool_choice": "auto", + "tools": [], + "top_logprobs": 0, + "top_p": 1.0, + "truncation": "disabled", + "usage": { + "input_tokens": 255, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 880, + "output_tokens_details": { + "reasoning_tokens": 640 + }, + "total_tokens": 1135 + }, + "user": null, + "metadata": {} +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-5b5fd25b-ebbc-486f-a908-37f1d23c8917.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-5b5fd25b-ebbc-486f-a908-37f1d23c8917.json new file mode 100644 index 00000000..dc378def --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-5b5fd25b-ebbc-486f-a908-37f1d23c8917.json @@ -0,0 +1,86 @@ +{ + "id": "resp_02227da51c3fd2580069f409061d248196be47ff3eda056fc9", + "object": "response", + "created_at": 1777600774, + "status": "completed", + "background": false, + "billing": { + "payer": "developer" + }, + "completed_at": 1777600789, + "error": null, + "frequency_penalty": 0.0, + "incomplete_details": null, + "instructions": null, + "max_output_tokens": null, + "max_tool_calls": null, + "model": "o4-mini-2025-04-16", + "moderation": null, + "output": [ + { + "id": "rs_02227da51c3fd2580069f4090796e88196977cb3ecce9d9545", + "type": "reasoning", + "summary": [ + { + "type": "summary_text", + "text": "**Calculating the 10th term and the sum**\n\nThe user wants to know the 10th term of the sequence and the sum of the first 10 terms. From our earlier work, we've figured out that the 10th term is a_{10} = 10 * 11 = 110. \n\nFor the sum of the first 10 terms, we can calculate it directly, finding that the result is 440. Alternatively, we discovered a neat formula for the sum of the first n terms, which also gives 440 when n=10. So, the final answers are: 10th term = 110 and sum of first 10 terms = 440." + }, + { + "type": "summary_text", + "text": "**Deriving the 10th term and sum**\n\nLet's show the derivation clearly. The formula for the nth term is a_n = n(n+1). So, for the 10th term, we calculate a_{10} = 10 * 11 = 110. \n\nFor the sum S_10 of the first 10 terms, we have S_10 = \u2211n(n+1), which breaks down into \u2211n^2 + \u2211n = 385 + 55 = 440. Also, I can provide the general formula for the sum: \u2211_{k=1}^n k(k+1) = n(n+1)(n+2)/3. For n=10, we find 10*11*12/3 = 440. So the answers are: 10th term = 110, sum of first 10 = 440." + } + ] + }, + { + "id": "msg_02227da51c3fd2580069f40914c23c8196978bc528f6c80fdc", + "type": "message", + "status": "completed", + "content": [ + { + "type": "output_text", + "annotations": [], + "logprobs": [], + "text": "The nth term is \n a\u2099 = n(n + 1). \n\nSo for n = 10: \n a\u2081\u2080 = 10\u00b711 = 110. \n\nThe sum of the first 10 terms is \n S\u2081\u2080 = \u2211\u2096\u208c\u2081\u00b9\u2070 k(k + 1) \n = \u2211\u2096\u208c\u2081\u00b9\u2070 (k\u00b2 + k) \n = (\u2211\u2096\u208c\u2081\u00b9\u2070 k\u00b2) + (\u2211\u2096\u208c\u2081\u00b9\u2070 k) \n = [10\u00b711\u00b721/6] + [10\u00b711/2] \n = 385 + 55 \n = 440. \n\nEquivalently, one can use the closed\u2010form \n \u2211\u2096\u208c\u2081\u207f k(k + 1) = n(n + 1)(n + 2)/3 \nso for n=10: 10\u00b711\u00b712/3 = 440." + } + ], + "role": "assistant" + } + ], + "parallel_tool_calls": true, + "presence_penalty": 0.0, + "previous_response_id": null, + "prompt_cache_key": null, + "prompt_cache_retention": "in_memory", + "reasoning": { + "effort": "high", + "summary": "detailed" + }, + "safety_identifier": null, + "service_tier": "default", + "store": true, + "temperature": 1.0, + "text": { + "format": { + "type": "text" + }, + "verbosity": "medium" + }, + "tool_choice": "auto", + "tools": [], + "top_logprobs": 0, + "top_p": 1.0, + "truncation": "disabled", + "usage": { + "input_tokens": 258, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 696, + "output_tokens_details": { + "reasoning_tokens": 448 + }, + "total_tokens": 954 + }, + "user": null, + "metadata": {} +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-9e7ab055-cd83-45cb-b979-cea9c4d5c331.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-9e7ab055-cd83-45cb-b979-cea9c4d5c331.json new file mode 100644 index 00000000..98877425 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-9e7ab055-cd83-45cb-b979-cea9c4d5c331.json @@ -0,0 +1,90 @@ +{ + "id": "resp_02227da51c3fd2580069f408f499188196bd24c55057797396", + "object": "response", + "created_at": 1777600756, + "status": "completed", + "background": false, + "billing": { + "payer": "developer" + }, + "completed_at": 1777600773, + "error": null, + "frequency_penalty": 0.0, + "incomplete_details": null, + "instructions": null, + "max_output_tokens": null, + "max_tool_calls": null, + "model": "o4-mini-2025-04-16", + "moderation": null, + "output": [ + { + "id": "rs_02227da51c3fd2580069f408f556408196b2db61e732ad86a6", + "type": "reasoning", + "summary": [ + { + "type": "summary_text", + "text": "**Analyzing a number sequence**\n\nThe user provided the sequence: 2, 6, 12, 20, 30, and I'm trying to find the pattern and formula for the nth term. I notice this sequence seems to be twice the triangular numbers, which are generated by the formula n(n+1)/2. When I apply that, I see that each term corresponds to the triangular number multiplied by 2. Additionally, the differences suggest it's a quadratic sequence, confirming the numbers are pronic numbers, products of consecutive integers." + }, + { + "type": "summary_text", + "text": "**Finding the term formula**\n\nThe formula for the sequence is a_n = n(n + 1). When starting from n=1, I see it gives the first term, 2. The differences between terms increase by 2 each time, confirming they are pronic numbers. By breaking it down further, I realize these can also be expressed as twice the triangular numbers. The difference sequence is 4, 6, 8, 10, showing it's quadratic. Ultimately, I conclude: a_n = n(n + 1) for the sequence 2, 6, 12, 20, 30." + }, + { + "type": "summary_text", + "text": "**Summarizing the sequence pattern**\n\nThe pattern in this sequence is found in the successive differences, which are even numbers: 4, 6, 8, 10. This leads to the conclusion that a_n = n^2 + n, or more simply, a_n = n(n + 1). Although there's a consideration for starting at n=0, it typically begins at n=1. I can also express it as twice the triangular numbers: a_n = 2T_n. Ultimately, the answer is a_n = n(n + 1) for the terms 2, 6, 12, and so on." + } + ] + }, + { + "id": "msg_02227da51c3fd2580069f40902d7ec81968d11d9124bb4043e", + "type": "message", + "status": "completed", + "content": [ + { + "type": "output_text", + "annotations": [], + "logprobs": [], + "text": "The \u201cgaps\u201d between terms are \n 6\u22122=4, 12\u22126=6, 20\u221212=8, 30\u221220=10, \u2026 \ni.e. the differences are 4,\u20096,\u20098,\u200910, \u2026 so the second difference is constant (2) and the sequence is quadratic. Solving or noting that it\u2019s twice the triangular numbers gives\n\n a\u2099 = 2\u00b7(n(n+1)/2) = n(n+1).\n\nIf you start counting at n=1 this indeed yields \n a\u2081 = 1\u00b72 = 2, \n a\u2082 = 2\u00b73 = 6, \n a\u2083 = 3\u00b74 = 12, \u2026 \n\nSo the nth term is a\u2099 = n(n+1)." + } + ], + "role": "assistant" + } + ], + "parallel_tool_calls": true, + "presence_penalty": 0.0, + "previous_response_id": null, + "prompt_cache_key": null, + "prompt_cache_retention": "in_memory", + "reasoning": { + "effort": "high", + "summary": "detailed" + }, + "safety_identifier": null, + "service_tier": "default", + "store": true, + "temperature": 1.0, + "text": { + "format": { + "type": "text" + }, + "verbosity": "medium" + }, + "tool_choice": "auto", + "tools": [], + "top_logprobs": 0, + "top_p": 1.0, + "truncation": "disabled", + "usage": { + "input_tokens": 41, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 1326, + "output_tokens_details": { + "reasoning_tokens": 1088 + }, + "total_tokens": 1367 + }, + "user": null, + "metadata": {} +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-a2325d24-d1b8-41b7-9544-cbc25a013b0a.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-a2325d24-d1b8-41b7-9544-cbc25a013b0a.json new file mode 100644 index 00000000..2a2a61ce --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-a2325d24-d1b8-41b7-9544-cbc25a013b0a.json @@ -0,0 +1,90 @@ +{ + "id": "resp_0ba4648fbb2a32ab0069f408fa8738819588ce34f432e86369", + "object": "response", + "created_at": 1777600762, + "status": "completed", + "background": false, + "billing": { + "payer": "developer" + }, + "completed_at": 1777600798, + "error": null, + "frequency_penalty": 0.0, + "incomplete_details": null, + "instructions": null, + "max_output_tokens": null, + "max_tool_calls": null, + "model": "o4-mini-2025-04-16", + "moderation": null, + "output": [ + { + "id": "rs_0ba4648fbb2a32ab0069f408fb07e48195a99c6346663bc45a", + "type": "reasoning", + "summary": [ + { + "type": "summary_text", + "text": "**Analyzing the sequence**\n\nThe user presents the sequence: 2, 6, 12, 20, 30, which corresponds to pronic or oblong numbers expressed as n(n+1). For example, 1*2=2, 2*3=6, 3*4=12, and so forth. The formula for the nth term is a(n) = n(n+1). I notice that the differences between consecutive terms (4, 6, 8, 10) are even numbers starting at 4, indicating a consistent increase. If n starts at 0, then a(n) = n(n+1), which results in 0 at n=0." + }, + { + "type": "summary_text", + "text": "**Exploring the pattern of the sequence**\n\nStarting with n=1, the pattern mirrors n\u00b2+n, leading to the formula a(n) = n(n+1) for pronic numbers. The differences between terms (4, 6, 8, 10...) form an arithmetic sequence, increasing by 2 each time. So, I can clearly state that the nth term is the product of consecutive integers, with a simple alternative expression. When indexed from zero, the formula shifts. Ultimately, what stands out is that each term follows the relationship a_n = n(n+1)." + }, + { + "type": "summary_text", + "text": "**Defining the sequence pattern**\n\nThe sequence represents pronic numbers, where each term, starting from n=1, follows the formula a_n = n(n+1). These numbers are the products of consecutive integers: 2 as 1\u00d72, 6 as 2\u00d73, and 12 as 3\u00d74. If I used a zero-based index, I'd say a_n = n(n+1) produces a_0=0, but since the sequence starts at n=1, the first term is 2. So, the final conclusion is that pronic numbers are defined by a_n = n(n+1)." + } + ] + }, + { + "id": "msg_0ba4648fbb2a32ab0069f40919cc608195b0fb875d88fdd280", + "type": "message", + "status": "completed", + "content": [ + { + "type": "output_text", + "annotations": [], + "logprobs": [], + "text": "Each term is the product of two consecutive integers:\n\n2 = 1\u00d72 \n6 = 2\u00d73 \n12 = 3\u00d74 \n20 = 4\u00d75 \n30 = 5\u00d76 \n\nSo if you label the terms a\u2081, a\u2082, a\u2083, \u2026 then\n\n\u2003a\u2099 = n\u2009(n+1).\n\nEquivalently, a\u2099 = n\u00b2 + n." + } + ], + "role": "assistant" + } + ], + "parallel_tool_calls": true, + "presence_penalty": 0.0, + "previous_response_id": null, + "prompt_cache_key": null, + "prompt_cache_retention": "in_memory", + "reasoning": { + "effort": "high", + "summary": "detailed" + }, + "safety_identifier": null, + "service_tier": "default", + "store": true, + "temperature": 1.0, + "text": { + "format": { + "type": "text" + }, + "verbosity": "medium" + }, + "tool_choice": "auto", + "tools": [], + "top_logprobs": 0, + "top_p": 1.0, + "truncation": "disabled", + "usage": { + "input_tokens": 41, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 1286, + "output_tokens_details": { + "reasoning_tokens": 1152 + }, + "total_tokens": 1327 + }, + "user": null, + "metadata": {} +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-d9ea4fac-3e76-4c11-aec7-e15f21bb5f52.json b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-d9ea4fac-3e76-4c11-aec7-e15f21bb5f52.json new file mode 100644 index 00000000..8fd4a30b --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/__files/responses-d9ea4fac-3e76-4c11-aec7-e15f21bb5f52.json @@ -0,0 +1,90 @@ +{ + "id": "resp_058f35ee350a999b0069f40928e1f48193a35c041634394a6f", + "object": "response", + "created_at": 1777600809, + "status": "completed", + "background": false, + "billing": { + "payer": "developer" + }, + "completed_at": 1777600827, + "error": null, + "frequency_penalty": 0.0, + "incomplete_details": null, + "instructions": null, + "max_output_tokens": null, + "max_tool_calls": null, + "model": "o4-mini-2025-04-16", + "moderation": null, + "output": [ + { + "id": "rs_058f35ee350a999b0069f40929ac388193b9568cdf70b02b54", + "type": "reasoning", + "summary": [ + { + "type": "summary_text", + "text": "**Analyzing a number sequence**\n\nThe user presented me with a sequence: 2, 6, 12, 20, 30. I'm trying to find the pattern and a formula for the nth term. It looks like these numbers correspond to triangular numbers multiplied by 2. In fact, they follow the formula: n(n + 1) which simplifies to n^2 + n. Just to clarify, triangular numbers follow the formula T_n = n(n + 1)/2. Based on this, I see that the given sequence is essentially twice each triangular number." + }, + { + "type": "summary_text", + "text": "**Clarifying the sequence pattern**\n\nI'm breaking down the sequence 2, 6, 12, 20, 30. I see now that it equals 2 times the triangular numbers: 2 = 2\u00d71, 6 = 2\u00d73, etc. The formula for the nth term is a_n = n(n + 1), and it can also be described by observing the differences between terms: 4, 6, 8, 10, which increase by 2 each time. This consistency indicates it's a quadratic sequence. The final conclusion is that the pattern represents rectangular numbers, confirming the formula is a_n = n(n + 1)." + }, + { + "type": "summary_text", + "text": "**Solving for the sequence**\n\nI\u2019m working on the sequence and setting up equations based on the relationships I see. I've established that b can be expressed in terms of a and derived equations that simplify down to a = 1 and b = 1, with c equaling 0. So, I've determined the nth term formula is a_n = n(n + 1), which reveals the pattern of pronic numbers, being the product of two consecutive integers, specifically: 2, 6, 12, 20, 30... Just to clarify, the final formula using indexing from 1 is a_n = n(n + 1)." + } + ] + }, + { + "id": "msg_058f35ee350a999b0069f4093af15481939783e600a43f5133", + "type": "message", + "status": "completed", + "content": [ + { + "type": "output_text", + "annotations": [], + "logprobs": [], + "text": "The differences between successive terms are\n\n 6\u20132 = 4, \n12\u20136 = 6, \n20\u201312 = 8, \n30\u201320 = 10, \n\nso the \u201cstep\u2010sizes\u201d are the even numbers 4,6,8,10,\u2026 (i.e. they increase by 2 each time). Any sequence whose second difference is constant is a quadratic, and in fact one checks that\n\n 2 = 1\u00b72, \n 6 = 2\u00b73, \n12 = 3\u00b74, \n20 = 4\u00b75, \n30 = 5\u00b76,\n\nso the nth term is the product of two consecutive integers. If we start counting at n=1, the formula is\n\n a\u2099 = n\u2009(n + 1) = n\u00b2 + n." + } + ], + "role": "assistant" + } + ], + "parallel_tool_calls": true, + "presence_penalty": 0.0, + "previous_response_id": null, + "prompt_cache_key": null, + "prompt_cache_retention": "in_memory", + "reasoning": { + "effort": "high", + "summary": "detailed" + }, + "safety_identifier": null, + "service_tier": "default", + "store": true, + "temperature": 1.0, + "text": { + "format": { + "type": "text" + }, + "verbosity": "medium" + }, + "tool_choice": "auto", + "tools": [], + "top_logprobs": 0, + "top_p": 1.0, + "truncation": "disabled", + "usage": { + "input_tokens": 41, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 1611, + "output_tokens_details": { + "reasoning_tokens": 1408 + }, + "total_tokens": 1652 + }, + "user": null, + "metadata": {} +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-248df310-4730-4cdf-a61e-f086ebb7a7f1.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-248df310-4730-4cdf-a61e-f086ebb7a7f1.json new file mode 100644 index 00000000..373b79e6 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-248df310-4730-4cdf-a61e-f086ebb7a7f1.json @@ -0,0 +1,49 @@ +{ + "id" : "248df310-4730-4cdf-a61e-f086ebb7a7f1", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"content\":\"you are a helpful assistant\",\"role\":\"system\"},{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"gpt-4o-mini\",\"temperature\":0.0,\"stream\":false}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-248df310-4730-4cdf-a61e-f086ebb7a7f1.json", + "headers" : { + "x-request-id" : "req_a2d1b449245f445f84b6771a97732b2f", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b302249385b4d-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999980", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:39 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=seVc4DIQO9tIm36okUnPP0bk.k5uieb524ASaGve.Yo-1777600778.6072915-1.0.1.1-zhn.mfa6FU4w2WK5uUkQe0CpoKlMLxvk40hAiTz1CHa1PdyKYasTWS_jK1EGKXvKRgN8_i6aE7OcKOYjiafT8QehLq_5hn3amZwVpzNbdN4CBS91uCGyJyCdjBBAN2PS; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:39 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "442", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "248df310-4730-4cdf-a61e-f086ebb7a7f1", + "persistent" : true, + "insertionIndex" : 37 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-33ce4449-9151-4981-bfc0-56957ddb31ac.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-33ce4449-9151-4981-bfc0-56957ddb31ac.json new file mode 100644 index 00000000..ba03711a --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-33ce4449-9151-4981-bfc0-56957ddb31ac.json @@ -0,0 +1,49 @@ +{ + "id" : "33ce4449-9151-4981-bfc0-56957ddb31ac", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\n \"model\" : \"gpt-4o-mini\",\n \"messages\" : [ {\n \"role\" : \"system\",\n \"content\" : \"you are a thoughtful assistant\"\n }, {\n \"role\" : \"user\",\n \"content\" : \"Count from 1 to 10 slowly.\"\n } ],\n \"temperature\" : 0.0,\n \"stream\" : true,\n \"stream_options\" : {\n \"include_usage\" : true\n },\n \"max_tokens\" : 800\n}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-33ce4449-9151-4981-bfc0-56957ddb31ac.txt", + "headers" : { + "x-request-id" : "req_1a7460720de24c13bbd38c78d97ddc4b", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2fb2acb8681a-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999982", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:21 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=N4hMfj26ZxL1xSbSM_i0ysPFPJij_gtBP17Judogi_A-1777600760.742154-1.0.1.1-mdSzBTdPv9E08JsfgvId7VtsPmWIMYrABwWRT8i7kq8q5zG6ddohMIb6sZaXX0S85xu3ZKpTwR5ro9Rx_gYGc5d_a6_PVLexkJyQDMmgmXVV3vsW6Cws0biRAY2Kk9ue; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:21 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "155", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "text/event-stream; charset=utf-8" + } + }, + "uuid" : "33ce4449-9151-4981-bfc0-56957ddb31ac", + "persistent" : true, + "insertionIndex" : 42 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-4ccc9540-2427-46bf-b755-41635e27c89b.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-4ccc9540-2427-46bf-b755-41635e27c89b.json new file mode 100644 index 00000000..2da30c78 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-4ccc9540-2427-46bf-b755-41635e27c89b.json @@ -0,0 +1,49 @@ +{ + "id" : "4ccc9540-2427-46bf-b755-41635e27c89b", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\n \"model\" : \"gpt-4o\",\n \"messages\" : [ {\n \"role\" : \"user\",\n \"content\" : \"What is the weather like in Paris, France?\"\n } ],\n \"temperature\" : 0.0,\n \"stream\" : false,\n \"max_tokens\" : 500,\n \"tools\" : [ {\n \"type\" : \"function\",\n \"function\" : {\n \"name\" : \"get_weather\",\n \"description\" : \"Get the current weather for a location\",\n \"parameters\" : {\n \"type\" : \"object\",\n \"properties\" : {\n \"location\" : {\n \"type\" : \"string\",\n \"description\" : \"The city and state, e.g. San Francisco, CA\"\n },\n \"unit\" : {\n \"type\" : \"string\",\n \"enum\" : [ \"celsius\", \"fahrenheit\" ],\n \"description\" : \"The unit of temperature\"\n }\n },\n \"required\" : [ \"location\" ]\n }\n }\n } ]\n}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-4ccc9540-2427-46bf-b755-41635e27c89b.json", + "headers" : { + "x-request-id" : "req_de9cd81774a440e598ab60753d03fea8", + "x-ratelimit-limit-tokens" : "30000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2f8cdb5dc366-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "6ms", + "x-ratelimit-remaining-tokens" : "29999987", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "9999", + "Date" : "Fri, 01 May 2026 01:59:15 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=maQWkpZEzbAPossnjrD1UMp3YV9nPMqyBSmnUNKc0Jk-1777600754.6980221-1.0.1.1-EdYGzywm2PMWWlpTKvjcKzvZEFknQVdqJwEUvFicuCJ9rqNY2nAqG.K2Cm7xr45j9pm_VDgwqA_TUVIoFd8Pzisosqc8NGHvAdP64Y9.g9tCt9xPzNm6SdWImapAqbTv; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:15 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "10000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "538", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "4ccc9540-2427-46bf-b755-41635e27c89b", + "persistent" : true, + "insertionIndex" : 48 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-55b2dc03-8f20-4ef1-9d28-fc013869181f.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-55b2dc03-8f20-4ef1-9d28-fc013869181f.json new file mode 100644 index 00000000..4c1678f1 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-55b2dc03-8f20-4ef1-9d28-fc013869181f.json @@ -0,0 +1,52 @@ +{ + "id" : "55b2dc03-8f20-4ef1-9d28-fc013869181f", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"content\":\"you are a helpful assistant\",\"role\":\"system\"},{\"content\":[{\"type\":\"text\",\"text\":\"What color is this image?\"},{\"type\":\"image_url\",\"image_url\":{\"url\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==\"}}],\"role\":\"user\"}],\"model\":\"gpt-4o-mini\",\"stream\":false,\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-55b2dc03-8f20-4ef1-9d28-fc013869181f.json", + "headers" : { + "Server" : "cloudflare", + "x-ratelimit-reset-input-images" : "1ms", + "x-ratelimit-reset-tokens" : "0s", + "x-ratelimit-limit-input-images" : "50000", + "set-cookie" : "__cf_bm=NuIi5lIbnUqRuwQak7UbETJV627YXbiGglW9Y.KnylI-1777600776.259083-1.0.1.1-PzcywoooTfwPqmoSOSGTZGxYe6lcMJahDD1JfhyVpzECoJXfmL59wM8ws.JxIigFut3vkK8HVqL7vB2B8EhwFEQPpgIfWex3pTqSHuE5NFImq4vruwmnshKNp5ZEOF5p; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:37 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-ratelimit-remaining-input-images" : "49999", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json", + "x-request-id" : "req_047636b31f6840b994d03c7bce515a8f", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "CF-Ray" : "9f4b30139d22c96d-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999220", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:37 GMT", + "access-control-expose-headers" : "X-Request-ID", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "875", + "alt-svc" : "h3=\":443\"; ma=86400" + } + }, + "uuid" : "55b2dc03-8f20-4ef1-9d28-fc013869181f", + "persistent" : true, + "insertionIndex" : 39 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-95657ac6-2e20-443c-8ba7-09b79ac752b5.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-95657ac6-2e20-443c-8ba7-09b79ac752b5.json new file mode 100644 index 00000000..4181b99b --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-95657ac6-2e20-443c-8ba7-09b79ac752b5.json @@ -0,0 +1,49 @@ +{ + "id" : "95657ac6-2e20-443c-8ba7-09b79ac752b5", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"content\":\"you are a thoughtful assistant\",\"role\":\"system\"},{\"content\":\"Count from 1 to 10 slowly.\",\"role\":\"user\"}],\"model\":\"gpt-4o-mini\",\"max_tokens\":800,\"stream\":true,\"stream_options\":{\"include_usage\":true},\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-95657ac6-2e20-443c-8ba7-09b79ac752b5.txt", + "headers" : { + "x-request-id" : "req_295a145e03c6472c907c2d5f32a6d7f6", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2f99f80ca6e4-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999982", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:17 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=Ajsk1PkGtV3KeLCM2P2ck7o1iUjOW5TIPJZPKoB.RLw-1777600756.7926934-1.0.1.1-lOQ2CtsbivSImO6HaCzvavfvZm8gxoPEgfqAQPrOx1_RIR1Dtod2NxGtFwShZ0bpf.1Re575hd_rWJEQkZV.LHzgwVzsP9Mn9VKAk7gibntWL7400OyCm8XhGlevPicV; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:17 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "415", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "text/event-stream; charset=utf-8" + } + }, + "uuid" : "95657ac6-2e20-443c-8ba7-09b79ac752b5", + "persistent" : true, + "insertionIndex" : 45 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-a40abba8-2ec4-42b2-a922-bace293d5f60.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-a40abba8-2ec4-42b2-a922-bace293d5f60.json new file mode 100644 index 00000000..60425a70 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-a40abba8-2ec4-42b2-a922-bace293d5f60.json @@ -0,0 +1,49 @@ +{ + "id" : "a40abba8-2ec4-42b2-a922-bace293d5f60", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"content\":\"What is the weather like in Paris, France?\",\"role\":\"user\"}],\"model\":\"gpt-4o\",\"max_tokens\":500,\"temperature\":0.0,\"tools\":[{\"function\":{\"name\":\"get_weather\",\"description\":\"Get the current weather for a location\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and state, e.g. San Francisco, CA\"},\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"],\"description\":\"The unit of temperature\"}},\"required\":[\"location\"]}},\"type\":\"function\"}],\"stream\":false}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-a40abba8-2ec4-42b2-a922-bace293d5f60.json", + "headers" : { + "x-request-id" : "req_a6911c3baacf4b6f97b7ff38f20b6745", + "x-ratelimit-limit-tokens" : "30000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2fa46cbf48e8-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "6ms", + "x-ratelimit-remaining-tokens" : "29999987", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "9999", + "Date" : "Fri, 01 May 2026 01:59:19 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=C9VjsUJUcoVUYeQZiLDaCJkthO6JgfS88pC6c8xAKUI-1777600758.4650762-1.0.1.1-CywauyfkeFMoQJ5wOvGyMnlP.qgdiypl5gdmui2sQij8MQyR4zQEl33DeN0GCKQ0n.x4VW7mGPDnWOXYSs62qJDFRRyLDgZL123WeXlTrLMqvEfZuZY8l.db1cv9fSYX; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:19 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "10000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "456", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "a40abba8-2ec4-42b2-a922-bace293d5f60", + "persistent" : true, + "insertionIndex" : 44 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3.json new file mode 100644 index 00000000..71bed3c9 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3.json @@ -0,0 +1,49 @@ +{ + "id" : "b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"content\":\"What is the weather like in Paris, France?\",\"role\":\"user\"}],\"model\":\"gpt-4o\",\"max_tokens\":500,\"stream\":false,\"temperature\":0.0,\"tools\":[{\"type\":\"function\",\"function\":{\"description\":\"Get the current weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and state, e.g. San Francisco, CA\"},\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"],\"description\":\"The unit of temperature\"}},\"required\":[\"location\"]}}}]}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3.json", + "headers" : { + "x-request-id" : "req_b1ae2851e5bd4ccb92a3ca724d6f397d", + "x-ratelimit-limit-tokens" : "30000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2f92dbbaf3ea-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "6ms", + "x-ratelimit-remaining-tokens" : "29999987", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "9999", + "Date" : "Fri, 01 May 2026 01:59:16 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=UNe6BjO0Phhmt93NFAhGja_toIfhQ.Q08ZgrmXaTtjg-1777600755.6524289-1.0.1.1-_Nyx5mcVILCfwz2mN6Fkna6Xp7TKoQgTPeEewv6NTOzDCFEIPQQqVHDlew2DE77HU8MbWypGHCsvIuW9GO2sTEm0DtE8zXZYuTzrkg3.8.TxzY39zsAnXFdOA2lThZUj; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:16 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "10000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "459", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "b1a2b7b1-6dfe-40d6-9ecb-2e541ec703f3", + "persistent" : true, + "insertionIndex" : 46 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-c85a7df0-c9d1-43e3-9243-6c9f08168a9a.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-c85a7df0-c9d1-43e3-9243-6c9f08168a9a.json new file mode 100644 index 00000000..1f30fb71 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-c85a7df0-c9d1-43e3-9243-6c9f08168a9a.json @@ -0,0 +1,49 @@ +{ + "id" : "c85a7df0-c9d1-43e3-9243-6c9f08168a9a", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\n \"model\" : \"gpt-4o-mini\",\n \"messages\" : [ {\n \"role\" : \"system\",\n \"content\" : \"you are a helpful assistant\"\n }, {\n \"role\" : \"user\",\n \"content\" : \"What is the capital of France?\"\n } ],\n \"temperature\" : 0.0,\n \"stream\" : false\n}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-c85a7df0-c9d1-43e3-9243-6c9f08168a9a.json", + "headers" : { + "x-request-id" : "req_c2f11fead58d41368261d94786de66a9", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b30274c177577-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999982", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:39 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=0X0UPC8ej4sf0oQrfDoNQH3llhreITftl81V8gJvj_o-1777600779.4082007-1.0.1.1-5gCurvunZI0xAqAQ_2t0YwiN.sFCD8GdZU9ROWeclqVGlB0lzwXjezC6Th.M3__Xs8PzaJP8GbU5z29UXi.aAXMNyPfRt3qyBFatUG_5HxnR88cN6btJiQT0_b9_6Cs2; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:39 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "408", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "c85a7df0-c9d1-43e3-9243-6c9f08168a9a", + "persistent" : true, + "insertionIndex" : 36 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-d9ab1761-3428-4e23-9ca4-8bc3d8d909e8.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-d9ab1761-3428-4e23-9ca4-8bc3d8d909e8.json new file mode 100644 index 00000000..e8313535 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-d9ab1761-3428-4e23-9ca4-8bc3d8d909e8.json @@ -0,0 +1,52 @@ +{ + "id" : "d9ab1761-3428-4e23-9ca4-8bc3d8d909e8", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"content\":\"you are a helpful assistant\",\"role\":\"system\"},{\"content\":[{\"text\":\"What color is this image?\",\"type\":\"text\"},{\"image_url\":{\"url\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==\"},\"type\":\"image_url\"}],\"role\":\"user\"}],\"model\":\"gpt-4o-mini\",\"temperature\":0.0,\"stream\":false}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-d9ab1761-3428-4e23-9ca4-8bc3d8d909e8.json", + "headers" : { + "Server" : "cloudflare", + "x-ratelimit-reset-input-images" : "1ms", + "x-ratelimit-reset-tokens" : "0s", + "x-ratelimit-limit-input-images" : "50000", + "set-cookie" : "__cf_bm=kRvV_9qT3df7M1BWEY8soVKcA91Uu_mdTZvOpL7fsRE-1777600777.8065412-1.0.1.1-HtN0cm8ewLpkewQ1BQiLU8mpj8xwwFnMNsUz72zgcF25w.d52p5xS1poWbSCZ3UGU3fl.gIBwb47CbRniUSZh.7Vs4qMrsCXan3KhE36G5hMdWmBmXJ6NOhhCbeURd_5; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:38 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-ratelimit-remaining-input-images" : "49999", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json", + "x-request-id" : "req_eaade2d820d044d997af4cb2ba6d7629", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "CF-Ray" : "9f4b301d4957d801-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999217", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:38 GMT", + "access-control-expose-headers" : "X-Request-ID", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "554", + "alt-svc" : "h3=\":443\"; ma=86400" + } + }, + "uuid" : "d9ab1761-3428-4e23-9ca4-8bc3d8d909e8", + "persistent" : true, + "insertionIndex" : 38 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-ed6872f2-4f70-495b-b6a0-c16db1f524a7.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-ed6872f2-4f70-495b-b6a0-c16db1f524a7.json new file mode 100644 index 00000000..e97b617a --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-ed6872f2-4f70-495b-b6a0-c16db1f524a7.json @@ -0,0 +1,52 @@ +{ + "id" : "ed6872f2-4f70-495b-b6a0-c16db1f524a7", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\n \"model\" : \"gpt-4o-mini\",\n \"messages\" : [ {\n \"role\" : \"system\",\n \"content\" : \"you are a helpful assistant\"\n }, {\n \"role\" : \"user\",\n \"content\" : [ {\n \"type\" : \"text\",\n \"text\" : \"What color is this image?\"\n }, {\n \"type\" : \"image_url\",\n \"image_url\" : {\n \"url\" : \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==\"\n }\n } ]\n } ],\n \"temperature\" : 0.0,\n \"stream\" : false\n}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-ed6872f2-4f70-495b-b6a0-c16db1f524a7.json", + "headers" : { + "Server" : "cloudflare", + "x-ratelimit-reset-input-images" : "1ms", + "x-ratelimit-reset-tokens" : "0s", + "x-ratelimit-limit-input-images" : "50000", + "set-cookie" : "__cf_bm=6DE7Nx3Dj8W2rpMCgWNdYr3b42fYH.yoPw5jAkEsbMw-1777600775.0868008-1.0.1.1-HUfCExCd9CORLDeCGHZKfs7T.zlc7e2PQTCbC7p.ZT99_SGk2q9PUmIVQ_cvxN4iZwgu0FcTyWBIJjxk73IoZKczlNRoAa2BT5Qz19xa79VUhxfbE0dsrUPe.YWKkGWj; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:36 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "x-ratelimit-remaining-input-images" : "49999", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json", + "x-request-id" : "req_20f8a5ff5b3c41c38eb8e459a4a4c96d", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "CF-Ray" : "9f4b300c484db9e6-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999220", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:36 GMT", + "access-control-expose-headers" : "X-Request-ID", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "869", + "alt-svc" : "h3=\":443\"; ma=86400" + } + }, + "uuid" : "ed6872f2-4f70-495b-b6a0-c16db1f524a7", + "persistent" : true, + "insertionIndex" : 40 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-f0745444-cdb9-4620-80fe-c3536a7e644b.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-f0745444-cdb9-4620-80fe-c3536a7e644b.json new file mode 100644 index 00000000..4fdb8184 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-f0745444-cdb9-4620-80fe-c3536a7e644b.json @@ -0,0 +1,49 @@ +{ + "id" : "f0745444-cdb9-4620-80fe-c3536a7e644b", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"content\":\"you are a thoughtful assistant\",\"role\":\"system\"},{\"content\":\"Count from 1 to 10 slowly.\",\"role\":\"user\"}],\"model\":\"gpt-4o-mini\",\"max_tokens\":800,\"stream_options\":{\"include_usage\":true},\"temperature\":0.0,\"stream\":true}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-f0745444-cdb9-4620-80fe-c3536a7e644b.txt", + "headers" : { + "x-request-id" : "req_7ad8f1d1b280453d8e5585547b41a34d", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2fa99830e2da-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999982", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:19 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=axVuhC5c1Wr.jVl7ZnL.O2ZYR9Ysj8OqsxLaVpQF42k-1777600759.2976038-1.0.1.1-5T0PBB5iPIDxUKEBLIFhfkj9tIBs9zH7FisH68Z37baPYf_19mYoGiLF0Vm7kfMROuOBkpPOWZ4C.nSg.HaPCjVKfK2P1J_8w_q4pnIrfbpqzPsol02vfL8v8feyZuD6; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:19 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "250", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "text/event-stream; charset=utf-8" + } + }, + "uuid" : "f0745444-cdb9-4620-80fe-c3536a7e644b", + "persistent" : true, + "insertionIndex" : 43 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-f72c5404-04da-4a59-9543-59097541dc1e.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-f72c5404-04da-4a59-9543-59097541dc1e.json new file mode 100644 index 00000000..bdec23a1 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/chat_completions-f72c5404-04da-4a59-9543-59097541dc1e.json @@ -0,0 +1,49 @@ +{ + "id" : "f72c5404-04da-4a59-9543-59097541dc1e", + "name" : "chat_completions", + "request" : { + "url" : "/chat/completions", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"messages\":[{\"content\":\"you are a helpful assistant\",\"role\":\"system\"},{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"gpt-4o-mini\",\"stream\":false,\"temperature\":0.0}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "chat_completions-f72c5404-04da-4a59-9543-59097541dc1e.json", + "headers" : { + "x-request-id" : "req_f4b7015e8f38414fb4b711578a587a3c", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2f910c7d3208-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999982", + "x-openai-proxy-wasm" : "v0.1", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:16 GMT", + "x-ratelimit-reset-tokens" : "0s", + "access-control-expose-headers" : "X-Request-ID", + "set-cookie" : "__cf_bm=5S6leRr9O537egiQRs5Ryy7HR6EAuD11QRgEuj0gPYc-1777600755.369958-1.0.1.1-p.wGN0T6iBF7fOUvWIwmqh15IbZ.FM8py_CwQ19xfLddqfLq_Mt.2h6FOHAT3sfKJwlM.Y1g9I7D4qhzcHccXm3hIkB2hq8lOCojkeVZhymrY2utv3yKiKDea1QwPQa8; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:16 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "474", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "f72c5404-04da-4a59-9543-59097541dc1e", + "persistent" : true, + "insertionIndex" : 47 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3.json new file mode 100644 index 00000000..199adddb --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3.json @@ -0,0 +1,47 @@ +{ + "id" : "32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3", + "name" : "responses", + "request" : { + "url" : "/responses", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"input\":[{\"role\":\"user\",\"content\":\"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\\n\"},{\"id\":\"rs_0ba4648fbb2a32ab0069f408fb07e48195a99c6346663bc45a\",\"summary\":[{\"text\":\"**Analyzing the sequence**\\n\\nThe user presents the sequence: 2, 6, 12, 20, 30, which corresponds to pronic or oblong numbers expressed as n(n+1). For example, 1*2=2, 2*3=6, 3*4=12, and so forth. The formula for the nth term is a(n) = n(n+1). I notice that the differences between consecutive terms (4, 6, 8, 10) are even numbers starting at 4, indicating a consistent increase. If n starts at 0, then a(n) = n(n+1), which results in 0 at n=0.\",\"type\":\"summary_text\"},{\"text\":\"**Exploring the pattern of the sequence**\\n\\nStarting with n=1, the pattern mirrors n²+n, leading to the formula a(n) = n(n+1) for pronic numbers. The differences between terms (4, 6, 8, 10...) form an arithmetic sequence, increasing by 2 each time. So, I can clearly state that the nth term is the product of consecutive integers, with a simple alternative expression. When indexed from zero, the formula shifts. Ultimately, what stands out is that each term follows the relationship a_n = n(n+1).\",\"type\":\"summary_text\"},{\"text\":\"**Defining the sequence pattern**\\n\\nThe sequence represents pronic numbers, where each term, starting from n=1, follows the formula a_n = n(n+1). These numbers are the products of consecutive integers: 2 as 1×2, 6 as 2×3, and 12 as 3×4. If I used a zero-based index, I'd say a_n = n(n+1) produces a_0=0, but since the sequence starts at n=1, the first term is 2. So, the final conclusion is that pronic numbers are defined by a_n = n(n+1).\",\"type\":\"summary_text\"}],\"type\":\"reasoning\"},{\"id\":\"msg_0ba4648fbb2a32ab0069f40919cc608195b0fb875d88fdd280\",\"content\":[{\"annotations\":[],\"text\":\"Each term is the product of two consecutive integers:\\n\\n2 = 1×2 \\n6 = 2×3 \\n12 = 3×4 \\n20 = 4×5 \\n30 = 5×6 \\n\\nSo if you label the terms a₁, a₂, a₃, … then\\n\\n aₙ = n (n+1).\\n\\nEquivalently, aₙ = n² + n.\",\"type\":\"output_text\",\"logprobs\":[]}],\"role\":\"assistant\",\"status\":\"completed\",\"type\":\"message\"},{\"role\":\"user\",\"content\":\"Using the pattern you discovered, what would be the 10th term? And can you find the sum of the first 10 terms?\"}],\"model\":\"o4-mini\",\"reasoning\":{\"effort\":\"high\",\"summary\":\"detailed\"}}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "responses-32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3.json", + "headers" : { + "x-request-id" : "req_e78e674163154de7bd3b7036f2e1cd5a", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b30a28a0bc4cb-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999625", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 02:00:08 GMT", + "x-ratelimit-reset-tokens" : "0s", + "set-cookie" : "__cf_bm=76YbHyL4X3nZ4_cg2OLHoVqtNa2rReG8f9fe0hrUYJM-1777600799.1295717-1.0.1.1-8QRJX8QHUdb_65toa2s_RWSFV1TaHs21f3Xerg_pX8efFMah5Z_tGOtGQhUnxQjVfZmIfiIG40m.rgSOCLqxibKeki7oS9zWUB0TCMSes3MglGRANo5nTowYl0Ng4Wl3; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:30:08 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "9319", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "32d9bf3d-b8c7-4aa1-bc27-c29cf0bd27e3", + "persistent" : true, + "insertionIndex" : 33 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-47aabefa-78d5-429e-b491-ccada4c9be78.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-47aabefa-78d5-429e-b491-ccada4c9be78.json new file mode 100644 index 00000000..2ce65a56 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-47aabefa-78d5-429e-b491-ccada4c9be78.json @@ -0,0 +1,47 @@ +{ + "id" : "47aabefa-78d5-429e-b491-ccada4c9be78", + "name" : "responses", + "request" : { + "url" : "/responses", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"input\":[{\"role\":\"user\",\"content\":\"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\\n\"},{\"id\":\"rs_058f35ee350a999b0069f40929ac388193b9568cdf70b02b54\",\"summary\":[{\"text\":\"**Analyzing a number sequence**\\n\\nThe user presented me with a sequence: 2, 6, 12, 20, 30. I'm trying to find the pattern and a formula for the nth term. It looks like these numbers correspond to triangular numbers multiplied by 2. In fact, they follow the formula: n(n + 1) which simplifies to n^2 + n. Just to clarify, triangular numbers follow the formula T_n = n(n + 1)/2. Based on this, I see that the given sequence is essentially twice each triangular number.\",\"type\":\"summary_text\"},{\"text\":\"**Clarifying the sequence pattern**\\n\\nI'm breaking down the sequence 2, 6, 12, 20, 30. I see now that it equals 2 times the triangular numbers: 2 = 2×1, 6 = 2×3, etc. The formula for the nth term is a_n = n(n + 1), and it can also be described by observing the differences between terms: 4, 6, 8, 10, which increase by 2 each time. This consistency indicates it's a quadratic sequence. The final conclusion is that the pattern represents rectangular numbers, confirming the formula is a_n = n(n + 1).\",\"type\":\"summary_text\"},{\"text\":\"**Solving for the sequence**\\n\\nI’m working on the sequence and setting up equations based on the relationships I see. I've established that b can be expressed in terms of a and derived equations that simplify down to a = 1 and b = 1, with c equaling 0. So, I've determined the nth term formula is a_n = n(n + 1), which reveals the pattern of pronic numbers, being the product of two consecutive integers, specifically: 2, 6, 12, 20, 30... Just to clarify, the final formula using indexing from 1 is a_n = n(n + 1).\",\"type\":\"summary_text\"}],\"type\":\"reasoning\"},{\"id\":\"msg_058f35ee350a999b0069f4093af15481939783e600a43f5133\",\"content\":[{\"annotations\":[],\"text\":\"The differences between successive terms are\\n\\n 6–2 = 4, \\n12–6 = 6, \\n20–12 = 8, \\n30–20 = 10, \\n\\nso the “step‐sizes” are the even numbers 4,6,8,10,… (i.e. they increase by 2 each time). Any sequence whose second difference is constant is a quadratic, and in fact one checks that\\n\\n 2 = 1·2, \\n 6 = 2·3, \\n12 = 3·4, \\n20 = 4·5, \\n30 = 5·6,\\n\\nso the nth term is the product of two consecutive integers. If we start counting at n=1, the formula is\\n\\n aₙ = n (n + 1) = n² + n.\",\"type\":\"output_text\",\"logprobs\":[]}],\"role\":\"assistant\",\"status\":\"completed\",\"type\":\"message\"},{\"role\":\"user\",\"content\":\"Using the pattern you discovered, what would be the 10th term? And can you find the sum of the first 10 terms?\"}],\"model\":\"o4-mini\",\"reasoning\":{\"effort\":\"high\",\"summary\":\"detailed\"}}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "responses-47aabefa-78d5-429e-b491-ccada4c9be78.json", + "headers" : { + "x-request-id" : "req_f182d1e776fe45049987ba70d1247392", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b315829ab9343-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999537", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 02:00:40 GMT", + "x-ratelimit-reset-tokens" : "0s", + "set-cookie" : "__cf_bm=HA5F3PfNj6mXfKPdm8Q5Jss8858QPx4RaXFaIdxnh20-1777600828.1823637-1.0.1.1-2fYnSxHvejBKFtINzXDZMV2WtRyFahFWJ33yzhQ7NnyiucRLprLmSw5DihYvzBphxBLxqgSQGWN4pkCq5znPMpu3J9Fs11fd3AO5E9uO3hB.mnNdJ7Wxc_Vn1pDEgcoU; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:30:40 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "12028", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "47aabefa-78d5-429e-b491-ccada4c9be78", + "persistent" : true, + "insertionIndex" : 31 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-5b5fd25b-ebbc-486f-a908-37f1d23c8917.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-5b5fd25b-ebbc-486f-a908-37f1d23c8917.json new file mode 100644 index 00000000..70a2c42b --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-5b5fd25b-ebbc-486f-a908-37f1d23c8917.json @@ -0,0 +1,47 @@ +{ + "id" : "5b5fd25b-ebbc-486f-a908-37f1d23c8917", + "name" : "responses", + "request" : { + "url" : "/responses", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"input\":[{\"role\":\"user\",\"content\":\"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\\n\"},{\"id\":\"rs_02227da51c3fd2580069f408f556408196b2db61e732ad86a6\",\"summary\":[{\"text\":\"**Analyzing a number sequence**\\n\\nThe user provided the sequence: 2, 6, 12, 20, 30, and I'm trying to find the pattern and formula for the nth term. I notice this sequence seems to be twice the triangular numbers, which are generated by the formula n(n+1)/2. When I apply that, I see that each term corresponds to the triangular number multiplied by 2. Additionally, the differences suggest it's a quadratic sequence, confirming the numbers are pronic numbers, products of consecutive integers.\",\"type\":\"summary_text\"},{\"text\":\"**Finding the term formula**\\n\\nThe formula for the sequence is a_n = n(n + 1). When starting from n=1, I see it gives the first term, 2. The differences between terms increase by 2 each time, confirming they are pronic numbers. By breaking it down further, I realize these can also be expressed as twice the triangular numbers. The difference sequence is 4, 6, 8, 10, showing it's quadratic. Ultimately, I conclude: a_n = n(n + 1) for the sequence 2, 6, 12, 20, 30.\",\"type\":\"summary_text\"},{\"text\":\"**Summarizing the sequence pattern**\\n\\nThe pattern in this sequence is found in the successive differences, which are even numbers: 4, 6, 8, 10. This leads to the conclusion that a_n = n^2 + n, or more simply, a_n = n(n + 1). Although there's a consideration for starting at n=0, it typically begins at n=1. I can also express it as twice the triangular numbers: a_n = 2T_n. Ultimately, the answer is a_n = n(n + 1) for the terms 2, 6, 12, and so on.\",\"type\":\"summary_text\"}],\"type\":\"reasoning\"},{\"id\":\"msg_02227da51c3fd2580069f40902d7ec81968d11d9124bb4043e\",\"content\":[{\"annotations\":[],\"text\":\"The “gaps” between terms are \\n 6−2=4, 12−6=6, 20−12=8, 30−20=10, … \\ni.e. the differences are 4, 6, 8, 10, … so the second difference is constant (2) and the sequence is quadratic. Solving or noting that it’s twice the triangular numbers gives\\n\\n aₙ = 2·(n(n+1)/2) = n(n+1).\\n\\nIf you start counting at n=1 this indeed yields \\n a₁ = 1·2 = 2, \\n a₂ = 2·3 = 6, \\n a₃ = 3·4 = 12, … \\n\\nSo the nth term is aₙ = n(n+1).\",\"type\":\"output_text\",\"logprobs\":[]}],\"role\":\"assistant\",\"status\":\"completed\",\"type\":\"message\"},{\"role\":\"user\",\"content\":\"Using the pattern you discovered, what would be the 10th term? And can you find the sum of the first 10 terms?\"}],\"model\":\"o4-mini\",\"reasoning\":{\"effort\":\"high\",\"summary\":\"detailed\"}}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "responses-5b5fd25b-ebbc-486f-a908-37f1d23c8917.json", + "headers" : { + "x-request-id" : "req_129159086a704204b746c783a074f56b", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b3004bfbad465-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999535", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:49 GMT", + "x-ratelimit-reset-tokens" : "0s", + "set-cookie" : "__cf_bm=n4rAgBPY43t5Y4j5M.Absw0.dGnIqORAI0RiLXcxcdM-1777600773.8751807-1.0.1.1-5mziabMd3Ug_Sm8BRoaztKT423fSfQhuHu8mLMq_VfcsaE0fsVkLNjWdmIIU_NhCQIAGzJO1uXTjeeBTap0e5wWlg8P0AaQ78uNVUis2NYDXxGRsH.qqwyVDJ3JVCrtP; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:49 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "15709", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "5b5fd25b-ebbc-486f-a908-37f1d23c8917", + "persistent" : true, + "insertionIndex" : 35 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-9e7ab055-cd83-45cb-b979-cea9c4d5c331.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-9e7ab055-cd83-45cb-b979-cea9c4d5c331.json new file mode 100644 index 00000000..bd6d14f5 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-9e7ab055-cd83-45cb-b979-cea9c4d5c331.json @@ -0,0 +1,50 @@ +{ + "id" : "9e7ab055-cd83-45cb-b979-cea9c4d5c331", + "name" : "responses", + "request" : { + "url" : "/responses", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"input\":[{\"role\":\"user\",\"content\":\"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\\n\"}],\"model\":\"o4-mini\",\"reasoning\":{\"effort\":\"high\",\"summary\":\"detailed\"}}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "responses-9e7ab055-cd83-45cb-b979-cea9c4d5c331.json", + "headers" : { + "x-request-id" : "req_54c715fd56744f3cb464ec1c5aed067d", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2f981801b9a4-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999752", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:33 GMT", + "x-ratelimit-reset-tokens" : "0s", + "set-cookie" : "__cf_bm=nIyy.ek3AOamDU_udYAt_GtyrOLJS3nrrQAm2U74bJ0-1777600756.4929082-1.0.1.1-rP4JmdVPDRGqHCGDyx4KiMLXVQB222K1jVo3sQRrK08NduSLtUi8AN8ZLDOGSP104G6UxVUFuUgb_oaX42n4bEGk8.DV0Ao00IN1ofnm5WKFWKZTx4c.FUk_LblQ0Z2u; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:33 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "16910", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "9e7ab055-cd83-45cb-b979-cea9c4d5c331", + "persistent" : true, + "scenarioName" : "scenario-1-responses", + "requiredScenarioState" : "Started", + "newScenarioState" : "scenario-1-responses-2", + "insertionIndex" : 41 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-a2325d24-d1b8-41b7-9544-cbc25a013b0a.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-a2325d24-d1b8-41b7-9544-cbc25a013b0a.json new file mode 100644 index 00000000..bd28095e --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-a2325d24-d1b8-41b7-9544-cbc25a013b0a.json @@ -0,0 +1,50 @@ +{ + "id" : "a2325d24-d1b8-41b7-9544-cbc25a013b0a", + "name" : "responses", + "request" : { + "url" : "/responses", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"input\":[{\"role\":\"user\",\"content\":\"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\\n\"}],\"model\":\"o4-mini\",\"reasoning\":{\"effort\":\"high\",\"summary\":\"detailed\"}}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "responses-a2325d24-d1b8-41b7-9544-cbc25a013b0a.json", + "headers" : { + "x-request-id" : "req_e406e12ab202421eb08059a75d560c4a", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b2fbd3bbb980d-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999752", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 01:59:58 GMT", + "x-ratelimit-reset-tokens" : "0s", + "set-cookie" : "__cf_bm=.r6C0WGdcJdtWCVjHB5JPSGe0xUNim_Pb7CgyM7NKSA-1777600762.4363596-1.0.1.1-U4V7ItBDsAKqhYedVJvVd88mvkQPlW.70smuQXItgDecix2nzT_gkLfRQ5abTpraRHnNpx6rjRTHYUZ.GYkm0i5suHFIbCh3pbKWgYRax147IUw3iSHES6eSMNnJs9qC; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:29:58 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "36163", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "a2325d24-d1b8-41b7-9544-cbc25a013b0a", + "persistent" : true, + "scenarioName" : "scenario-1-responses", + "requiredScenarioState" : "scenario-1-responses-2", + "newScenarioState" : "scenario-1-responses-3", + "insertionIndex" : 34 +} \ No newline at end of file diff --git a/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-d9ea4fac-3e76-4c11-aec7-e15f21bb5f52.json b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-d9ea4fac-3e76-4c11-aec7-e15f21bb5f52.json new file mode 100644 index 00000000..903dabf0 --- /dev/null +++ b/test-harness/src/testFixtures/resources/cassettes/openai/mappings/responses-d9ea4fac-3e76-4c11-aec7-e15f21bb5f52.json @@ -0,0 +1,49 @@ +{ + "id" : "d9ea4fac-3e76-4c11-aec7-e15f21bb5f52", + "name" : "responses", + "request" : { + "url" : "/responses", + "method" : "POST", + "headers" : { + "Content-Type" : { + "equalTo" : "application/json" + } + }, + "bodyPatterns" : [ { + "equalToJson" : "{\"input\":[{\"role\":\"user\",\"content\":\"Look at this sequence: 2, 6, 12, 20, 30. What is the pattern and what would be the formula for the nth term?\\n\"}],\"model\":\"o4-mini\",\"reasoning\":{\"effort\":\"high\",\"summary\":\"detailed\"}}", + "ignoreArrayOrder" : true, + "ignoreExtraElements" : false + } ] + }, + "response" : { + "status" : 200, + "bodyFileName" : "responses-d9ea4fac-3e76-4c11-aec7-e15f21bb5f52.json", + "headers" : { + "x-request-id" : "req_2bcaeb7ec46b45a0a1f2d8906094b049", + "x-ratelimit-limit-tokens" : "150000000", + "openai-organization" : "braintrust-data", + "Server" : "cloudflare", + "CF-Ray" : "9f4b30de882723ab-SEA", + "X-Content-Type-Options" : "nosniff", + "x-ratelimit-reset-requests" : "2ms", + "x-ratelimit-remaining-tokens" : "149999752", + "x-ratelimit-remaining-requests" : "29999", + "Date" : "Fri, 01 May 2026 02:00:27 GMT", + "x-ratelimit-reset-tokens" : "0s", + "set-cookie" : "__cf_bm=ji1kPcnPhDZMVMn0p1Zql9I9uoGuQhnGkj32UvfDp.Q-1777600808.7286487-1.0.1.1-gXOVAbo1zVDyJYYY3NaMDR3QTxzS6FtMkigK96mB1fZab7zvigl2Ot1.e.d4I7q3K8sEhB9407EU5wiLEOyjTNMvj7z1ONP875MREzfxm_xcAEwFLdH825qtMgMDsJGT; HttpOnly; Secure; Path=/; Domain=api.openai.com; Expires=Fri, 01 May 2026 02:30:27 GMT", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains; preload", + "CF-Cache-Status" : "DYNAMIC", + "x-ratelimit-limit-requests" : "30000", + "openai-version" : "2020-10-01", + "openai-processing-ms" : "18952", + "alt-svc" : "h3=\":443\"; ma=86400", + "openai-project" : "proj_vsCSXafhhByzWOThMrJcZiw9", + "Content-Type" : "application/json" + } + }, + "uuid" : "d9ea4fac-3e76-4c11-aec7-e15f21bb5f52", + "persistent" : true, + "scenarioName" : "scenario-1-responses", + "requiredScenarioState" : "scenario-1-responses-3", + "insertionIndex" : 32 +} \ No newline at end of file