diff --git a/.changeset/bump-openrouter-sdk-support.md b/.changeset/bump-openrouter-sdk-support.md new file mode 100644 index 000000000..5070ccd55 --- /dev/null +++ b/.changeset/bump-openrouter-sdk-support.md @@ -0,0 +1,5 @@ +--- +"braintrust": minor +--- + +feat: Bump support for openrouter sdk diff --git a/e2e/scenarios/openrouter-instrumentation/__snapshots__/openrouter-v1-latest.span-tree.json b/e2e/scenarios/openrouter-instrumentation/__snapshots__/openrouter-v1-latest.span-tree.json index f4a406e23..f3adea145 100644 --- a/e2e/scenarios/openrouter-instrumentation/__snapshots__/openrouter-v1-latest.span-tree.json +++ b/e2e/scenarios/openrouter-instrumentation/__snapshots__/openrouter-v1-latest.span-tree.json @@ -431,309 +431,6 @@ "operation": "rerank", "testRunId": "" } - }, - { - "name": "openrouter-call-model-operation", - "children": [ - { - "name": "openrouter.callModel", - "type": "task", - "children": [ - { - "name": "openrouter.beta.responses.send", - "type": "llm", - "children": [], - "input": "Use the lookup_weather tool for Vienna exactly once, then answer with only the forecast.", - "output": [ - { - "arguments": "{\"city\":\"Vienna\"}", - "callId": "tool_lookup_weather_wpdUzM9iTJVWsAhhwR5y", - "id": "", - "name": "lookup_weather", - "status": "completed", - "type": "function_call" - } - ], - "metadata": { - "background": false, - "completedAt": 1785754658, - "createdAt": 1785754657, - "error": null, - "frequencyPenalty": 0, - "id": "", - "incompleteDetails": null, - "instructions": null, - "is_byok": false, - "maxOutputTokens": 24, - "maxToolCalls": 1, - "metadata": {}, - "model": "gemini-2.5-flash-lite", - "object": "response", - "parallelToolCalls": true, - "presencePenalty": 0, - "previousResponseId": null, - "promptCacheOptions": null, - "provider": "google", - "reasoning": null, - "safetyIdentifier": null, - "serviceTier": "default", - "status": "completed", - "step": 1, - "step_type": "initial", - "store": false, - "stream": true, - "temperature": 0, - "text": { - "format": { - "type": "text" - } - }, - "toolChoice": "auto", - "tools": [ - { - "description": "Look up the weather forecast for a city.", - "name": "lookup_weather", - "parameters": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "city": { - "type": "string" - } - }, - "required": [ - "city" - ], - "type": "object" - }, - "strict": null, - "type": "function" - } - ], - "topLogprobs": 0, - "topP": 1, - "truncation": "disabled" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 5, - "cost": 0.0000054, - "cost_upstream_inference_cost": 0.0000054, - "cost_upstream_inference_input_cost": 0.0000034, - "cost_upstream_inference_output_cost": 0.000002, - "prompt_cache_write_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 34, - "tokens": 39 - } - }, - { - "name": "lookup_weather", - "type": "tool", - "children": [], - "input": { - "city": "Vienna" - }, - "output": { - "forecast": "Sunny in Vienna" - }, - "metadata": { - "provider": "openrouter", - "tool_name": "lookup_weather" - } - }, - { - "name": "openrouter.beta.responses.send", - "type": "llm", - "children": [], - "input": [ - "Use the lookup_weather tool for Vienna exactly once, then answer with only the forecast.", - { - "arguments": "{\"city\":\"Vienna\"}", - "callId": "tool_lookup_weather_wpdUzM9iTJVWsAhhwR5y", - "id": "", - "name": "lookup_weather", - "status": "completed", - "type": "function_call" - }, - { - "callId": "tool_lookup_weather_wpdUzM9iTJVWsAhhwR5y", - "id": "", - "output": "{\"forecast\":\"Sunny in Vienna\"}", - "type": "function_call_output" - } - ], - "output": [ - { - "content": [ - { - "annotations": [], - "logprobs": [], - "text": "Sunny in Vienna", - "type": "output_text" - } - ], - "id": "", - "role": "assistant", - "status": "completed", - "type": "message" - } - ], - "metadata": { - "background": false, - "completedAt": 1785754658, - "createdAt": 1785754658, - "error": null, - "frequencyPenalty": 0, - "id": "", - "incompleteDetails": null, - "instructions": null, - "is_byok": false, - "maxOutputTokens": 24, - "maxToolCalls": 1, - "metadata": {}, - "model": "gemini-2.5-flash-lite", - "object": "response", - "parallelToolCalls": true, - "presencePenalty": 0, - "previousResponseId": null, - "promptCacheOptions": null, - "provider": "google", - "reasoning": null, - "safetyIdentifier": null, - "serviceTier": "default", - "status": "completed", - "step": 2, - "step_type": "continue", - "store": false, - "stream": false, - "temperature": 0, - "text": { - "format": { - "type": "text" - } - }, - "toolChoice": "auto", - "tools": [ - { - "description": "Look up the weather forecast for a city.", - "name": "lookup_weather", - "parameters": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "city": { - "type": "string" - } - }, - "required": [ - "city" - ], - "type": "object" - }, - "strict": null, - "type": "function" - } - ], - "topLogprobs": 0, - "topP": 1, - "truncation": "disabled" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 3, - "cost": 0.0000058, - "cost_upstream_inference_cost": 0.0000058, - "cost_upstream_inference_input_cost": 0.0000046, - "cost_upstream_inference_output_cost": 0.0000012, - "prompt_cache_write_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 46, - "tokens": 49 - } - } - ], - "input": "Use the lookup_weather tool for Vienna exactly once, then answer with only the forecast.", - "output": [ - { - "content": [ - { - "annotations": [], - "logprobs": [], - "text": "Sunny in Vienna", - "type": "output_text" - } - ], - "id": "", - "role": "assistant", - "status": "completed", - "type": "message" - } - ], - "metadata": { - "background": false, - "completedAt": 1785754658, - "createdAt": 1785754658, - "error": null, - "frequencyPenalty": 0, - "id": "", - "incompleteDetails": null, - "instructions": null, - "is_byok": false, - "maxOutputTokens": 24, - "maxToolCalls": 1, - "metadata": {}, - "model": "gemini-2.5-flash-lite", - "object": "response", - "parallelToolCalls": true, - "presencePenalty": 0, - "previousResponseId": null, - "promptCacheOptions": null, - "provider": "google", - "reasoning": null, - "safetyIdentifier": null, - "serviceTier": "default", - "status": "completed", - "store": false, - "temperature": 0, - "text": { - "format": { - "type": "text" - } - }, - "toolChoice": "auto", - "tools": [ - { - "description": "Look up the weather forecast for a city.", - "name": "lookup_weather", - "parameters": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "city": { - "type": "string" - } - }, - "required": [ - "city" - ], - "type": "object" - }, - "strict": null, - "type": "function" - } - ], - "topLogprobs": 0, - "topP": 1, - "truncation": "disabled", - "turn_count": 2 - } - } - ], - "metadata": { - "operation": "call-model", - "testRunId": "" - } } ], "metadata": { diff --git a/e2e/scenarios/openrouter-instrumentation/__snapshots__/openrouter-v1-latest.span-tree.txt b/e2e/scenarios/openrouter-instrumentation/__snapshots__/openrouter-v1-latest.span-tree.txt index 3876b0e07..c3798882a 100644 --- a/e2e/scenarios/openrouter-instrumentation/__snapshots__/openrouter-v1-latest.span-tree.txt +++ b/e2e/scenarios/openrouter-instrumentation/__snapshots__/openrouter-v1-latest.span-tree.txt @@ -325,336 +325,54 @@ span_tree: │ "time_to_first_token": 0, │ "tokens": 18 │ } - ├── openrouter-rerank-operation - │ metadata: { - │ "operation": "rerank", - │ "testRunId": "" - │ } - │ └── openrouter.rerank.rerank [llm] - │ input: { - │ "documents": [ - │ "Athens is in Greece.", - │ "Paris is in France.", - │ "Lima is in Peru." - │ ], - │ "query": "Which document is about France?" - │ } - │ output: [ - │ { - │ "index": 1, - │ "relevance_score": 0.06657539 - │ }, - │ { - │ "index": 0, - │ "relevance_score": 0.015062517 - │ } - │ ] - │ metadata: { - │ "document_count": 3, - │ "id": "", - │ "model": "rerank-v3.5", - │ "provider": "cohere", - │ "results": [ - │ { - │ "document": { - │ "text": "Paris is in France." - │ }, - │ "index": 1, - │ "relevanceScore": 0.06657539 - │ }, - │ { - │ "document": { - │ "text": "Athens is in Greece." - │ }, - │ "index": 0, - │ "relevanceScore": 0.015062517 - │ } - │ ], - │ "topN": 2 - │ } - │ metrics: { - │ "cost": 0.001, - │ "search_units": 1 - │ } - └── openrouter-call-model-operation + └── openrouter-rerank-operation metadata: { - "operation": "call-model", + "operation": "rerank", "testRunId": "" } - └── openrouter.callModel [task] - input: "Use the lookup_weather tool for Vienna exactly once, then answer with only the forecast." + └── openrouter.rerank.rerank [llm] + input: { + "documents": [ + "Athens is in Greece.", + "Paris is in France.", + "Lima is in Peru." + ], + "query": "Which document is about France?" + } output: [ { - "content": [ - { - "annotations": [], - "logprobs": [], - "text": "Sunny in Vienna", - "type": "output_text" - } - ], - "id": "", - "role": "assistant", - "status": "completed", - "type": "message" + "index": 1, + "relevance_score": 0.06657539 + }, + { + "index": 0, + "relevance_score": 0.015062517 } ] metadata: { - "background": false, - "completedAt": 1785754658, - "createdAt": 1785754658, - "error": null, - "frequencyPenalty": 0, + "document_count": 3, "id": "", - "incompleteDetails": null, - "instructions": null, - "is_byok": false, - "maxOutputTokens": 24, - "maxToolCalls": 1, - "metadata": {}, - "model": "gemini-2.5-flash-lite", - "object": "response", - "parallelToolCalls": true, - "presencePenalty": 0, - "previousResponseId": null, - "promptCacheOptions": null, - "provider": "google", - "reasoning": null, - "safetyIdentifier": null, - "serviceTier": "default", - "status": "completed", - "store": false, - "temperature": 0, - "text": { - "format": { - "type": "text" - } - }, - "toolChoice": "auto", - "tools": [ + "model": "rerank-v3.5", + "provider": "cohere", + "results": [ { - "description": "Look up the weather forecast for a city.", - "name": "lookup_weather", - "parameters": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "city": { - "type": "string" - } - }, - "required": [ - "city" - ], - "type": "object" + "document": { + "text": "Paris is in France." }, - "strict": null, - "type": "function" + "index": 1, + "relevanceScore": 0.06657539 + }, + { + "document": { + "text": "Athens is in Greece." + }, + "index": 0, + "relevanceScore": 0.015062517 } ], - "topLogprobs": 0, - "topP": 1, - "truncation": "disabled", - "turn_count": 2 + "topN": 2 + } + metrics: { + "cost": 0.001, + "search_units": 1 } - ├── openrouter.beta.responses.send [llm] - │ input: "Use the lookup_weather tool for Vienna exactly once, then answer with only the forecast." - │ output: [ - │ { - │ "arguments": "{\"city\":\"Vienna\"}", - │ "callId": "tool_lookup_weather_wpdUzM9iTJVWsAhhwR5y", - │ "id": "", - │ "name": "lookup_weather", - │ "status": "completed", - │ "type": "function_call" - │ } - │ ] - │ metadata: { - │ "background": false, - │ "completedAt": 1785754658, - │ "createdAt": 1785754657, - │ "error": null, - │ "frequencyPenalty": 0, - │ "id": "", - │ "incompleteDetails": null, - │ "instructions": null, - │ "is_byok": false, - │ "maxOutputTokens": 24, - │ "maxToolCalls": 1, - │ "metadata": {}, - │ "model": "gemini-2.5-flash-lite", - │ "object": "response", - │ "parallelToolCalls": true, - │ "presencePenalty": 0, - │ "previousResponseId": null, - │ "promptCacheOptions": null, - │ "provider": "google", - │ "reasoning": null, - │ "safetyIdentifier": null, - │ "serviceTier": "default", - │ "status": "completed", - │ "step": 1, - │ "step_type": "initial", - │ "store": false, - │ "stream": true, - │ "temperature": 0, - │ "text": { - │ "format": { - │ "type": "text" - │ } - │ }, - │ "toolChoice": "auto", - │ "tools": [ - │ { - │ "description": "Look up the weather forecast for a city.", - │ "name": "lookup_weather", - │ "parameters": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "city": { - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "city" - │ ], - │ "type": "object" - │ }, - │ "strict": null, - │ "type": "function" - │ } - │ ], - │ "topLogprobs": 0, - │ "topP": 1, - │ "truncation": "disabled" - │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 5, - │ "cost": 0.0000054, - │ "cost_upstream_inference_cost": 0.0000054, - │ "cost_upstream_inference_input_cost": 0.0000034, - │ "cost_upstream_inference_output_cost": 0.000002, - │ "prompt_cache_write_tokens": 0, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 34, - │ "tokens": 39 - │ } - ├── lookup_weather [tool] - │ input: { - │ "city": "Vienna" - │ } - │ output: { - │ "forecast": "Sunny in Vienna" - │ } - │ metadata: { - │ "provider": "openrouter", - │ "tool_name": "lookup_weather" - │ } - └── openrouter.beta.responses.send [llm] - input: [ - "Use the lookup_weather tool for Vienna exactly once, then answer with only the forecast.", - { - "arguments": "{\"city\":\"Vienna\"}", - "callId": "tool_lookup_weather_wpdUzM9iTJVWsAhhwR5y", - "id": "", - "name": "lookup_weather", - "status": "completed", - "type": "function_call" - }, - { - "callId": "tool_lookup_weather_wpdUzM9iTJVWsAhhwR5y", - "id": "", - "output": "{\"forecast\":\"Sunny in Vienna\"}", - "type": "function_call_output" - } - ] - output: [ - { - "content": [ - { - "annotations": [], - "logprobs": [], - "text": "Sunny in Vienna", - "type": "output_text" - } - ], - "id": "", - "role": "assistant", - "status": "completed", - "type": "message" - } - ] - metadata: { - "background": false, - "completedAt": 1785754658, - "createdAt": 1785754658, - "error": null, - "frequencyPenalty": 0, - "id": "", - "incompleteDetails": null, - "instructions": null, - "is_byok": false, - "maxOutputTokens": 24, - "maxToolCalls": 1, - "metadata": {}, - "model": "gemini-2.5-flash-lite", - "object": "response", - "parallelToolCalls": true, - "presencePenalty": 0, - "previousResponseId": null, - "promptCacheOptions": null, - "provider": "google", - "reasoning": null, - "safetyIdentifier": null, - "serviceTier": "default", - "status": "completed", - "step": 2, - "step_type": "continue", - "store": false, - "stream": false, - "temperature": 0, - "text": { - "format": { - "type": "text" - } - }, - "toolChoice": "auto", - "tools": [ - { - "description": "Look up the weather forecast for a city.", - "name": "lookup_weather", - "parameters": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "city": { - "type": "string" - } - }, - "required": [ - "city" - ], - "type": "object" - }, - "strict": null, - "type": "function" - } - ], - "topLogprobs": 0, - "topP": 1, - "truncation": "disabled" - } - metrics: { - "completion_reasoning_tokens": 0, - "completion_tokens": 3, - "cost": 0.0000058, - "cost_upstream_inference_cost": 0.0000058, - "cost_upstream_inference_input_cost": 0.0000046, - "cost_upstream_inference_output_cost": 0.0000012, - "prompt_cache_write_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 46, - "tokens": 49 - } diff --git a/e2e/scenarios/openrouter-instrumentation/assertions.ts b/e2e/scenarios/openrouter-instrumentation/assertions.ts index 6a4a01590..9c52949f6 100644 --- a/e2e/scenarios/openrouter-instrumentation/assertions.ts +++ b/e2e/scenarios/openrouter-instrumentation/assertions.ts @@ -138,6 +138,7 @@ export function defineOpenRouterTraceAssertions(options: { name: string; runScenario: RunOpenRouterScenario; snapshotName: string; + supportsCallModel: boolean; supportsRerank: boolean; testFileUrl: string; timeoutMs: number; @@ -336,7 +337,7 @@ export function defineOpenRouterTraceAssertions(options: { expect(span?.output).toBeDefined(); }); - test( + test.runIf(options.supportsCallModel)( "captures trace for client.callModel() and the nested tool call", testConfig, () => { diff --git a/e2e/scenarios/openrouter-instrumentation/package.json b/e2e/scenarios/openrouter-instrumentation/package.json index c84fda1af..ed841d36b 100644 --- a/e2e/scenarios/openrouter-instrumentation/package.json +++ b/e2e/scenarios/openrouter-instrumentation/package.json @@ -20,6 +20,6 @@ "openrouter-sdk-v0": "npm:@openrouter/sdk@0.9.11", "openrouter-sdk-v0-latest": "npm:@openrouter/sdk@0.13.67", "openrouter-sdk-v1": "npm:@openrouter/sdk@1.0.0", - "openrouter-sdk-v1-latest": "npm:@openrouter/sdk@1.2.2" + "openrouter-sdk-v1-latest": "npm:@openrouter/sdk@1.5.60" } } diff --git a/e2e/scenarios/openrouter-instrumentation/pnpm-lock.yaml b/e2e/scenarios/openrouter-instrumentation/pnpm-lock.yaml index 0d2bc7539..b63bdb3a6 100644 --- a/e2e/scenarios/openrouter-instrumentation/pnpm-lock.yaml +++ b/e2e/scenarios/openrouter-instrumentation/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: npm:@openrouter/sdk@1.0.0 version: '@openrouter/sdk@1.0.0' openrouter-sdk-v1-latest: - specifier: npm:@openrouter/sdk@1.2.2 - version: '@openrouter/sdk@1.2.2' + specifier: npm:@openrouter/sdk@1.5.60 + version: '@openrouter/sdk@1.5.60' zod: specifier: 4.1.11 version: 4.1.11 @@ -35,8 +35,8 @@ packages: '@openrouter/sdk@1.0.0': resolution: {integrity: sha512-FTZg35yWnNUjMCGrjBbsGw9WJhnleAWyJlON4ZQ7pxOKsqBrZo7Zzmc3OoJQFQ+39bsIcKMf3wRNNC9KLjihrw==} - '@openrouter/sdk@1.2.2': - resolution: {integrity: sha512-UQPK6WhGJTm5kgJ4fWmktHUhP9MvhMtWVm5alUmL6wPfk9CQ5+e2uwmAdVeoCqtVJfYkr3uMejzQL1AsvfnyOw==} + '@openrouter/sdk@1.5.60': + resolution: {integrity: sha512-l1DL0bCGi5u3QUFXwHgJkr14jdTR6qwXdPhtpafTasLtPc6SHQ5GY1auZbPaGYO8UysGHd6XoSNYWj0adH1Jlw==} zod@4.1.11: resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} @@ -55,7 +55,7 @@ snapshots: dependencies: zod: 4.1.11 - '@openrouter/sdk@1.2.2': + '@openrouter/sdk@1.5.60': dependencies: zod: 4.1.11 diff --git a/e2e/scenarios/openrouter-instrumentation/scenario.impl.mjs b/e2e/scenarios/openrouter-instrumentation/scenario.impl.mjs index 01fe570ea..c2d3af110 100644 --- a/e2e/scenarios/openrouter-instrumentation/scenario.impl.mjs +++ b/e2e/scenarios/openrouter-instrumentation/scenario.impl.mjs @@ -1,3 +1,4 @@ +import assert from "node:assert/strict"; import { wrapOpenRouter } from "braintrust"; import { z } from "zod"; import { @@ -191,6 +192,12 @@ async function runOpenRouterInstrumentationScenario( ); } + // callModel moved to @openrouter/agent in SDK 1.5.57. + if (process.env.OPENROUTER_SUPPORTS_CALL_MODEL === "false") { + assert.equal(client.callModel, undefined); + return; + } + await runOperation( "openrouter-call-model-operation", "call-model", diff --git a/e2e/scenarios/openrouter-instrumentation/scenario.test.ts b/e2e/scenarios/openrouter-instrumentation/scenario.test.ts index 41de5133f..23c22a480 100644 --- a/e2e/scenarios/openrouter-instrumentation/scenario.test.ts +++ b/e2e/scenarios/openrouter-instrumentation/scenario.test.ts @@ -18,6 +18,7 @@ const openRouterScenarios = await Promise.all( autoEntry: "scenario.openrouter-v0911.mjs", dependencyName: "openrouter-sdk-v0", snapshotName: "openrouter-v0", + supportsCallModel: true, supportsRerank: false, wrapperEntry: "scenario.openrouter-v0911.ts", }, @@ -25,6 +26,7 @@ const openRouterScenarios = await Promise.all( autoEntry: "scenario.mjs", dependencyName: "openrouter-sdk-v0-latest", snapshotName: "openrouter-v0-latest", + supportsCallModel: true, supportsRerank: true, wrapperEntry: "scenario.ts", }, @@ -32,6 +34,7 @@ const openRouterScenarios = await Promise.all( autoEntry: "scenario.mjs", dependencyName: "openrouter-sdk-v1", snapshotName: "openrouter-v1", + supportsCallModel: true, supportsRerank: true, wrapperEntry: "scenario.ts", }, @@ -39,6 +42,7 @@ const openRouterScenarios = await Promise.all( autoEntry: "scenario.mjs", dependencyName: "openrouter-sdk-v1-latest", snapshotName: "openrouter-v1-latest", + supportsCallModel: false, supportsRerank: true, wrapperEntry: "scenario.ts", }, @@ -59,7 +63,12 @@ describe.concurrent("variants", () => { runScenario: async ({ runScenarioDir }) => { await runScenarioDir({ entry: scenario.wrapperEntry, - env: { OPENROUTER_PACKAGE_NAME: scenario.dependencyName }, + env: { + OPENROUTER_PACKAGE_NAME: scenario.dependencyName, + OPENROUTER_SUPPORTS_CALL_MODEL: String( + scenario.supportsCallModel, + ), + }, runContext: { variantKey: scenario.snapshotName, originalScenarioDir, @@ -69,6 +78,7 @@ describe.concurrent("variants", () => { }); }, snapshotName: scenario.snapshotName, + supportsCallModel: scenario.supportsCallModel, supportsRerank: scenario.supportsRerank, testFileUrl: import.meta.url, timeoutMs: TIMEOUT_MS, @@ -79,7 +89,12 @@ describe.concurrent("variants", () => { runScenario: async ({ runNodeScenarioDir }) => { await runNodeScenarioDir({ entry: scenario.autoEntry, - env: { OPENROUTER_PACKAGE_NAME: scenario.dependencyName }, + env: { + OPENROUTER_PACKAGE_NAME: scenario.dependencyName, + OPENROUTER_SUPPORTS_CALL_MODEL: String( + scenario.supportsCallModel, + ), + }, nodeArgs: ["--import", "braintrust/hook.mjs"], runContext: { variantKey: scenario.snapshotName, @@ -90,6 +105,7 @@ describe.concurrent("variants", () => { }); }, snapshotName: scenario.snapshotName, + supportsCallModel: scenario.supportsCallModel, supportsRerank: scenario.supportsRerank, testFileUrl: import.meta.url, timeoutMs: TIMEOUT_MS, diff --git a/integrations/otel-js/Dockerfile.test b/integrations/otel-js/Dockerfile.test index 84c76f791..388c3f273 100644 --- a/integrations/otel-js/Dockerfile.test +++ b/integrations/otel-js/Dockerfile.test @@ -33,17 +33,10 @@ WORKDIR /workspace # Copy the entire SDK repository (build context is SDK repo root) COPY . . -# Build braintrust SDK first (required peer dependency) -WORKDIR /workspace/js -RUN pnpm install --ignore-workspace -RUN pnpm run build - -# Build @braintrust/otel package -WORKDIR /workspace/integrations/otel-js -# Replace workspace:* with file: path for braintrust dependency -RUN sed -i.bak 's/"braintrust": "workspace:\*"/"braintrust": "file:..\/..\/js"/' package.json && rm -f package.json.bak -RUN pnpm install --ignore-workspace -RUN pnpm run build +# Build both packages with the workspace lockfile so peer dependencies do not +# resolve to untested releases. Tests install their own version-specific deps. +RUN pnpm install --frozen-lockfile +RUN pnpm exec turbo run build --filter=braintrust --filter=@braintrust/otel # Set the test directory as environment variable (available at runtime) ENV TEST_DIR=${TEST_DIR} diff --git a/integrations/otel-js/run-tests.sh b/integrations/otel-js/run-tests.sh index c3a7b4d0f..3deee29bf 100644 --- a/integrations/otel-js/run-tests.sh +++ b/integrations/otel-js/run-tests.sh @@ -1,5 +1,5 @@ #!/bin/sh set -e -pnpm install --ignore-workspace +pnpm install --ignore-workspace --frozen-lockfile pnpm exec vitest run diff --git a/js/src/auto-instrumentations/configs/openrouter.ts b/js/src/auto-instrumentations/configs/openrouter.ts index 573dd41bb..37cc3d820 100644 --- a/js/src/auto-instrumentations/configs/openrouter.ts +++ b/js/src/auto-instrumentations/configs/openrouter.ts @@ -71,7 +71,8 @@ export const openRouterConfigs: InstrumentationConfig[] = [ channelName: openRouterChannels.callModel.channelName, module: { name: "@openrouter/sdk", - versionRange: ">=0.9.11 <2.0.0", + // callModel moved to @openrouter/agent and was removed in SDK 1.5.57. + versionRange: ">=0.9.11 <1.5.57", filePath: "esm/sdk/sdk.js", }, functionQuery: {