diff --git a/engine/Cargo.lock b/engine/Cargo.lock index 7b65d4cd63..2cc7239c5d 100644 --- a/engine/Cargo.lock +++ b/engine/Cargo.lock @@ -1266,6 +1266,7 @@ dependencies = [ "minijinja", "notify-debouncer-full", "once_cell", + "percent-encoding", "pin-project-lite", "pretty", "pretty_assertions", diff --git a/engine/baml-runtime/Cargo.toml b/engine/baml-runtime/Cargo.toml index 54eeb1ae78..13793944ad 100644 --- a/engine/baml-runtime/Cargo.toml +++ b/engine/baml-runtime/Cargo.toml @@ -66,6 +66,7 @@ log.workspace = true minijinja.workspace = true pin-project-lite.workspace = true pretty.workspace = true +percent-encoding = "2.3.1" regex.workspace = true reqwest-eventsource = "0.6.0" scopeguard.workspace = true diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs b/engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs index 33c151132d..5ae46cfd02 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap, ops::Deref, sync::Arc, time::Duration}; +use std::{borrow::Cow, collections::HashMap, ops::Deref, sync::Arc}; use anyhow::{Context, Result}; use aws_config::{ @@ -7,7 +7,8 @@ use aws_config::{ use aws_credential_types::{ provider::{ error::{CredentialsError, CredentialsNotLoaded}, - future::ProvideCredentials, + future::ProvideCredentials as ProvideCredentialsFuture, + ProvideCredentials, }, Credentials, }; @@ -20,7 +21,7 @@ use aws_sdk_bedrockruntime::{ use aws_smithy_json::serialize::JsonObjectWriter; use aws_smithy_runtime_api::{client::result::SdkError, http::Headers}; use aws_smithy_types::{Blob, Document}; -use baml_ids::HttpRequestId; +use baml_ids::{FunctionCallId, HttpRequestId}; use baml_types::{ tracing::events::{ ClientDetails, HTTPBody, HTTPRequest, HTTPResponse, HTTPResponseStream, SSEEvent, @@ -35,6 +36,7 @@ use internal_llm_client::{ aws_bedrock::{self, ResolvedAwsBedrock}, AllowedRoleMetadata, ClientProvider, ResolvedClientProperty, UnresolvedClientProperty, }; +use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC}; use secrecy::ExposeSecret; use serde::Deserialize; use serde_json::{json, Map}; @@ -68,6 +70,62 @@ fn strip_mime_prefix(mime: &str) -> &str { mime.split_once('/').map(|(_, s)| s).unwrap_or(mime) } +fn media_to_content_block_json(media: &BamlMedia) -> Result { + match media.media_type { + BamlMediaType::Image => match &media.content { + BamlMediaContent::Base64(b64) => { + let mut image_obj = serde_json::Map::new(); + if let Some(mime) = media.mime_type.as_deref() { + image_obj.insert("format".into(), json!(strip_mime_prefix(mime))); + } + image_obj.insert("source".into(), json!({ "bytes": b64.base64 })); + Ok(json!({ "image": serde_json::Value::Object(image_obj) })) + } + _ => anyhow::bail!("AWS Bedrock only supports base64 image inputs in modular requests"), + }, + BamlMediaType::Pdf => match &media.content { + BamlMediaContent::Base64(b64) => { + let mut doc_obj = serde_json::Map::new(); + if let Some(mime) = media.mime_type.as_deref() { + doc_obj.insert("format".into(), json!(strip_mime_prefix(mime))); + } + doc_obj.insert("name".into(), json!("document.pdf")); + doc_obj.insert("source".into(), json!({ "bytes": b64.base64 })); + Ok(json!({ "document": serde_json::Value::Object(doc_obj) })) + } + _ => anyhow::bail!("AWS Bedrock only supports base64 PDF inputs in modular requests"), + }, + BamlMediaType::Video => match &media.content { + BamlMediaContent::Base64(b64) => { + let mut video_obj = serde_json::Map::new(); + if let Some(mime) = media.mime_type.as_deref() { + video_obj.insert("format".into(), json!(strip_mime_prefix(mime))); + } + video_obj.insert("source".into(), json!({ "bytes": b64.base64 })); + Ok(json!({ "video": serde_json::Value::Object(video_obj) })) + } + _ => anyhow::bail!("AWS Bedrock only supports base64 video inputs in modular requests"), + }, + BamlMediaType::Audio => anyhow::bail!("AWS Bedrock does not support audio media parts"), + } +} + +fn system_part_to_json(part: &ChatMessagePart) -> Result { + match part { + ChatMessagePart::Text(t) => Ok(json!({ "text": t })), + ChatMessagePart::WithMeta(p, _) => system_part_to_json(p), + other => anyhow::bail!("AWS Bedrock only supports text system blocks, but got {other:?}"), + } +} + +fn chat_part_to_json(part: &ChatMessagePart) -> Result { + match part { + ChatMessagePart::Text(t) => Ok(json!({ "text": t })), + ChatMessagePart::Media(media) => media_to_content_block_json(media), + ChatMessagePart::WithMeta(inner, _) => chat_part_to_json(inner), + } +} + // represents client that interacts with the Bedrock API pub struct AwsClient { pub name: String, @@ -77,6 +135,12 @@ pub struct AwsClient { properties: ResolvedAwsBedrock, } +const PATH_SEGMENT_ENCODE_SET: &AsciiSet = &NON_ALPHANUMERIC + .remove(b'-') + .remove(b'_') + .remove(b'.') + .remove(b'~'); + fn resolve_properties( provider: &ClientProvider, properties: &UnresolvedClientProperty<()>, @@ -237,13 +301,11 @@ struct ExplicitCredentialsProvider { } impl aws_credential_types::provider::ProvideCredentials for ExplicitCredentialsProvider { - fn provide_credentials<'a>( - &'a self, - ) -> aws_credential_types::provider::future::ProvideCredentials<'a> + fn provide_credentials<'a>(&'a self) -> ProvideCredentialsFuture<'a> where Self: 'a, { - ProvideCredentials::ready(match (&self.access_key_id, &self.secret_access_key, &self.session_token) { + ProvideCredentialsFuture::ready(match (&self.access_key_id, &self.secret_access_key, &self.session_token) { (None, None, None) => { Err(CredentialsError::unhandled("BAML internal error: ExplicitCredentialsProvider should only be constructed if either access_key_id or secret_access_key are provided")) } @@ -261,6 +323,123 @@ impl aws_credential_types::provider::ProvideCredentials for ExplicitCredentialsP } impl AwsClient { + fn build_converse_body_json( + &self, + prompt: &[RenderedChatMessage], + ) -> Result> { + let mut system_blocks: Option> = None; + let mut chat_slice = prompt; + + if let Some((first, remainder)) = chat_slice.split_first() { + if first.role == "system" { + let mut blocks = Vec::new(); + for part in &first.parts { + blocks.push(system_part_to_json(part)?); + } + system_blocks = Some(blocks); + chat_slice = remainder; + } + } + + let mut messages_json: Vec = Vec::new(); + for message in chat_slice { + let mut content_blocks = Vec::new(); + for part in &message.parts { + content_blocks.push(chat_part_to_json(part)?); + } + messages_json.push(json!({ + "role": message.role, + "content": content_blocks, + })); + } + + let mut root = serde_json::Map::new(); + root.insert("messages".into(), serde_json::Value::Array(messages_json)); + + if let Some(system) = system_blocks { + root.insert("system".into(), serde_json::Value::Array(system)); + } + + if let Some(cfg) = &self.properties.inference_config { + let mut map = serde_json::Map::new(); + if let Some(v) = cfg.max_tokens { + map.insert("maxTokens".into(), json!(v)); + } + if let Some(v) = cfg.temperature { + map.insert("temperature".into(), json!(v)); + } + if let Some(v) = cfg.top_p { + map.insert("topP".into(), json!(v)); + } + if let Some(v) = cfg.stop_sequences.as_ref() { + map.insert("stopSequences".into(), json!(v)); + } + if !map.is_empty() { + root.insert("inferenceConfig".into(), serde_json::Value::Object(map)); + } + } + + if !self.properties.additional_model_request_fields.is_empty() { + let addl = serde_json::to_value(&self.properties.additional_model_request_fields)?; + root.insert("additionalModelRequestFields".into(), addl); + } + + Ok(root) + } + + pub async fn build_modular_http_request( + &self, + ctx: &RuntimeContext, + chat_messages: &[RenderedChatMessage], + stream: bool, + request_id: HttpRequestId, + ) -> Result { + if stream { + anyhow::bail!( + "AWS Bedrock modular streaming is not supported. Use non-streaming modular requests." + ); + } + + let region = self.properties.region.clone().unwrap_or_else(|| { + ctx.env_vars() + .get("AWS_REGION") + .cloned() + .unwrap_or_default() + }); + + if region.is_empty() { + anyhow::bail!( + "AWS region is required to build modular request. Set it in the client options or via AWS_REGION." + ); + } + + let body_string = serde_json::to_string(&serde_json::Value::Object( + self.build_converse_body_json(chat_messages)?, + ))?; + let body_bytes = body_string.as_bytes().to_vec(); + + let host = format!("bedrock-runtime.{region}.amazonaws.com"); + let encoded_model = + utf8_percent_encode(&self.properties.model, PATH_SEGMENT_ENCODE_SET).to_string(); + let url = format!("https://{host}/model/{}/converse", encoded_model); + + let mut header_map = HashMap::new(); + header_map.insert("content-type".to_string(), "application/json".to_string()); + header_map.insert("accept".to_string(), "application/json".to_string()); + + Ok(HTTPRequest::new( + request_id, + url, + "POST".to_string(), + header_map, + HTTPBody::new(body_bytes), + ClientDetails { + name: self.context.name.clone(), + provider: "aws-bedrock".to_string(), + options: self.properties.client_options(), + }, + )) + } pub fn dynamic_new(client: &ClientProperty, ctx: &RuntimeContext) -> Result { let properties = resolve_properties(&client.provider, &client.unresolved_options()?, ctx)?; @@ -554,125 +733,6 @@ impl WithRenderRawCurl for AwsClient { prompt: &[internal_baml_jinja::RenderedChatMessage], render_settings: RenderCurlSettings, ) -> Result { - // Build system and messages payloads from the prompt - let mut system_blocks: Option> = None; - let mut chat_slice = prompt; - - if let Some((first, remainder_slice)) = chat_slice.split_first() { - if first.role == "system" { - let mut blocks = Vec::new(); - for part in &first.parts { - match part { - ChatMessagePart::Text(t) => { - blocks.push(json!({ "text": t })); - } - ChatMessagePart::Media(_) => { - anyhow::bail!( - "AWS Bedrock only supports text blocks for system messages, but got {:?}", - part - ); - } - ChatMessagePart::WithMeta(p, _) => { - if let ChatMessagePart::Text(t) = p.as_ref() { - blocks.push(json!({ "text": t })); - } else { - anyhow::bail!( - "AWS Bedrock only supports text blocks for system messages, but got {:?}", - p - ); - } - } - } - } - system_blocks = Some(blocks); - chat_slice = remainder_slice; - } - } - - fn strip_mime_prefix(mime: &str) -> String { - match mime.split_once('/') { - Some((_, s)) => s.to_string(), - None => mime.to_string(), - } - } - - fn to_cli_content_block(media: &BamlMedia) -> Result { - match media.media_type { - BamlMediaType::Image => match &media.content { - BamlMediaContent::Base64(b64) => { - let mut image_obj = serde_json::Map::new(); - if let Some(mime) = media.mime_type.as_deref() { - image_obj.insert("format".into(), json!(strip_mime_prefix(mime))); - } - image_obj.insert("source".into(), json!({ "bytes": b64.base64 })); - Ok(json!({ "image": serde_json::Value::Object(image_obj) })) - } - BamlMediaContent::File(_) | BamlMediaContent::Url(_) => { - anyhow::bail!("BAML internal error (AWSBedrock): image inputs must be base64 for raw curl rendering") - } - }, - BamlMediaType::Pdf => match &media.content { - BamlMediaContent::Base64(b64) => { - let mut doc_obj = serde_json::Map::new(); - if let Some(mime) = media.mime_type.as_deref() { - doc_obj.insert("format".into(), json!(strip_mime_prefix(mime))); - } - doc_obj.insert("name".into(), json!("document.pdf")); - doc_obj.insert("source".into(), json!({ "bytes": b64.base64 })); - Ok(json!({ "document": serde_json::Value::Object(doc_obj) })) - } - BamlMediaContent::File(_) | BamlMediaContent::Url(_) => { - anyhow::bail!("BAML internal error (AWSBedrock): PDF inputs must be base64 for raw curl rendering") - } - }, - BamlMediaType::Video => match &media.content { - BamlMediaContent::Base64(b64) => { - let mut video_obj = serde_json::Map::new(); - if let Some(mime) = media.mime_type.as_deref() { - video_obj.insert("format".into(), json!(strip_mime_prefix(mime))); - } - video_obj.insert("source".into(), json!({ "bytes": b64.base64 })); - Ok(json!({ "video": serde_json::Value::Object(video_obj) })) - } - BamlMediaContent::File(_) | BamlMediaContent::Url(_) => { - anyhow::bail!("BAML internal error (AWSBedrock): video inputs must be base64 for raw curl rendering") - } - }, - BamlMediaType::Audio => { - anyhow::bail!( - "AWS Bedrock does not support audio media type: {:#?}", - media - ) - } - } - } - - let messages_json: Vec = chat_slice - .iter() - .map(|m| { - let mut content_blocks: Vec = Vec::new(); - for part in &m.parts { - match part { - ChatMessagePart::Text(t) => content_blocks.push(json!({ "text": t })), - ChatMessagePart::Media(media) => { - content_blocks.push(to_cli_content_block(media)?); - } - ChatMessagePart::WithMeta(p, _) => match p.as_ref() { - ChatMessagePart::Text(t) => content_blocks.push(json!({ "text": t })), - ChatMessagePart::Media(media) => { - content_blocks.push(to_cli_content_block(media)?); - } - ChatMessagePart::WithMeta(_, _) => unreachable!(), - }, - } - } - Ok(json!({ - "role": m.role, - "content": content_blocks - })) - }) - .collect::>>()?; - // Build CLI command let mut cmd = vec![]; if let Some(region) = &self.properties.region { @@ -692,40 +752,7 @@ impl WithRenderRawCurl for AwsClient { cmd.push("--output json".to_string()); // Build --cli-input-json payload - let mut root = serde_json::Map::new(); - // messages are required - root.insert("messages".into(), serde_json::Value::Array(messages_json)); - - // system (optional) - if let Some(blocks) = system_blocks { - root.insert("system".into(), serde_json::Value::Array(blocks)); - } - - // inferenceConfig (optional) - if let Some(cfg) = &self.properties.inference_config { - let mut map = serde_json::Map::new(); - if let Some(v) = cfg.max_tokens { - map.insert("maxTokens".into(), json!(v)); - } - if let Some(v) = cfg.temperature { - map.insert("temperature".into(), json!(v)); - } - if let Some(v) = cfg.top_p { - map.insert("topP".into(), json!(v)); - } - if let Some(v) = cfg.stop_sequences.as_ref() { - map.insert("stopSequences".into(), json!(v)); - } - if !map.is_empty() { - root.insert("inferenceConfig".into(), serde_json::Value::Object(map)); - } - } - - // additionalModelRequestFields (optional) - if !self.properties.additional_model_request_fields.is_empty() { - let addl = serde_json::to_value(&self.properties.additional_model_request_fields)?; - root.insert("additionalModelRequestFields".into(), addl); - } + let root = self.build_converse_body_json(prompt)?; // pretty, multi-line JSON let input_json_str = serde_json::to_string_pretty(&serde_json::Value::Object(root))?; diff --git a/engine/baml-runtime/src/lib.rs b/engine/baml-runtime/src/lib.rs index 1cb26c38a5..62aedfe027 100644 --- a/engine/baml-runtime/src/lib.rs +++ b/engine/baml-runtime/src/lib.rs @@ -1044,6 +1044,20 @@ impl BamlRuntime { .await .map(|(prompt, ..)| prompt)?; + let mut request_id = HttpRequestId::new(); + + if let RenderedPrompt::Chat(chat) = &prompt { + if let LLMProvider::Primitive(primitive) = provider.as_ref() { + if let internal::llm_client::primitive::LLMPrimitiveProvider::Aws(aws_client) = + primitive.as_ref() + { + return aws_client + .build_modular_http_request(&ctx, chat, stream, request_id) + .await; + } + } + } + let request = match prompt { RenderedPrompt::Chat(chat) => provider .build_request(either::Either::Right(&chat), true, stream, &ctx, self) @@ -1064,7 +1078,7 @@ impl BamlRuntime { // Would also be nice if RequestBuilder had getters so we didn't have to // call .build()? above. Ok(HTTPRequest::new( - HttpRequestId::new(), + std::mem::take(&mut request_id), request.url().to_string(), request.method().to_string(), json_headers(request.headers()), diff --git a/fern/01-guide/05-baml-advanced/modular-api.mdx b/fern/01-guide/05-baml-advanced/modular-api.mdx index e8f944a697..f107e30e58 100644 --- a/fern/01-guide/05-baml-advanced/modular-api.mdx +++ b/fern/01-guide/05-baml-advanced/modular-api.mdx @@ -448,6 +448,172 @@ async function run() { ``` +### AWS Bedrock + +The modular API now returns requests for Bedrock's Converse API. You can +modify it, sign it and forward the request with any HTTP client. A signature +with the SignatureV4 SDK is required, we provide examples of how to do this +below. + +```baml BAML {2} +function ExtractResume(resume: string) -> Resume { + client Bedrock + // Prompt here... +} +``` + + +```python Python +import asyncio +import json +import os +import httpx +from botocore.auth import SigV4Auth +from botocore.awsrequest import AWSRequest +import boto3 +from baml_client import b +from urllib.parse import urlsplit + +async def run(): + req = await b.request.ExtractResume("John Doe | Software Engineer | BSc in CS") + + body = req.body.json() + # Optional: append your own messages before signing. + body["messages"].append({ + "role": "system", + "content": [{"text": "You must respond in JSON."}], + }) + body_string = json.dumps(body) + body_bytes = body_string.encode("utf-8") + + session = boto3.Session() + credentials = session.get_credentials().get_frozen_credentials() + region = ( + req.client_details.options.get("region") + or os.environ.get("AWS_REGION") + or os.environ.get("AWS_DEFAULT_REGION") + or session.region_name + or "us-east-1" + ) + + url = urlsplit(req.url) + + base_headers = { + key: value + for key, value in dict(req.headers).items() + if value is not None + } + + headers = { + **base_headers, + "content-type": "application/json", + "accept": "application/json", + "host": url.netloc, + } + + aws_request = AWSRequest( + method=req.method, + url=req.url, + data=body_bytes, + headers=headers, + ) + SigV4Auth(credentials, "bedrock", region).add_auth(aws_request) + + async with httpx.AsyncClient() as client: + response = await client.post( + req.url, + headers={key: str(value) for key, value in aws_request.headers.items()}, + content=body_bytes, + ) + if not response.is_success: + raise RuntimeError( + f"Bedrock request failed: {response.status_code} {response.text}" + ) + + payload = response.json() + message = payload["output"]["message"]["content"][0]["text"] + parsed = b.parse.ExtractResume(message) + print(parsed) + +asyncio.run(run()) +``` + +```typescript TypeScript +import { SignatureV4 } from "@smithy/signature-v4" +import { fromEnv } from "@aws-sdk/credential-providers" +import { HttpRequest } from "@smithy/protocol-http" +import { Sha256 } from "@aws-crypto/sha256-js" +import { b } from 'baml_client' + +async function run() { + const req = await b.request.ExtractResume("John Doe | Software Engineer | BSc in CS") + + const body = req.body.json() as any + body.messages.push({ + role: "user", + content: [{ text: "Add a short TL;DR." }], + }) + const bodyString = JSON.stringify(body) + + const url = new URL(req.url) + const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? "us-east-1" + + const signer = new SignatureV4({ + service: "bedrock", + region, + credentials: fromEnv(), + sha256: Sha256, + }) + + const baseHeaders = Object.fromEntries( + Object.entries(req.headers as Record).filter( + ([, value]) => value !== undefined, + ), + ) as Record + + const headers = { + ...baseHeaders, + host: url.host, + "content-type": "application/json", + accept: "application/json", + } + + const unsigned = new HttpRequest({ + protocol: url.protocol, + hostname: url.hostname, + path: url.pathname, + method: req.method, + headers, + body: bodyString, + }) + + const signed = await signer.sign(unsigned) + const signedHeaders = Object.fromEntries( + Object.entries(signed.headers).map(([key, value]) => [key, String(value)]), + ) as Record + + const res = await fetch(req.url, { + method: req.method, + headers: signedHeaders, + body: bodyString, + }) + + if (!res.ok) { + throw new Error(`Bedrock request failed: ${res.status} ${await res.text()}`) + } + + const payload = await res.json() + const message = payload.output.message.content.find((block: any) => block.text)?.text ?? '' + const parsed = b.parse.ExtractResume(message) + console.log(parsed) +} +``` + + +> ℹ️ Streaming modular requests are not yet supported for Bedrock. Call +> `b.request` (non-streaming) when targeting AWS, and re-sign after any +> modifications to the body or headers. + ## Type Checking ### Python diff --git a/fern/03-reference/baml/clients/providers/aws-bedrock.mdx b/fern/03-reference/baml/clients/providers/aws-bedrock.mdx index b75575b30f..c698346400 100644 --- a/fern/03-reference/baml/clients/providers/aws-bedrock.mdx +++ b/fern/03-reference/baml/clients/providers/aws-bedrock.mdx @@ -484,6 +484,106 @@ You can use this to modify the `region`, `access_key_id`, `secret_access_key`, a +## Modular API + +- `b.request` returns a fully signed SigV4 `HTTPRequest` pointing at the + Converse API. +- Forward the request as-is. Do not mutate the headers; they already include + `Authorization`, `X-Amz-Date`, and (if needed) `X-Amz-Security-Token`. +- Send the request immediately after building it. The signature is computed at + request time, so rebuilding gives you a fresh signature. +- Streaming modular calls are not yet supported for Bedrock. + +```typescript TypeScript +import { SignatureV4 } from "@aws-sdk/signature-v4" +import { defaultProvider } from "@aws-sdk/credential-provider-node" +import { HttpRequest } from "@aws-sdk/protocol-http" +import { b } from 'baml_client' + +async function callBedrock() { + const req = await b.request.ExtractResume("John Doe | Software Engineer | BSc in CS") + + const body = req.body.json() as any + const bodyString = JSON.stringify(body) + const url = new URL(req.url) + const region = (req.client_details.options?.region as string) ?? process.env.AWS_REGION ?? "us-east-1" + + const signer = new SignatureV4({ + service: "bedrock", + region, + credentials: defaultProvider(), + }) + + const unsigned = new HttpRequest({ + protocol: url.protocol, + hostname: url.hostname, + path: url.pathname, + method: req.method, + headers: { + ...req.headers, + host: url.host, + "content-type": "application/json", + }, + body: bodyString, + }) + + const signed = await signer.sign(unsigned) + + const res = await fetch(req.url, { + method: req.method, + headers: signed.headers as Record, + body: bodyString, + }) + + if (!res.ok) { + throw new Error(`Bedrock request failed: ${res.status}`) + } + + const payload = await res.json() + const message = payload.output.message.content.find((block: any) => block.text)?.text ?? '' + + return b.parse.ExtractResume(message) +} +``` + +```python Python +import json +import requests +from botocore.auth import SigV4Auth +from botocore.awsrequest import AWSRequest +import boto3 +from baml_client import b + +def call_bedrock(): + req = b.request.ExtractResume("John Doe | Software Engineer | BSc in CS") + + body = req.body.json() + body_bytes = json.dumps(body).encode("utf-8") + + session = boto3.Session() + credentials = session.get_credentials().get_frozen_credentials() + region = req.client_details.options.get("region") or session.region_name or "us-east-1" + + aws_request = AWSRequest( + method=req.method, + url=req.url, + data=body_bytes, + headers=dict(req.headers), + ) + SigV4Auth(credentials, "bedrock", region).add_auth(aws_request) + + response = requests.post( + req.url, + headers=dict(aws_request.headers.items()), + data=body_bytes, + ) + response.raise_for_status() + + payload = response.json() + message = payload["output"]["message"]["content"][0]["text"] + return b.parse.ExtractResume(message) +``` + ## Provider request parameters These are other `options` that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. @@ -600,4 +700,3 @@ client MyClient { - Use `AWS_PROFILE` to manage multiple profiles - Run `aws configure list` to verify configuration - diff --git a/flake.nix b/flake.nix index 2a2a14803b..80a004f89a 100644 --- a/flake.nix +++ b/flake.nix @@ -46,8 +46,9 @@ buildInputs = (with pkgs; [ cmake git - go - gotools + go + gotools + mise openssl pkg-config lld_17 diff --git a/integ-tests/baml_src/clients.baml b/integ-tests/baml_src/clients.baml index aba8076b9a..62af65c3c3 100644 --- a/integ-tests/baml_src/clients.baml +++ b/integ-tests/baml_src/clients.baml @@ -219,7 +219,7 @@ client AwsBedrock { // max_completion_tokens 100000 // model "anthropic.claude-3-5-sonnet-20240620-v1:0" // model_id "anthropic.claude-3-haiku-20240307-v1:0" - model "meta.llama3-8b-instruct-v1:0" + model "arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0" // region "us-east-1" // access_key_id env.AWS_ACCESS_KEY_ID // secret_access_key env.AWS_SECRET_ACCESS_KEY @@ -432,4 +432,4 @@ client AzureO3WithMaxCompletionTokens { api_key env.AZURE_OPENAI_API_KEY max_completion_tokens 1000 } -} \ No newline at end of file +} diff --git a/integ-tests/go/baml_client/baml_source_map.go b/integ-tests/go/baml_client/baml_source_map.go index eba335a2e1..543830ef43 100644 --- a/integ-tests/go/baml_client/baml_source_map.go +++ b/integ-tests/go/baml_client/baml_source_map.go @@ -15,7 +15,7 @@ package baml_client var file_map = map[string]string{ - "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"meta.llama3-8b-instruct-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}", + "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n", "custom-task.baml": "class BookOrder {\n orderId string @description(#\"\n The ID of the book order\n \"#)\n title string @description(#\"\n The title of the ordered book\n \"#)\n quantity int @description(#\"\n The quantity of books ordered\n \"#)\n price float @description(#\"\n The price of the book\n \"#)\n}\n\nclass FlightConfirmation {\n confirmationNumber string @description(#\"\n The flight confirmation number\n \"#)\n flightNumber string @description(#\"\n The flight number\n \"#)\n departureTime string @description(#\"\n The scheduled departure time of the flight\n \"#)\n arrivalTime string @description(#\"\n The scheduled arrival time of the flight\n \"#)\n seatNumber string @description(#\"\n The seat number assigned on the flight\n \"#)\n}\n\nclass GroceryReceipt {\n receiptId string @description(#\"\n The ID of the grocery receipt\n \"#)\n storeName string @description(#\"\n The name of the grocery store\n \"#)\n items (string | int | float)[] @description(#\"\n A list of items purchased. Each item consists of a name, quantity, and price.\n \"#)\n totalAmount float @description(#\"\n The total amount spent on groceries\n \"#)\n}\n \nclass CustomTaskResult {\n bookOrder BookOrder | null\n flightConfirmation FlightConfirmation | null\n groceryReceipt GroceryReceipt | null\n}\n\nfunction CustomTask(input: string) -> BookOrder | FlightConfirmation | GroceryReceipt {\n client \"openai/gpt-4o-mini\"\n prompt #\"\n Given the input string, extract either an order for a book, a flight confirmation, or a grocery receipt.\n\n {{ ctx.output_format }}\n\n Input:\n \n {{ input}}\n \"#\n}\n\ntest CustomTask {\n functions [CustomTask]\n args {\n input #\"\nDear [Your Name],\n\nThank you for booking with [Airline Name]! We are pleased to confirm your upcoming flight.\n\nFlight Confirmation Details:\n\nBooking Reference: ABC123\nPassenger Name: [Your Name]\nFlight Number: XY789\nDeparture Date: September 15, 2024\nDeparture Time: 10:30 AM\nArrival Time: 1:45 PM\nDeparture Airport: John F. Kennedy International Airport (JFK), New York, NY\nArrival Airport: Los Angeles International Airport (LAX), Los Angeles, CA\nSeat Number: 12A\nClass: Economy\nBaggage Allowance:\n\nChecked Baggage: 1 piece, up to 23 kg\nCarry-On Baggage: 1 piece, up to 7 kg\nImportant Information:\n\nPlease arrive at the airport at least 2 hours before your scheduled departure.\nCheck-in online via our website or mobile app to save time at the airport.\nEnsure that your identification documents are up to date and match the name on your booking.\nContact Us:\n\nIf you have any questions or need to make changes to your booking, please contact our customer service team at 1-800-123-4567 or email us at support@[airline].com.\n\nWe wish you a pleasant journey and thank you for choosing [Airline Name].\n\nBest regards,\n\n[Airline Name] Customer Service\n \"#\n }\n}", "fiddle-examples/audio/audio.baml": "function DescribeAudio(audio: audio) -> string {\n client GPT4o\n prompt #\"\n Describe the audio below in 20 words:\n {{ _.role(\"user\") }}\n {{ audio }}\n \"#\n\n}\n\n\n\n\n// chat role user present\nfunction DescribeAudio2(audio: audio) -> string {\n client GPT4Turbo\n prompt #\"\n {{ _.role(\"user\") }}\n You should return 1 answer that answer the following command.\n\n Describe this in 5 words:\n {{ audio }}\n \"#\n}\n\ntest TestAudio {\n functions [DescribeAudio]\n args {\n audio { url \"https://www.pacdv.com/sounds/voices/friday-rocks.wav\"}\n }\n}\n\ntest TestAudio2 {\n functions [DescribeAudio2]\n args {\n audio { file \"friday-rocks.wav\" }\n }\n}\n", "fiddle-examples/chain-of-thought.baml": "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", diff --git a/integ-tests/python-v1/baml_client/inlinedbaml.py b/integ-tests/python-v1/baml_client/inlinedbaml.py index 7dac7d16a0..fa96abf307 100644 --- a/integ-tests/python-v1/baml_client/inlinedbaml.py +++ b/integ-tests/python-v1/baml_client/inlinedbaml.py @@ -12,7 +12,7 @@ _file_map = { - "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"meta.llama3-8b-instruct-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}", + "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n", "custom-task.baml": "class BookOrder {\n orderId string @description(#\"\n The ID of the book order\n \"#)\n title string @description(#\"\n The title of the ordered book\n \"#)\n quantity int @description(#\"\n The quantity of books ordered\n \"#)\n price float @description(#\"\n The price of the book\n \"#)\n}\n\nclass FlightConfirmation {\n confirmationNumber string @description(#\"\n The flight confirmation number\n \"#)\n flightNumber string @description(#\"\n The flight number\n \"#)\n departureTime string @description(#\"\n The scheduled departure time of the flight\n \"#)\n arrivalTime string @description(#\"\n The scheduled arrival time of the flight\n \"#)\n seatNumber string @description(#\"\n The seat number assigned on the flight\n \"#)\n}\n\nclass GroceryReceipt {\n receiptId string @description(#\"\n The ID of the grocery receipt\n \"#)\n storeName string @description(#\"\n The name of the grocery store\n \"#)\n items (string | int | float)[] @description(#\"\n A list of items purchased. Each item consists of a name, quantity, and price.\n \"#)\n totalAmount float @description(#\"\n The total amount spent on groceries\n \"#)\n}\n \nclass CustomTaskResult {\n bookOrder BookOrder | null\n flightConfirmation FlightConfirmation | null\n groceryReceipt GroceryReceipt | null\n}\n\nfunction CustomTask(input: string) -> BookOrder | FlightConfirmation | GroceryReceipt {\n client \"openai/gpt-4o-mini\"\n prompt #\"\n Given the input string, extract either an order for a book, a flight confirmation, or a grocery receipt.\n\n {{ ctx.output_format }}\n\n Input:\n \n {{ input}}\n \"#\n}\n\ntest CustomTask {\n functions [CustomTask]\n args {\n input #\"\nDear [Your Name],\n\nThank you for booking with [Airline Name]! We are pleased to confirm your upcoming flight.\n\nFlight Confirmation Details:\n\nBooking Reference: ABC123\nPassenger Name: [Your Name]\nFlight Number: XY789\nDeparture Date: September 15, 2024\nDeparture Time: 10:30 AM\nArrival Time: 1:45 PM\nDeparture Airport: John F. Kennedy International Airport (JFK), New York, NY\nArrival Airport: Los Angeles International Airport (LAX), Los Angeles, CA\nSeat Number: 12A\nClass: Economy\nBaggage Allowance:\n\nChecked Baggage: 1 piece, up to 23 kg\nCarry-On Baggage: 1 piece, up to 7 kg\nImportant Information:\n\nPlease arrive at the airport at least 2 hours before your scheduled departure.\nCheck-in online via our website or mobile app to save time at the airport.\nEnsure that your identification documents are up to date and match the name on your booking.\nContact Us:\n\nIf you have any questions or need to make changes to your booking, please contact our customer service team at 1-800-123-4567 or email us at support@[airline].com.\n\nWe wish you a pleasant journey and thank you for choosing [Airline Name].\n\nBest regards,\n\n[Airline Name] Customer Service\n \"#\n }\n}", "fiddle-examples/audio/audio.baml": "function DescribeAudio(audio: audio) -> string {\n client GPT4o\n prompt #\"\n Describe the audio below in 20 words:\n {{ _.role(\"user\") }}\n {{ audio }}\n \"#\n\n}\n\n\n\n\n// chat role user present\nfunction DescribeAudio2(audio: audio) -> string {\n client GPT4Turbo\n prompt #\"\n {{ _.role(\"user\") }}\n You should return 1 answer that answer the following command.\n\n Describe this in 5 words:\n {{ audio }}\n \"#\n}\n\ntest TestAudio {\n functions [DescribeAudio]\n args {\n audio { url \"https://www.pacdv.com/sounds/voices/friday-rocks.wav\"}\n }\n}\n\ntest TestAudio2 {\n functions [DescribeAudio2]\n args {\n audio { file \"friday-rocks.wav\" }\n }\n}\n", "fiddle-examples/chain-of-thought.baml": "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", diff --git a/integ-tests/python/baml_client/inlinedbaml.py b/integ-tests/python/baml_client/inlinedbaml.py index 7dac7d16a0..fa96abf307 100644 --- a/integ-tests/python/baml_client/inlinedbaml.py +++ b/integ-tests/python/baml_client/inlinedbaml.py @@ -12,7 +12,7 @@ _file_map = { - "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"meta.llama3-8b-instruct-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}", + "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n", "custom-task.baml": "class BookOrder {\n orderId string @description(#\"\n The ID of the book order\n \"#)\n title string @description(#\"\n The title of the ordered book\n \"#)\n quantity int @description(#\"\n The quantity of books ordered\n \"#)\n price float @description(#\"\n The price of the book\n \"#)\n}\n\nclass FlightConfirmation {\n confirmationNumber string @description(#\"\n The flight confirmation number\n \"#)\n flightNumber string @description(#\"\n The flight number\n \"#)\n departureTime string @description(#\"\n The scheduled departure time of the flight\n \"#)\n arrivalTime string @description(#\"\n The scheduled arrival time of the flight\n \"#)\n seatNumber string @description(#\"\n The seat number assigned on the flight\n \"#)\n}\n\nclass GroceryReceipt {\n receiptId string @description(#\"\n The ID of the grocery receipt\n \"#)\n storeName string @description(#\"\n The name of the grocery store\n \"#)\n items (string | int | float)[] @description(#\"\n A list of items purchased. Each item consists of a name, quantity, and price.\n \"#)\n totalAmount float @description(#\"\n The total amount spent on groceries\n \"#)\n}\n \nclass CustomTaskResult {\n bookOrder BookOrder | null\n flightConfirmation FlightConfirmation | null\n groceryReceipt GroceryReceipt | null\n}\n\nfunction CustomTask(input: string) -> BookOrder | FlightConfirmation | GroceryReceipt {\n client \"openai/gpt-4o-mini\"\n prompt #\"\n Given the input string, extract either an order for a book, a flight confirmation, or a grocery receipt.\n\n {{ ctx.output_format }}\n\n Input:\n \n {{ input}}\n \"#\n}\n\ntest CustomTask {\n functions [CustomTask]\n args {\n input #\"\nDear [Your Name],\n\nThank you for booking with [Airline Name]! We are pleased to confirm your upcoming flight.\n\nFlight Confirmation Details:\n\nBooking Reference: ABC123\nPassenger Name: [Your Name]\nFlight Number: XY789\nDeparture Date: September 15, 2024\nDeparture Time: 10:30 AM\nArrival Time: 1:45 PM\nDeparture Airport: John F. Kennedy International Airport (JFK), New York, NY\nArrival Airport: Los Angeles International Airport (LAX), Los Angeles, CA\nSeat Number: 12A\nClass: Economy\nBaggage Allowance:\n\nChecked Baggage: 1 piece, up to 23 kg\nCarry-On Baggage: 1 piece, up to 7 kg\nImportant Information:\n\nPlease arrive at the airport at least 2 hours before your scheduled departure.\nCheck-in online via our website or mobile app to save time at the airport.\nEnsure that your identification documents are up to date and match the name on your booking.\nContact Us:\n\nIf you have any questions or need to make changes to your booking, please contact our customer service team at 1-800-123-4567 or email us at support@[airline].com.\n\nWe wish you a pleasant journey and thank you for choosing [Airline Name].\n\nBest regards,\n\n[Airline Name] Customer Service\n \"#\n }\n}", "fiddle-examples/audio/audio.baml": "function DescribeAudio(audio: audio) -> string {\n client GPT4o\n prompt #\"\n Describe the audio below in 20 words:\n {{ _.role(\"user\") }}\n {{ audio }}\n \"#\n\n}\n\n\n\n\n// chat role user present\nfunction DescribeAudio2(audio: audio) -> string {\n client GPT4Turbo\n prompt #\"\n {{ _.role(\"user\") }}\n You should return 1 answer that answer the following command.\n\n Describe this in 5 words:\n {{ audio }}\n \"#\n}\n\ntest TestAudio {\n functions [DescribeAudio]\n args {\n audio { url \"https://www.pacdv.com/sounds/voices/friday-rocks.wav\"}\n }\n}\n\ntest TestAudio2 {\n functions [DescribeAudio2]\n args {\n audio { file \"friday-rocks.wav\" }\n }\n}\n", "fiddle-examples/chain-of-thought.baml": "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", diff --git a/integ-tests/python/tests/test_modular_api.py b/integ-tests/python/tests/test_modular_api.py index a3543d2cb5..8e052a2d1d 100644 --- a/integ-tests/python/tests/test_modular_api.py +++ b/integ-tests/python/tests/test_modular_api.py @@ -3,13 +3,19 @@ import time import typing import json +import os import pytest import anthropic import requests +import boto3 from google import genai from openai import AsyncOpenAI, OpenAI, AsyncStream, Stream from openai.types.chat import ChatCompletion, ChatCompletionChunk from openai.types.responses import Response +from botocore.auth import SigV4Auth +from botocore.awsrequest import AWSRequest +from botocore.exceptions import ProfileNotFound +from urllib.parse import urlsplit from baml_py import ClientRegistry, HTTPRequest as BamlHttpRequest from ..baml_client import b from ..baml_client.sync_client import b as sync_b @@ -33,6 +39,8 @@ Software Engineer at Google (2020 - Present) """ +LONG_CACHEABLE_CONTEXT = " ".join(["Reusable cacheable context paragraph." for _ in range(600)]) + JOHN_DOE_PARSED_RESUME = types.Resume( name="John Doe", email="johndoe@example.com", @@ -120,6 +128,90 @@ async def test_modular_openai_gpt4(): assert parsed == JOHN_DOE_PARSED_RESUME +@pytest.mark.asyncio +async def test_modular_bedrock_manual_cache_point(): + req = await b.request.TestAws("Dr. Pepper") + + body = req.body.json() + assert isinstance(body["messages"], list) + assert len(body["messages"]) > 0 + + content = body["messages"][0]["content"] + assert isinstance(content, list) + original_length = len(content) + + content.insert(1, {"text": LONG_CACHEABLE_CONTEXT}) + content.insert(2, {"cachePoint": {"type": "default"}}) + + assert content[1] == {"text": LONG_CACHEABLE_CONTEXT} + assert content[2] == {"cachePoint": {"type": "default"}} + assert len(content) == original_length + 2 + + # additional.setdefault("cacheConfig", {"type": "default"}) + + body_string = json.dumps(body) + body_bytes = body_string.encode("utf-8") + + url = urlsplit(req.url) + + base_headers = { + key: value + for key, value in dict(req.headers).items() + if value is not None + } + + headers = { + **base_headers, + "content-type": "application/json", + "accept": "application/json", + "host": url.netloc, + } + + try: + session = boto3.Session() + except ProfileNotFound: + session = boto3.Session(profile_name=None) + credentials = session.get_credentials() + if credentials is None: + pytest.skip("AWS credentials not configured") + frozen = credentials.get_frozen_credentials() + + region = os.environ.get("AWS_REGION") or os.environ.get("AWS_DEFAULT_REGION") + if not region: + region = session.region_name + if not region: + available = session.get_available_regions("bedrock-runtime") + region = available[0] if available else None + if not region: + pytest.skip("AWS region not configured") + + aws_request = AWSRequest( + method=req.method, + url=req.url, + data=body_bytes, + headers=headers, + ) + + SigV4Auth(frozen, "bedrock", region).add_auth(aws_request) + + response = requests.post( + req.url, + headers={key: str(value) for key, value in aws_request.headers.items()}, + data=body_bytes, + ) + if not response.ok: + raise AssertionError( + f"Bedrock returned {response.status_code}: {response.text}" + ) + response.raise_for_status() + + payload = response.json() + content_blocks = payload.get("output", {}).get("message", {}).get("content", []) + assert isinstance(content_blocks, list) + text_block = next((block.get("text") for block in content_blocks if "text" in block), "") + assert text_block + + @pytest.mark.asyncio async def test_modular_anthropic_claude_3_haiku(): client = anthropic.AsyncAnthropic() @@ -318,20 +410,20 @@ async def test_openai_batch_api(): async def test_modular_openai_responses(): """Test openai-responses provider using the modular API""" from openai import AsyncOpenAI - + client = AsyncOpenAI() - + # Use TestOpenAIResponses from the providers directory req = await b.request.TestOpenAIResponses("mountains") - + # The openai-responses provider should use the /v1/responses endpoint. response = typing.cast( Response, await client.responses.create(**req.body.json()) ) - + parsed = b.parse.TestOpenAIResponses(response.output_text) - + assert isinstance(parsed, str) assert len(parsed) > 0 @@ -363,4 +455,4 @@ async def test_modular_vertex(): # we should be well under 50ms cause there's no network latency assert mean_duration < 50, "Vertex should be cached" # this should be pretty low - assert std_dev < 5, "Vertex should be cached" \ No newline at end of file + assert std_dev < 5, "Vertex should be cached" diff --git a/integ-tests/react/baml_client/inlinedbaml.ts b/integ-tests/react/baml_client/inlinedbaml.ts index 73fc823ee8..7e9455ad7d 100644 --- a/integ-tests/react/baml_client/inlinedbaml.ts +++ b/integ-tests/react/baml_client/inlinedbaml.ts @@ -20,7 +20,7 @@ $ pnpm add @boundaryml/baml const fileMap = { - "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"meta.llama3-8b-instruct-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}", + "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n", "custom-task.baml": "class BookOrder {\n orderId string @description(#\"\n The ID of the book order\n \"#)\n title string @description(#\"\n The title of the ordered book\n \"#)\n quantity int @description(#\"\n The quantity of books ordered\n \"#)\n price float @description(#\"\n The price of the book\n \"#)\n}\n\nclass FlightConfirmation {\n confirmationNumber string @description(#\"\n The flight confirmation number\n \"#)\n flightNumber string @description(#\"\n The flight number\n \"#)\n departureTime string @description(#\"\n The scheduled departure time of the flight\n \"#)\n arrivalTime string @description(#\"\n The scheduled arrival time of the flight\n \"#)\n seatNumber string @description(#\"\n The seat number assigned on the flight\n \"#)\n}\n\nclass GroceryReceipt {\n receiptId string @description(#\"\n The ID of the grocery receipt\n \"#)\n storeName string @description(#\"\n The name of the grocery store\n \"#)\n items (string | int | float)[] @description(#\"\n A list of items purchased. Each item consists of a name, quantity, and price.\n \"#)\n totalAmount float @description(#\"\n The total amount spent on groceries\n \"#)\n}\n \nclass CustomTaskResult {\n bookOrder BookOrder | null\n flightConfirmation FlightConfirmation | null\n groceryReceipt GroceryReceipt | null\n}\n\nfunction CustomTask(input: string) -> BookOrder | FlightConfirmation | GroceryReceipt {\n client \"openai/gpt-4o-mini\"\n prompt #\"\n Given the input string, extract either an order for a book, a flight confirmation, or a grocery receipt.\n\n {{ ctx.output_format }}\n\n Input:\n \n {{ input}}\n \"#\n}\n\ntest CustomTask {\n functions [CustomTask]\n args {\n input #\"\nDear [Your Name],\n\nThank you for booking with [Airline Name]! We are pleased to confirm your upcoming flight.\n\nFlight Confirmation Details:\n\nBooking Reference: ABC123\nPassenger Name: [Your Name]\nFlight Number: XY789\nDeparture Date: September 15, 2024\nDeparture Time: 10:30 AM\nArrival Time: 1:45 PM\nDeparture Airport: John F. Kennedy International Airport (JFK), New York, NY\nArrival Airport: Los Angeles International Airport (LAX), Los Angeles, CA\nSeat Number: 12A\nClass: Economy\nBaggage Allowance:\n\nChecked Baggage: 1 piece, up to 23 kg\nCarry-On Baggage: 1 piece, up to 7 kg\nImportant Information:\n\nPlease arrive at the airport at least 2 hours before your scheduled departure.\nCheck-in online via our website or mobile app to save time at the airport.\nEnsure that your identification documents are up to date and match the name on your booking.\nContact Us:\n\nIf you have any questions or need to make changes to your booking, please contact our customer service team at 1-800-123-4567 or email us at support@[airline].com.\n\nWe wish you a pleasant journey and thank you for choosing [Airline Name].\n\nBest regards,\n\n[Airline Name] Customer Service\n \"#\n }\n}", "fiddle-examples/audio/audio.baml": "function DescribeAudio(audio: audio) -> string {\n client GPT4o\n prompt #\"\n Describe the audio below in 20 words:\n {{ _.role(\"user\") }}\n {{ audio }}\n \"#\n\n}\n\n\n\n\n// chat role user present\nfunction DescribeAudio2(audio: audio) -> string {\n client GPT4Turbo\n prompt #\"\n {{ _.role(\"user\") }}\n You should return 1 answer that answer the following command.\n\n Describe this in 5 words:\n {{ audio }}\n \"#\n}\n\ntest TestAudio {\n functions [DescribeAudio]\n args {\n audio { url \"https://www.pacdv.com/sounds/voices/friday-rocks.wav\"}\n }\n}\n\ntest TestAudio2 {\n functions [DescribeAudio2]\n args {\n audio { file \"friday-rocks.wav\" }\n }\n}\n", "fiddle-examples/chain-of-thought.baml": "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", diff --git a/integ-tests/typescript-esm/baml_client/inlinedbaml.ts b/integ-tests/typescript-esm/baml_client/inlinedbaml.ts index 73fc823ee8..7e9455ad7d 100644 --- a/integ-tests/typescript-esm/baml_client/inlinedbaml.ts +++ b/integ-tests/typescript-esm/baml_client/inlinedbaml.ts @@ -20,7 +20,7 @@ $ pnpm add @boundaryml/baml const fileMap = { - "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"meta.llama3-8b-instruct-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}", + "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n", "custom-task.baml": "class BookOrder {\n orderId string @description(#\"\n The ID of the book order\n \"#)\n title string @description(#\"\n The title of the ordered book\n \"#)\n quantity int @description(#\"\n The quantity of books ordered\n \"#)\n price float @description(#\"\n The price of the book\n \"#)\n}\n\nclass FlightConfirmation {\n confirmationNumber string @description(#\"\n The flight confirmation number\n \"#)\n flightNumber string @description(#\"\n The flight number\n \"#)\n departureTime string @description(#\"\n The scheduled departure time of the flight\n \"#)\n arrivalTime string @description(#\"\n The scheduled arrival time of the flight\n \"#)\n seatNumber string @description(#\"\n The seat number assigned on the flight\n \"#)\n}\n\nclass GroceryReceipt {\n receiptId string @description(#\"\n The ID of the grocery receipt\n \"#)\n storeName string @description(#\"\n The name of the grocery store\n \"#)\n items (string | int | float)[] @description(#\"\n A list of items purchased. Each item consists of a name, quantity, and price.\n \"#)\n totalAmount float @description(#\"\n The total amount spent on groceries\n \"#)\n}\n \nclass CustomTaskResult {\n bookOrder BookOrder | null\n flightConfirmation FlightConfirmation | null\n groceryReceipt GroceryReceipt | null\n}\n\nfunction CustomTask(input: string) -> BookOrder | FlightConfirmation | GroceryReceipt {\n client \"openai/gpt-4o-mini\"\n prompt #\"\n Given the input string, extract either an order for a book, a flight confirmation, or a grocery receipt.\n\n {{ ctx.output_format }}\n\n Input:\n \n {{ input}}\n \"#\n}\n\ntest CustomTask {\n functions [CustomTask]\n args {\n input #\"\nDear [Your Name],\n\nThank you for booking with [Airline Name]! We are pleased to confirm your upcoming flight.\n\nFlight Confirmation Details:\n\nBooking Reference: ABC123\nPassenger Name: [Your Name]\nFlight Number: XY789\nDeparture Date: September 15, 2024\nDeparture Time: 10:30 AM\nArrival Time: 1:45 PM\nDeparture Airport: John F. Kennedy International Airport (JFK), New York, NY\nArrival Airport: Los Angeles International Airport (LAX), Los Angeles, CA\nSeat Number: 12A\nClass: Economy\nBaggage Allowance:\n\nChecked Baggage: 1 piece, up to 23 kg\nCarry-On Baggage: 1 piece, up to 7 kg\nImportant Information:\n\nPlease arrive at the airport at least 2 hours before your scheduled departure.\nCheck-in online via our website or mobile app to save time at the airport.\nEnsure that your identification documents are up to date and match the name on your booking.\nContact Us:\n\nIf you have any questions or need to make changes to your booking, please contact our customer service team at 1-800-123-4567 or email us at support@[airline].com.\n\nWe wish you a pleasant journey and thank you for choosing [Airline Name].\n\nBest regards,\n\n[Airline Name] Customer Service\n \"#\n }\n}", "fiddle-examples/audio/audio.baml": "function DescribeAudio(audio: audio) -> string {\n client GPT4o\n prompt #\"\n Describe the audio below in 20 words:\n {{ _.role(\"user\") }}\n {{ audio }}\n \"#\n\n}\n\n\n\n\n// chat role user present\nfunction DescribeAudio2(audio: audio) -> string {\n client GPT4Turbo\n prompt #\"\n {{ _.role(\"user\") }}\n You should return 1 answer that answer the following command.\n\n Describe this in 5 words:\n {{ audio }}\n \"#\n}\n\ntest TestAudio {\n functions [DescribeAudio]\n args {\n audio { url \"https://www.pacdv.com/sounds/voices/friday-rocks.wav\"}\n }\n}\n\ntest TestAudio2 {\n functions [DescribeAudio2]\n args {\n audio { file \"friday-rocks.wav\" }\n }\n}\n", "fiddle-examples/chain-of-thought.baml": "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", diff --git a/integ-tests/typescript/baml_client/inlinedbaml.ts b/integ-tests/typescript/baml_client/inlinedbaml.ts index 73fc823ee8..7e9455ad7d 100644 --- a/integ-tests/typescript/baml_client/inlinedbaml.ts +++ b/integ-tests/typescript/baml_client/inlinedbaml.ts @@ -20,7 +20,7 @@ $ pnpm add @boundaryml/baml const fileMap = { - "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"meta.llama3-8b-instruct-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}", + "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4o {\n provider openai\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider openai\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n}\n\nretry_policy GPT4oRetry {\n max_retries 2\n strategy {\n type exponential_backoff\n }\n}\n\nclient GPT35 {\n provider openai\n retry_policy GPT4oRetry\n options {\n model \"gpt-4o-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient GPT35LegacyProvider {\n provider openai\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n\nclient Ollama {\n provider ollama\n options {\n model llama3.1\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\n// Azure O1 client without max_tokens (should not add default)\nclient AzureO1 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O1 client with explicit max_tokens (should keep user value)\nclient AzureO1WithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\nclient AzureO1WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o1-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// Azure GPT-35 client with explicit max_tokens (should keep user value)\nclient GPT35AzureWithMaxTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure client with invalid resource name (for testing failures)\nclient GPT35AzureFailed {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml-incorrect-suffix\"\n deployment_id \"gpt-35-turbo-default\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options {\n model gemini-2.5-flash\n api_key env.GOOGLE_API_KEY\n safetySettings {\n category HARM_CATEGORY_HATE_SPEECH\n threshold BLOCK_LOW_AND_ABOVE\n }\n }\n}\n\nclient Gemini25ProThinking {\n provider google-ai\n retry_policy Constant\n options {\n model \"gemini-2.5-pro\"\n api_key env.GOOGLE_API_KEY\n generationConfig {\n thinkingConfig {\n thinkingBudget 1024\n includeThoughts true\n }\n }\n }\n}\n\nclient GeminiOpenAiGeneric {\n provider \"openai-generic\"\n options {\n base_url \"https://generativelanguage.googleapis.com/v1beta/\"\n model \"gemini-2.5-flash\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\nclient Vertex {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient VertexWithQueryParams {\n provider vertex-ai\n options {\n model gemini-2.5-flash\n location us-central1\n project_id gloo-ai\n query_params {\n key env.VERTEX_API_KEY\n }\n }\n}\n\nclient VertexClaude {\n provider vertex-ai\n options {\n model \"claude-3-5-sonnet@20240620\"\n location us-east5\n anthropic_version \"vertex-2023-10-16\"\n credentials env.INTEG_TESTS_GOOGLE_APPLICATION_CREDENTIALS_CONTENT\n }\n}\n\n\nclient AwsBedrock {\n provider aws-bedrock\n options {\n inference_configuration {\n max_tokens 2048\n }\n // max_tokens 100000\n // max_completion_tokens 100000\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model \"arn:aws:bedrock:us-east-1:404337120808:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0\"\n // region \"us-east-1\"\n // access_key_id env.AWS_ACCESS_KEY_ID\n // secret_access_key env.AWS_SECRET_ACCESS_KEY\n // session_token env.AWS_SESSION_TOKEN\n // session_token null\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidRegion {\n provider aws-bedrock\n options {\n region \"us-invalid-7\"\n inference_configuration {\n max_tokens 100\n }\n // model \"anthropic.claude-3-5-sonnet-20240620-v1:0\"\n // model_id \"anthropic.claude-3-haiku-20240307-v1:0\"\n model_id \"meta.llama3-8b-instruct-v1:0\"\n // model_id \"mistral.mistral-7b-instruct-v0:2\"\n }\n}\n\nclient AwsBedrockInvalidAccessKey {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidProfile {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n profile \"boundaryml-dev-invalid\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient AwsBedrockInvalidSessionToken {\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\n\nclient Invalid{\n provider aws-bedrock\n options {\n model_id \"meta.llama3-8b-instruct-v1:0\"\n region \"us-east-1\"\n access_key_id \"AKIAINVALID12345678\"\n secret_access_key \"abcdef1234567890abcdef1234567890abcdef12\"\n session_token \"invalid-session-token\"\n inference_configuration {\n max_tokens 100\n }\n }\n}\n\nclient Sonnet {\n provider anthropic\n options {\n model claude-3-5-sonnet-20241022\n api_key env.ANTHROPIC_API_KEY\n }\n}\n\n\nclient SonnetThinking {\n provider anthropic\n options {\n model \"claude-3-7-sonnet-20250219\"\n api_key env.ANTHROPIC_API_KEY\n max_tokens 2048\n thinking {\n type \"enabled\"\n budget_tokens 1024\n }\n }\n}\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient ClaudeWithCaching {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 500\n allowed_role_metadata [\"cache_control\"]\n headers {\n \"anthropic-beta\" \"prompt-caching-2024-07-31\"\n }\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n}\n\nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n Claude\n GPT35\n ]\n }\n}\n\nclient TogetherAi {\n provider \"openai-generic\"\n options {\n base_url \"https://api.together.ai/v1\"\n api_key env.TOGETHER_API_KEY\n model \"meta-llama/Llama-3-70b-chat-hf\"\n }\n}\n\n// OpenAI O1 client without max_tokens (should not add default)\nclient OpenAIO1 {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n }\n}\n\n// OpenAI O1 client with explicit max_tokens (should fail)\nclient OpenAIO1WithMaxTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// OpenAI O1 client with explicit max_completion_tokens\nclient OpenAIO1WithMaxCompletionTokens {\n provider openai\n options {\n model \"o1-mini\"\n api_key env.OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n\n// OpenAI GPT-4 client with explicit max_tokens\nclient GPT4WithMaxTokens {\n provider openai\n options {\n model \"gpt-4\"\n api_key env.OPENAI_API_KEY\n max_tokens 1000\n }\n}\n\n// Azure O3 client without max_tokens (should not add default)\nclient AzureO3 {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_tokens null\n }\n}\n\n// Azure O3 client with explicit max_completion_tokens\nclient AzureO3WithMaxCompletionTokens {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"o3-mini\"\n api_version \"2024-08-01-preview\"\n api_key env.AZURE_OPENAI_API_KEY\n max_completion_tokens 1000\n }\n}\n", "custom-task.baml": "class BookOrder {\n orderId string @description(#\"\n The ID of the book order\n \"#)\n title string @description(#\"\n The title of the ordered book\n \"#)\n quantity int @description(#\"\n The quantity of books ordered\n \"#)\n price float @description(#\"\n The price of the book\n \"#)\n}\n\nclass FlightConfirmation {\n confirmationNumber string @description(#\"\n The flight confirmation number\n \"#)\n flightNumber string @description(#\"\n The flight number\n \"#)\n departureTime string @description(#\"\n The scheduled departure time of the flight\n \"#)\n arrivalTime string @description(#\"\n The scheduled arrival time of the flight\n \"#)\n seatNumber string @description(#\"\n The seat number assigned on the flight\n \"#)\n}\n\nclass GroceryReceipt {\n receiptId string @description(#\"\n The ID of the grocery receipt\n \"#)\n storeName string @description(#\"\n The name of the grocery store\n \"#)\n items (string | int | float)[] @description(#\"\n A list of items purchased. Each item consists of a name, quantity, and price.\n \"#)\n totalAmount float @description(#\"\n The total amount spent on groceries\n \"#)\n}\n \nclass CustomTaskResult {\n bookOrder BookOrder | null\n flightConfirmation FlightConfirmation | null\n groceryReceipt GroceryReceipt | null\n}\n\nfunction CustomTask(input: string) -> BookOrder | FlightConfirmation | GroceryReceipt {\n client \"openai/gpt-4o-mini\"\n prompt #\"\n Given the input string, extract either an order for a book, a flight confirmation, or a grocery receipt.\n\n {{ ctx.output_format }}\n\n Input:\n \n {{ input}}\n \"#\n}\n\ntest CustomTask {\n functions [CustomTask]\n args {\n input #\"\nDear [Your Name],\n\nThank you for booking with [Airline Name]! We are pleased to confirm your upcoming flight.\n\nFlight Confirmation Details:\n\nBooking Reference: ABC123\nPassenger Name: [Your Name]\nFlight Number: XY789\nDeparture Date: September 15, 2024\nDeparture Time: 10:30 AM\nArrival Time: 1:45 PM\nDeparture Airport: John F. Kennedy International Airport (JFK), New York, NY\nArrival Airport: Los Angeles International Airport (LAX), Los Angeles, CA\nSeat Number: 12A\nClass: Economy\nBaggage Allowance:\n\nChecked Baggage: 1 piece, up to 23 kg\nCarry-On Baggage: 1 piece, up to 7 kg\nImportant Information:\n\nPlease arrive at the airport at least 2 hours before your scheduled departure.\nCheck-in online via our website or mobile app to save time at the airport.\nEnsure that your identification documents are up to date and match the name on your booking.\nContact Us:\n\nIf you have any questions or need to make changes to your booking, please contact our customer service team at 1-800-123-4567 or email us at support@[airline].com.\n\nWe wish you a pleasant journey and thank you for choosing [Airline Name].\n\nBest regards,\n\n[Airline Name] Customer Service\n \"#\n }\n}", "fiddle-examples/audio/audio.baml": "function DescribeAudio(audio: audio) -> string {\n client GPT4o\n prompt #\"\n Describe the audio below in 20 words:\n {{ _.role(\"user\") }}\n {{ audio }}\n \"#\n\n}\n\n\n\n\n// chat role user present\nfunction DescribeAudio2(audio: audio) -> string {\n client GPT4Turbo\n prompt #\"\n {{ _.role(\"user\") }}\n You should return 1 answer that answer the following command.\n\n Describe this in 5 words:\n {{ audio }}\n \"#\n}\n\ntest TestAudio {\n functions [DescribeAudio]\n args {\n audio { url \"https://www.pacdv.com/sounds/voices/friday-rocks.wav\"}\n }\n}\n\ntest TestAudio2 {\n functions [DescribeAudio2]\n args {\n audio { file \"friday-rocks.wav\" }\n }\n}\n", "fiddle-examples/chain-of-thought.baml": "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", diff --git a/integ-tests/typescript/package.json b/integ-tests/typescript/package.json index 07660ec61a..9f35886539 100644 --- a/integ-tests/typescript/package.json +++ b/integ-tests/typescript/package.json @@ -34,9 +34,15 @@ }, "dependencies": { "@anthropic-ai/sdk": "0.39.0", + "@aws-crypto/sha256-js": "^5.2.0", "@aws-sdk/client-sts": "3.721.0", + "@aws-sdk/credential-providers": "3.830.0", "@boundaryml/baml": "workspace:*", "@google/generative-ai": "0.24.0", + "@smithy/hash-node": "^4.1.1", + "@smithy/protocol-http": "^5.2.1", + "@smithy/signature-v4": "^5.2.1", + "@smithy/types": "^4.5.0", "dotenv": "16.4.5", "esbuild": "0.25.2", "openai": "4.87.3" diff --git a/integ-tests/typescript/tests/modular.test.ts b/integ-tests/typescript/tests/modular.test.ts index d7946b880d..47c1dd8ce7 100644 --- a/integ-tests/typescript/tests/modular.test.ts +++ b/integ-tests/typescript/tests/modular.test.ts @@ -9,10 +9,18 @@ import { GenerateContentRequest, GoogleGenerativeAI, } from "@google/generative-ai"; +import { SignatureV4 } from "@smithy/signature-v4"; +import { fromEnv } from "@aws-sdk/credential-providers"; +import { HttpRequest } from "@smithy/protocol-http"; +import { Sha256 } from "@aws-crypto/sha256-js"; import { HTTPRequest as BamlHttpRequest } from "@boundaryml/baml"; import { Resume } from "../baml_client/types"; import { b, ClientRegistry } from "./test-setup"; +const LONG_CACHEABLE_CONTEXT = Array.from({ length: 600 }) + .map(() => "Reusable cacheable context paragraph.") + .join(" "); + const JOHN_DOE_TEXT_RESUME = ` John Doe johndoe@example.com @@ -271,7 +279,7 @@ describe("Modular API Tests", () => { const req = await b.request.TestOpenAIResponses("mountains"); // The openai-responses provider should use the /v1/responses endpoint - const res = await client.responses.create(req.body.json()) as any; + const res = (await client.responses.create(req.body.json())) as any; // Parse the response from the responses API (uses output_text instead of choices) const parsed = b.parse.TestOpenAIResponses(res.output_text); @@ -279,4 +287,89 @@ describe("Modular API Tests", () => { expect(typeof parsed).toBe("string"); expect(parsed.length).toBeGreaterThan(0); }); + + it("modular aws bedrock custom cache point", async () => { + const req = await b.request.TestAws("Dr. Pepper"); + + const body = req.body.json() as any; + expect(Array.isArray(body.messages)).toBe(true); + expect(body.messages.length).toBeGreaterThan(0); + + const content = body.messages[0].content as any[]; + expect(Array.isArray(content)).toBe(true); + + const originalLength = content.length; + content.splice(1, 0, { text: LONG_CACHEABLE_CONTEXT }); + content.splice(2, 0, { cachePoint: { type: "default" } }); + + expect(content[1]).toEqual({ text: LONG_CACHEABLE_CONTEXT }); + expect(content[2]).toEqual({ cachePoint: { type: "default" } }); + expect(content.length).toBe(originalLength + 2); + + body.additionalModelRequestFields = { + ...(body.additionalModelRequestFields ?? {}), + }; + + const bodyString = JSON.stringify(body); + const url = new URL(req.url); + const region = + process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? "us-east-1"; + + const signer = new SignatureV4({ + service: "bedrock", + region, + credentials: fromEnv(), + sha256: Sha256, + }); + + const baseHeaders = Object.fromEntries( + Object.entries(req.headers as Record).filter( + ([, value]) => value !== undefined, + ), + ) as Record; + + const headers = { + ...baseHeaders, + host: url.host, + "content-type": "application/json", + accept: "application/json", + }; + + const unsigned = new HttpRequest({ + protocol: url.protocol, + hostname: url.hostname, + path: url.pathname, + method: req.method, + headers, + body: bodyString, + }); + + const signed = await signer.sign(unsigned); + const signedHeaders = Object.fromEntries( + Object.entries(signed.headers).map(([key, value]) => [ + key, + String(value), + ]), + ) as Record; + + const res = await fetch(req.url, { + method: req.method, + headers: signedHeaders, + body: bodyString, + }); + + if (!res.ok) { + throw new Error( + `Bedrock request failed: ${res.status} ${await res.text()}`, + ); + } + + const payload = (await res.json()) as any; + const contentBlocks = payload?.output?.message?.content ?? []; + expect(Array.isArray(contentBlocks)).toBe(true); + const textBlock = + contentBlocks.find((block: any) => block.text)?.text ?? ""; + expect(typeof textBlock).toBe("string"); + expect(textBlock.length).toBeGreaterThan(0); + }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index df139e6f74..8354fa9740 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -88,7 +88,7 @@ importers: version: 6.2.6 ts-jest: specifier: ^29.1.1 - version: 29.4.0(@babel/core@7.27.7)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@29.7.0(@babel/core@7.27.7))(jest-util@30.0.2)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.7)(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3) + version: 29.4.0(@babel/core@7.28.0)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@29.7.0(@babel/core@7.28.0))(jest-util@30.0.2)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.7)(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3) ts-node: specifier: ^10.9.2 version: 10.9.2(@swc/core@1.12.7)(@types/node@20.19.1)(typescript@5.8.3) @@ -263,15 +263,33 @@ importers: '@anthropic-ai/sdk': specifier: 0.39.0 version: 0.39.0 + '@aws-crypto/sha256-js': + specifier: ^5.2.0 + version: 5.2.0 '@aws-sdk/client-sts': specifier: 3.721.0 version: 3.721.0 + '@aws-sdk/credential-providers': + specifier: 3.830.0 + version: 3.830.0 '@boundaryml/baml': specifier: workspace:* version: link:../../engine/language_client_typescript '@google/generative-ai': specifier: 0.24.0 version: 0.24.0 + '@smithy/hash-node': + specifier: ^4.1.1 + version: 4.1.1 + '@smithy/protocol-http': + specifier: ^5.2.1 + version: 5.2.1 + '@smithy/signature-v4': + specifier: ^5.2.1 + version: 5.2.1 + '@smithy/types': + specifier: ^4.5.0 + version: 4.5.0 dotenv: specifier: 16.4.5 version: 16.4.5 @@ -311,7 +329,7 @@ importers: version: 0.0.2 ts-jest: specifier: 29.1.2 - version: 29.1.2(@babel/core@7.28.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.0))(esbuild@0.25.2)(jest@29.7.0(@types/node@20.17.17)(ts-node@10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.15))(@types/node@20.17.17)(typescript@5.4.2)))(typescript@5.4.2) + version: 29.1.2(@babel/core@7.27.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.7))(esbuild@0.25.2)(jest@29.7.0(@types/node@20.17.17)(ts-node@10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.15))(@types/node@20.17.17)(typescript@5.4.2)))(typescript@5.4.2) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.15))(@types/node@20.17.17)(typescript@5.4.2) @@ -403,16 +421,16 @@ importers: version: 15.5.13 css-loader: specifier: ^7.1.2 - version: 7.1.2(webpack@5.99.9) + version: 7.1.2(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)) jotai-devtools: specifier: 0.12.0 version: 0.12.0(@types/react@19.1.9)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(redux@5.0.1)(storybook@8.6.14) style-loader: specifier: ^4.0.0 - version: 4.0.0(webpack@5.99.9) + version: 4.0.0(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)) ts-loader: specifier: ^9.4.0 - version: 9.5.2(typescript@5.8.3)(webpack@5.99.9) + version: 9.5.2(typescript@5.8.3)(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)) typescript: specifier: ^5.0.0 version: 5.8.3 @@ -4799,8 +4817,8 @@ packages: resolution: {integrity: sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA==} engines: {node: '>=16.0.0'} - '@smithy/hash-node@4.0.4': - resolution: {integrity: sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==} + '@smithy/hash-node@4.1.1': + resolution: {integrity: sha512-H9DIU9WBLhYrvPs9v4sYvnZ1PiAI0oc8CgNQUJ1rpN3pP7QADbTOUjchI2FB764Ub0DstH5xbTqcMJu1pnVqxA==} engines: {node: '>=18.0.0'} '@smithy/invalid-dependency@3.0.11': @@ -4818,8 +4836,8 @@ packages: resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==} engines: {node: '>=16.0.0'} - '@smithy/is-array-buffer@4.0.0': - resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==} + '@smithy/is-array-buffer@4.1.0': + resolution: {integrity: sha512-ePTYUOV54wMogio+he4pBybe8fwg4sDvEVDBU8ZlHOZXbXK3/C0XfJgUCu6qAZcawv05ZhZzODGUerFBPsPUDQ==} engines: {node: '>=18.0.0'} '@smithy/middleware-content-length@3.0.13': @@ -4890,8 +4908,8 @@ packages: resolution: {integrity: sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==} engines: {node: '>=16.0.0'} - '@smithy/protocol-http@5.1.2': - resolution: {integrity: sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==} + '@smithy/protocol-http@5.2.1': + resolution: {integrity: sha512-T8SlkLYCwfT/6m33SIU/JOVGNwoelkrvGjFKDSDtVvAXj/9gOT78JVJEas5a+ETjOu4SVvpCstKgd0PxSu/aHw==} engines: {node: '>=18.0.0'} '@smithy/querystring-builder@3.0.11': @@ -4930,8 +4948,8 @@ packages: resolution: {integrity: sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==} engines: {node: '>=16.0.0'} - '@smithy/signature-v4@5.1.2': - resolution: {integrity: sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==} + '@smithy/signature-v4@5.2.1': + resolution: {integrity: sha512-M9rZhWQLjlQVCCR37cSjHfhriGRN+FQ8UfgrYNufv66TJgk+acaggShl3KS5U/ssxivvZLlnj7QH2CUOKlxPyA==} engines: {node: '>=18.0.0'} '@smithy/smithy-client@3.7.0': @@ -4950,6 +4968,10 @@ packages: resolution: {integrity: sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==} engines: {node: '>=18.0.0'} + '@smithy/types@4.5.0': + resolution: {integrity: sha512-RkUpIOsVlAwUIZXO1dsz8Zm+N72LClFfsNqf173catVlvRZiwPy0x2u0JLEA4byreOPKDZPGjmPDylMoP8ZJRg==} + engines: {node: '>=18.0.0'} + '@smithy/url-parser@3.0.11': resolution: {integrity: sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==} @@ -4988,8 +5010,8 @@ packages: resolution: {integrity: sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==} engines: {node: '>=16.0.0'} - '@smithy/util-buffer-from@4.0.0': - resolution: {integrity: sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==} + '@smithy/util-buffer-from@4.1.0': + resolution: {integrity: sha512-N6yXcjfe/E+xKEccWEKzK6M+crMrlwaCepKja0pNnlSkm6SjAeLKKA++er5Ba0I17gvKfN/ThV+ZOx/CntKTVw==} engines: {node: '>=18.0.0'} '@smithy/util-config-provider@3.0.0': @@ -5028,16 +5050,16 @@ packages: resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==} engines: {node: '>=16.0.0'} - '@smithy/util-hex-encoding@4.0.0': - resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==} + '@smithy/util-hex-encoding@4.1.0': + resolution: {integrity: sha512-1LcueNN5GYC4tr8mo14yVYbh/Ur8jHhWOxniZXii+1+ePiIbsLZ5fEI0QQGtbRRP5mOhmooos+rLmVASGGoq5w==} engines: {node: '>=18.0.0'} '@smithy/util-middleware@3.0.11': resolution: {integrity: sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==} engines: {node: '>=16.0.0'} - '@smithy/util-middleware@4.0.4': - resolution: {integrity: sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==} + '@smithy/util-middleware@4.1.1': + resolution: {integrity: sha512-CGmZ72mL29VMfESz7S6dekqzCh8ZISj3B+w0g1hZFXaOjGTVaSqfAEFAq8EGp8fUL+Q2l8aqNmt8U1tglTikeg==} engines: {node: '>=18.0.0'} '@smithy/util-retry@3.0.11': @@ -5060,8 +5082,8 @@ packages: resolution: {integrity: sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==} engines: {node: '>=16.0.0'} - '@smithy/util-uri-escape@4.0.0': - resolution: {integrity: sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==} + '@smithy/util-uri-escape@4.1.0': + resolution: {integrity: sha512-b0EFQkq35K5NHUYxU72JuoheM6+pytEVUGlTwiFxWFpmddA+Bpz3LgsPRIpBk8lnPE47yT7AF2Egc3jVnKLuPg==} engines: {node: '>=18.0.0'} '@smithy/util-utf8@2.3.0': @@ -5072,8 +5094,8 @@ packages: resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} engines: {node: '>=16.0.0'} - '@smithy/util-utf8@4.0.0': - resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==} + '@smithy/util-utf8@4.1.0': + resolution: {integrity: sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ==} engines: {node: '>=18.0.0'} '@standard-schema/utils@0.3.0': @@ -10709,7 +10731,7 @@ packages: react-markdown@10.1.0: resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} peerDependencies: - '@types/react': '>=18' + '@types/react': 19.0.8 react: '>=18' react-markdown@9.1.0: @@ -12939,7 +12961,7 @@ snapshots: '@smithy/config-resolver': 4.1.4 '@smithy/core': 3.6.0 '@smithy/fetch-http-handler': 5.0.4 - '@smithy/hash-node': 4.0.4 + '@smithy/hash-node': 4.1.1 '@smithy/invalid-dependency': 4.0.4 '@smithy/middleware-content-length': 4.0.4 '@smithy/middleware-endpoint': 4.1.13 @@ -12948,9 +12970,9 @@ snapshots: '@smithy/middleware-stack': 4.0.4 '@smithy/node-config-provider': 4.1.3 '@smithy/node-http-handler': 4.0.6 - '@smithy/protocol-http': 5.1.2 + '@smithy/protocol-http': 5.2.1 '@smithy/smithy-client': 4.4.5 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 @@ -12958,9 +12980,9 @@ snapshots: '@smithy/util-defaults-mode-browser': 4.0.21 '@smithy/util-defaults-mode-node': 4.0.21 '@smithy/util-endpoints': 3.0.6 - '@smithy/util-middleware': 4.0.4 + '@smithy/util-middleware': 4.1.1 '@smithy/util-retry': 4.0.6 - '@smithy/util-utf8': 4.0.0 + '@smithy/util-utf8': 4.1.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13070,7 +13092,7 @@ snapshots: '@smithy/config-resolver': 4.1.4 '@smithy/core': 3.6.0 '@smithy/fetch-http-handler': 5.0.4 - '@smithy/hash-node': 4.0.4 + '@smithy/hash-node': 4.1.1 '@smithy/invalid-dependency': 4.0.4 '@smithy/middleware-content-length': 4.0.4 '@smithy/middleware-endpoint': 4.1.13 @@ -13079,9 +13101,9 @@ snapshots: '@smithy/middleware-stack': 4.0.4 '@smithy/node-config-provider': 4.1.3 '@smithy/node-http-handler': 4.0.6 - '@smithy/protocol-http': 5.1.2 + '@smithy/protocol-http': 5.2.1 '@smithy/smithy-client': 4.4.5 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 @@ -13089,9 +13111,9 @@ snapshots: '@smithy/util-defaults-mode-browser': 4.0.21 '@smithy/util-defaults-mode-node': 4.0.21 '@smithy/util-endpoints': 3.0.6 - '@smithy/util-middleware': 4.0.4 + '@smithy/util-middleware': 4.1.1 '@smithy/util-retry': 4.0.6 - '@smithy/util-utf8': 4.0.0 + '@smithy/util-utf8': 4.1.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13162,14 +13184,14 @@ snapshots: '@smithy/core': 3.6.0 '@smithy/node-config-provider': 4.1.3 '@smithy/property-provider': 4.0.4 - '@smithy/protocol-http': 5.1.2 - '@smithy/signature-v4': 5.1.2 + '@smithy/protocol-http': 5.2.1 + '@smithy/signature-v4': 5.2.1 '@smithy/smithy-client': 4.4.5 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 - '@smithy/util-middleware': 4.0.4 - '@smithy/util-utf8': 4.0.0 + '@smithy/util-middleware': 4.1.1 + '@smithy/util-utf8': 4.1.0 fast-xml-parser: 4.4.1 tslib: 2.8.1 @@ -13178,7 +13200,7 @@ snapshots: '@aws-sdk/client-cognito-identity': 3.830.0 '@aws-sdk/types': 3.821.0 '@smithy/property-provider': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13196,7 +13218,7 @@ snapshots: '@aws-sdk/core': 3.826.0 '@aws-sdk/types': 3.821.0 '@smithy/property-provider': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@aws-sdk/credential-provider-http@3.716.0': @@ -13219,9 +13241,9 @@ snapshots: '@smithy/fetch-http-handler': 5.0.4 '@smithy/node-http-handler': 4.0.6 '@smithy/property-provider': 4.0.4 - '@smithy/protocol-http': 5.1.2 + '@smithy/protocol-http': 5.2.1 '@smithy/smithy-client': 4.4.5 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/util-stream': 4.2.2 tslib: 2.8.1 @@ -13257,7 +13279,7 @@ snapshots: '@smithy/credential-provider-imds': 4.0.6 '@smithy/property-provider': 4.0.4 '@smithy/shared-ini-file-loader': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13293,7 +13315,7 @@ snapshots: '@smithy/credential-provider-imds': 4.0.6 '@smithy/property-provider': 4.0.4 '@smithy/shared-ini-file-loader': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13313,7 +13335,7 @@ snapshots: '@aws-sdk/types': 3.821.0 '@smithy/property-provider': 4.0.4 '@smithy/shared-ini-file-loader': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@aws-sdk/credential-provider-sso@3.721.0(@aws-sdk/client-sso-oidc@3.721.0(@aws-sdk/client-sts@3.721.0))': @@ -13338,7 +13360,7 @@ snapshots: '@aws-sdk/types': 3.821.0 '@smithy/property-provider': 4.0.4 '@smithy/shared-ini-file-loader': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13358,7 +13380,7 @@ snapshots: '@aws-sdk/nested-clients': 3.830.0 '@aws-sdk/types': 3.821.0 '@smithy/property-provider': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13382,7 +13404,7 @@ snapshots: '@smithy/credential-provider-imds': 4.0.6 '@smithy/node-config-provider': 4.1.3 '@smithy/property-provider': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13397,8 +13419,8 @@ snapshots: '@aws-sdk/middleware-host-header@3.821.0': dependencies: '@aws-sdk/types': 3.821.0 - '@smithy/protocol-http': 5.1.2 - '@smithy/types': 4.3.1 + '@smithy/protocol-http': 5.2.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@aws-sdk/middleware-logger@3.714.0': @@ -13410,7 +13432,7 @@ snapshots: '@aws-sdk/middleware-logger@3.821.0': dependencies: '@aws-sdk/types': 3.821.0 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@aws-sdk/middleware-recursion-detection@3.714.0': @@ -13423,8 +13445,8 @@ snapshots: '@aws-sdk/middleware-recursion-detection@3.821.0': dependencies: '@aws-sdk/types': 3.821.0 - '@smithy/protocol-http': 5.1.2 - '@smithy/types': 4.3.1 + '@smithy/protocol-http': 5.2.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@aws-sdk/middleware-user-agent@3.721.0': @@ -13443,8 +13465,8 @@ snapshots: '@aws-sdk/types': 3.821.0 '@aws-sdk/util-endpoints': 3.828.0 '@smithy/core': 3.6.0 - '@smithy/protocol-http': 5.1.2 - '@smithy/types': 4.3.1 + '@smithy/protocol-http': 5.2.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@aws-sdk/nested-clients@3.830.0': @@ -13464,7 +13486,7 @@ snapshots: '@smithy/config-resolver': 4.1.4 '@smithy/core': 3.6.0 '@smithy/fetch-http-handler': 5.0.4 - '@smithy/hash-node': 4.0.4 + '@smithy/hash-node': 4.1.1 '@smithy/invalid-dependency': 4.0.4 '@smithy/middleware-content-length': 4.0.4 '@smithy/middleware-endpoint': 4.1.13 @@ -13473,9 +13495,9 @@ snapshots: '@smithy/middleware-stack': 4.0.4 '@smithy/node-config-provider': 4.1.3 '@smithy/node-http-handler': 4.0.6 - '@smithy/protocol-http': 5.1.2 + '@smithy/protocol-http': 5.2.1 '@smithy/smithy-client': 4.4.5 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 @@ -13483,9 +13505,9 @@ snapshots: '@smithy/util-defaults-mode-browser': 4.0.21 '@smithy/util-defaults-mode-node': 4.0.21 '@smithy/util-endpoints': 3.0.6 - '@smithy/util-middleware': 4.0.4 + '@smithy/util-middleware': 4.1.1 '@smithy/util-retry': 4.0.6 - '@smithy/util-utf8': 4.0.0 + '@smithy/util-utf8': 4.1.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13503,9 +13525,9 @@ snapshots: dependencies: '@aws-sdk/types': 3.821.0 '@smithy/node-config-provider': 4.1.3 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/util-config-provider': 4.0.0 - '@smithy/util-middleware': 4.0.4 + '@smithy/util-middleware': 4.1.1 tslib: 2.8.1 '@aws-sdk/token-providers@3.721.0(@aws-sdk/client-sso-oidc@3.721.0(@aws-sdk/client-sts@3.721.0))': @@ -13524,7 +13546,7 @@ snapshots: '@aws-sdk/types': 3.821.0 '@smithy/property-provider': 4.0.4 '@smithy/shared-ini-file-loader': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -13536,7 +13558,7 @@ snapshots: '@aws-sdk/types@3.821.0': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@aws-sdk/util-endpoints@3.714.0': @@ -13549,7 +13571,7 @@ snapshots: '@aws-sdk/util-endpoints@3.828.0': dependencies: '@aws-sdk/types': 3.821.0 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/util-endpoints': 3.0.6 tslib: 2.8.1 @@ -13567,7 +13589,7 @@ snapshots: '@aws-sdk/util-user-agent-browser@3.821.0': dependencies: '@aws-sdk/types': 3.821.0 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 bowser: 2.11.0 tslib: 2.8.1 @@ -13584,12 +13606,12 @@ snapshots: '@aws-sdk/middleware-user-agent': 3.828.0 '@aws-sdk/types': 3.821.0 '@smithy/node-config-provider': 4.1.3 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@aws-sdk/xml-builder@3.821.0': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@azu/format-text@1.0.2': {} @@ -17206,7 +17228,7 @@ snapshots: '@smithy/abort-controller@4.0.4': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/config-resolver@3.0.13': @@ -17220,9 +17242,9 @@ snapshots: '@smithy/config-resolver@4.1.4': dependencies: '@smithy/node-config-provider': 4.1.3 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/util-config-provider': 4.0.0 - '@smithy/util-middleware': 4.0.4 + '@smithy/util-middleware': 4.1.1 tslib: 2.8.1 '@smithy/core@2.5.7': @@ -17239,13 +17261,13 @@ snapshots: '@smithy/core@3.6.0': dependencies: '@smithy/middleware-serde': 4.0.8 - '@smithy/protocol-http': 5.1.2 - '@smithy/types': 4.3.1 + '@smithy/protocol-http': 5.2.1 + '@smithy/types': 4.5.0 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 - '@smithy/util-middleware': 4.0.4 + '@smithy/util-middleware': 4.1.1 '@smithy/util-stream': 4.2.2 - '@smithy/util-utf8': 4.0.0 + '@smithy/util-utf8': 4.1.0 tslib: 2.8.1 '@smithy/credential-provider-imds@3.2.8': @@ -17260,7 +17282,7 @@ snapshots: dependencies: '@smithy/node-config-provider': 4.1.3 '@smithy/property-provider': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/url-parser': 4.0.4 tslib: 2.8.1 @@ -17274,9 +17296,9 @@ snapshots: '@smithy/fetch-http-handler@5.0.4': dependencies: - '@smithy/protocol-http': 5.1.2 + '@smithy/protocol-http': 5.2.1 '@smithy/querystring-builder': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/util-base64': 4.0.0 tslib: 2.8.1 @@ -17287,11 +17309,11 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/hash-node@4.0.4': + '@smithy/hash-node@4.1.1': dependencies: - '@smithy/types': 4.3.1 - '@smithy/util-buffer-from': 4.0.0 - '@smithy/util-utf8': 4.0.0 + '@smithy/types': 4.5.0 + '@smithy/util-buffer-from': 4.1.0 + '@smithy/util-utf8': 4.1.0 tslib: 2.8.1 '@smithy/invalid-dependency@3.0.11': @@ -17301,7 +17323,7 @@ snapshots: '@smithy/invalid-dependency@4.0.4': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': @@ -17312,7 +17334,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/is-array-buffer@4.0.0': + '@smithy/is-array-buffer@4.1.0': dependencies: tslib: 2.8.1 @@ -17324,8 +17346,8 @@ snapshots: '@smithy/middleware-content-length@4.0.4': dependencies: - '@smithy/protocol-http': 5.1.2 - '@smithy/types': 4.3.1 + '@smithy/protocol-http': 5.2.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/middleware-endpoint@3.2.8': @@ -17345,9 +17367,9 @@ snapshots: '@smithy/middleware-serde': 4.0.8 '@smithy/node-config-provider': 4.1.3 '@smithy/shared-ini-file-loader': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/url-parser': 4.0.4 - '@smithy/util-middleware': 4.0.4 + '@smithy/util-middleware': 4.1.1 tslib: 2.8.1 '@smithy/middleware-retry@3.0.34': @@ -17365,11 +17387,11 @@ snapshots: '@smithy/middleware-retry@4.1.14': dependencies: '@smithy/node-config-provider': 4.1.3 - '@smithy/protocol-http': 5.1.2 + '@smithy/protocol-http': 5.2.1 '@smithy/service-error-classification': 4.0.6 '@smithy/smithy-client': 4.4.5 - '@smithy/types': 4.3.1 - '@smithy/util-middleware': 4.0.4 + '@smithy/types': 4.5.0 + '@smithy/util-middleware': 4.1.1 '@smithy/util-retry': 4.0.6 tslib: 2.8.1 uuid: 9.0.1 @@ -17381,8 +17403,8 @@ snapshots: '@smithy/middleware-serde@4.0.8': dependencies: - '@smithy/protocol-http': 5.1.2 - '@smithy/types': 4.3.1 + '@smithy/protocol-http': 5.2.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/middleware-stack@3.0.11': @@ -17392,7 +17414,7 @@ snapshots: '@smithy/middleware-stack@4.0.4': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/node-config-provider@3.1.12': @@ -17406,7 +17428,7 @@ snapshots: dependencies: '@smithy/property-provider': 4.0.4 '@smithy/shared-ini-file-loader': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/node-http-handler@3.3.3': @@ -17420,9 +17442,9 @@ snapshots: '@smithy/node-http-handler@4.0.6': dependencies: '@smithy/abort-controller': 4.0.4 - '@smithy/protocol-http': 5.1.2 + '@smithy/protocol-http': 5.2.1 '@smithy/querystring-builder': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/property-provider@3.1.11': @@ -17432,7 +17454,7 @@ snapshots: '@smithy/property-provider@4.0.4': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/protocol-http@4.1.8': @@ -17440,9 +17462,9 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/protocol-http@5.1.2': + '@smithy/protocol-http@5.2.1': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/querystring-builder@3.0.11': @@ -17453,8 +17475,8 @@ snapshots: '@smithy/querystring-builder@4.0.4': dependencies: - '@smithy/types': 4.3.1 - '@smithy/util-uri-escape': 4.0.0 + '@smithy/types': 4.5.0 + '@smithy/util-uri-escape': 4.1.0 tslib: 2.8.1 '@smithy/querystring-parser@3.0.11': @@ -17464,7 +17486,7 @@ snapshots: '@smithy/querystring-parser@4.0.4': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/service-error-classification@3.0.11': @@ -17473,7 +17495,7 @@ snapshots: '@smithy/service-error-classification@4.0.6': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/shared-ini-file-loader@3.1.12': dependencies: @@ -17482,7 +17504,7 @@ snapshots: '@smithy/shared-ini-file-loader@4.0.4': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/signature-v4@4.2.4': @@ -17496,15 +17518,15 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/signature-v4@5.1.2': + '@smithy/signature-v4@5.2.1': dependencies: - '@smithy/is-array-buffer': 4.0.0 - '@smithy/protocol-http': 5.1.2 - '@smithy/types': 4.3.1 - '@smithy/util-hex-encoding': 4.0.0 - '@smithy/util-middleware': 4.0.4 - '@smithy/util-uri-escape': 4.0.0 - '@smithy/util-utf8': 4.0.0 + '@smithy/is-array-buffer': 4.1.0 + '@smithy/protocol-http': 5.2.1 + '@smithy/types': 4.5.0 + '@smithy/util-hex-encoding': 4.1.0 + '@smithy/util-middleware': 4.1.1 + '@smithy/util-uri-escape': 4.1.0 + '@smithy/util-utf8': 4.1.0 tslib: 2.8.1 '@smithy/smithy-client@3.7.0': @@ -17522,8 +17544,8 @@ snapshots: '@smithy/core': 3.6.0 '@smithy/middleware-endpoint': 4.1.13 '@smithy/middleware-stack': 4.0.4 - '@smithy/protocol-http': 5.1.2 - '@smithy/types': 4.3.1 + '@smithy/protocol-http': 5.2.1 + '@smithy/types': 4.5.0 '@smithy/util-stream': 4.2.2 tslib: 2.8.1 @@ -17535,6 +17557,10 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/types@4.5.0': + dependencies: + tslib: 2.8.1 + '@smithy/url-parser@3.0.11': dependencies: '@smithy/querystring-parser': 3.0.11 @@ -17544,7 +17570,7 @@ snapshots: '@smithy/url-parser@4.0.4': dependencies: '@smithy/querystring-parser': 4.0.4 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/util-base64@3.0.0': @@ -17555,8 +17581,8 @@ snapshots: '@smithy/util-base64@4.0.0': dependencies: - '@smithy/util-buffer-from': 4.0.0 - '@smithy/util-utf8': 4.0.0 + '@smithy/util-buffer-from': 4.1.0 + '@smithy/util-utf8': 4.1.0 tslib: 2.8.1 '@smithy/util-body-length-browser@3.0.0': @@ -17585,9 +17611,9 @@ snapshots: '@smithy/is-array-buffer': 3.0.0 tslib: 2.8.1 - '@smithy/util-buffer-from@4.0.0': + '@smithy/util-buffer-from@4.1.0': dependencies: - '@smithy/is-array-buffer': 4.0.0 + '@smithy/is-array-buffer': 4.1.0 tslib: 2.8.1 '@smithy/util-config-provider@3.0.0': @@ -17610,7 +17636,7 @@ snapshots: dependencies: '@smithy/property-provider': 4.0.4 '@smithy/smithy-client': 4.4.5 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 bowser: 2.11.0 tslib: 2.8.1 @@ -17631,7 +17657,7 @@ snapshots: '@smithy/node-config-provider': 4.1.3 '@smithy/property-provider': 4.0.4 '@smithy/smithy-client': 4.4.5 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/util-endpoints@2.1.7': @@ -17643,14 +17669,14 @@ snapshots: '@smithy/util-endpoints@3.0.6': dependencies: '@smithy/node-config-provider': 4.1.3 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/util-hex-encoding@3.0.0': dependencies: tslib: 2.8.1 - '@smithy/util-hex-encoding@4.0.0': + '@smithy/util-hex-encoding@4.1.0': dependencies: tslib: 2.8.1 @@ -17659,9 +17685,9 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/util-middleware@4.0.4': + '@smithy/util-middleware@4.1.1': dependencies: - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/util-retry@3.0.11': @@ -17673,7 +17699,7 @@ snapshots: '@smithy/util-retry@4.0.6': dependencies: '@smithy/service-error-classification': 4.0.6 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 tslib: 2.8.1 '@smithy/util-stream@3.3.4': @@ -17691,18 +17717,18 @@ snapshots: dependencies: '@smithy/fetch-http-handler': 5.0.4 '@smithy/node-http-handler': 4.0.6 - '@smithy/types': 4.3.1 + '@smithy/types': 4.5.0 '@smithy/util-base64': 4.0.0 - '@smithy/util-buffer-from': 4.0.0 - '@smithy/util-hex-encoding': 4.0.0 - '@smithy/util-utf8': 4.0.0 + '@smithy/util-buffer-from': 4.1.0 + '@smithy/util-hex-encoding': 4.1.0 + '@smithy/util-utf8': 4.1.0 tslib: 2.8.1 '@smithy/util-uri-escape@3.0.0': dependencies: tslib: 2.8.1 - '@smithy/util-uri-escape@4.0.0': + '@smithy/util-uri-escape@4.1.0': dependencies: tslib: 2.8.1 @@ -17716,9 +17742,9 @@ snapshots: '@smithy/util-buffer-from': 3.0.0 tslib: 2.8.1 - '@smithy/util-utf8@4.0.0': + '@smithy/util-utf8@4.1.0': dependencies: - '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-buffer-from': 4.1.0 tslib: 2.8.1 '@standard-schema/utils@0.3.0': {} @@ -19113,17 +19139,17 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.99.9)': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack@5.99.9))(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4))': dependencies: webpack: 5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.99.9) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.99.9)': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack@5.99.9))(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4))': dependencies: webpack: 5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.99.9) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.99.9)': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack@5.99.9))(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4))': dependencies: webpack: 5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.99.9) @@ -20091,7 +20117,7 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-loader@7.1.2(webpack@5.99.9): + css-loader@7.1.2(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)): dependencies: icss-utils: 5.1.0(postcss@8.5.6) postcss: 8.5.6 @@ -25802,7 +25828,7 @@ snapshots: dependencies: boundary: 2.0.0 - style-loader@4.0.0(webpack@5.99.9): + style-loader@4.0.0(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)): dependencies: webpack: 5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4) @@ -25973,7 +25999,7 @@ snapshots: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - terser-webpack-plugin@5.3.14(@swc/core@1.12.7)(esbuild@0.25.2)(webpack@5.99.9): + terser-webpack-plugin@5.3.14(@swc/core@1.12.7)(esbuild@0.25.2)(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.29 jest-worker: 27.5.1 @@ -26109,7 +26135,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.1.2(@babel/core@7.28.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.0))(esbuild@0.25.2)(jest@29.7.0(@types/node@20.17.17)(ts-node@10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.15))(@types/node@20.17.17)(typescript@5.4.2)))(typescript@5.4.2): + ts-jest@29.1.2(@babel/core@7.27.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.7))(esbuild@0.25.2)(jest@29.7.0(@types/node@20.17.17)(ts-node@10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.15))(@types/node@20.17.17)(typescript@5.4.2)))(typescript@5.4.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -26122,12 +26148,12 @@ snapshots: typescript: 5.4.2 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.27.7 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.28.0) + babel-jest: 29.7.0(@babel/core@7.27.7) esbuild: 0.25.2 - ts-jest@29.4.0(@babel/core@7.27.7)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@29.7.0(@babel/core@7.27.7))(jest-util@30.0.2)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.7)(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3): + ts-jest@29.4.0(@babel/core@7.28.0)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@29.7.0(@babel/core@7.28.0))(jest-util@30.0.2)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.7)(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -26141,10 +26167,10 @@ snapshots: typescript: 5.8.3 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.27.7 + '@babel/core': 7.28.0 '@jest/transform': 30.0.2 '@jest/types': 30.0.1 - babel-jest: 29.7.0(@babel/core@7.27.7) + babel-jest: 29.7.0(@babel/core@7.28.0) jest-util: 30.0.2 ts-jest@29.4.0(@babel/core@7.28.0)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@29.7.0(@babel/core@7.28.0))(jest-util@30.0.2)(jest@29.7.0(@types/node@22.15.33)(ts-node@10.9.2(@swc/core@1.12.7)(@types/node@22.15.33)(typescript@5.8.3)))(typescript@5.8.3): @@ -26167,7 +26193,7 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.28.0) jest-util: 30.0.2 - ts-loader@9.5.2(typescript@5.8.3)(webpack@5.99.9): + ts-loader@9.5.2(typescript@5.8.3)(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)): dependencies: chalk: 4.1.2 enhanced-resolve: 5.18.2 @@ -27070,9 +27096,9 @@ snapshots: webpack-cli@5.1.4(webpack@5.99.9): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.99.9) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.99.9) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.99.9) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack@5.99.9))(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack@5.99.9))(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack@5.99.9))(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.6 @@ -27149,7 +27175,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.2 tapable: 2.2.2 - terser-webpack-plugin: 5.3.14(@swc/core@1.12.7)(esbuild@0.25.2)(webpack@5.99.9) + terser-webpack-plugin: 5.3.14(@swc/core@1.12.7)(esbuild@0.25.2)(webpack@5.99.9(@swc/core@1.12.7)(esbuild@0.25.2)(webpack-cli@5.1.4)) watchpack: 2.4.4 webpack-sources: 3.3.3 optionalDependencies: