Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
c72f82b
add multiple cloudflare tests and change bundling for the browser build
cpinn Jan 15, 2026
6606c48
remove support in nextjs
cpinn Jan 15, 2026
25c561c
updates
cpinn Jan 16, 2026
723dad2
add full matrix of compatibility
cpinn Jan 16, 2026
77ad12b
ensure all 4 environments are checked
cpinn Jan 16, 2026
58d2c4d
add back proper error, undo browser test changes
cpinn Jan 16, 2026
2826981
move templating with nunjucks out completely
cpinn Jan 16, 2026
c9cf36d
add integration tests adn builds
cpinn Jan 16, 2026
93aff8b
update tests
cpinn Jan 16, 2026
d94f4ce
update lockfile
cpinn Jan 16, 2026
51bb20b
Python trace scoring candidate (#1278)
CLowbrow Jan 21, 2026
617d9b7
bump python version (#1297)
CLowbrow Jan 21, 2026
12e4729
Merge branch 'main' into caitlin/remove-templating-optino
cpinn Jan 22, 2026
ef71ab2
Merge branch 'caitlin/externalize' into caitlin/remove-templating-optino
cpinn Jan 22, 2026
143beac
restore with caitlin/externalize branch changes
cpinn Jan 22, 2026
996cb10
move the template test
cpinn Jan 22, 2026
043ef44
remove isomorph change
cpinn Jan 22, 2026
6c23ceb
fix test
cpinn Jan 22, 2026
6f75589
cleanup renaming, new workflow for package
cpinn Jan 22, 2026
97282c5
fix package json and build
cpinn Jan 22, 2026
e48aa0c
changes to the plugin registration
cpinn Jan 22, 2026
5c3a9f7
template nunjucks update
cpinn Jan 22, 2026
28afda0
Merge branch 'caitlin/externalize' into caitlin/remove-templating-optino
cpinn Jan 23, 2026
5a0ba2f
update expected nunjucks failure message
cpinn Jan 23, 2026
084253d
update test expectation
cpinn Jan 23, 2026
da238cf
cleanup plugin registry
cpinn Jan 23, 2026
4c8921d
fix some of the test coverage and improve messaging in browser test
cpinn Jan 23, 2026
e3e9e04
remove bad package json setting
cpinn Jan 23, 2026
6d80c32
updates to registry
cpinn Jan 23, 2026
a0125b8
move templating test to integration
cpinn Jan 23, 2026
c65aa5f
keep smoke scenarios separate
cpinn Jan 23, 2026
63f3162
fix test run issue in workspace
cpinn Jan 24, 2026
659c317
fix makefile discovery
cpinn Jan 24, 2026
30d6de3
update test scenarios
cpinn Jan 24, 2026
809c0ec
test updates
cpinn Jan 26, 2026
1d98331
migrate integration tests to integration, fix scenario makefile
cpinn Jan 26, 2026
16c9c8b
fixes to new integration flow
cpinn Jan 26, 2026
d6ee005
fix nextjs, deno tests and attempt to re-use the existing template te…
cpinn Jan 26, 2026
11395fc
update from integrations/scenarios to integrations/smoke/scenarios
cpinn Jan 26, 2026
24eb2ae
deno is causing issues with obtaining the 3.0.0 package and is attemp…
cpinn Jan 26, 2026
4db121d
update makefiles for integration tests
cpinn Jan 26, 2026
8c270cb
deno update re-try
cpinn Jan 26, 2026
e37d662
clarify license behavior
cpinn Jan 27, 2026
f68b17d
deno testing
cpinn Jan 27, 2026
4545c79
fix package build
cpinn Jan 27, 2026
308b753
finally fix deno please
cpinn Jan 27, 2026
c01db42
update tarball path for deno
cpinn Jan 27, 2026
e315405
braintrust/browser package and use of async local storage in browser …
cpinn Jan 29, 2026
4da4b25
remove this leftover artifact
cpinn Jan 29, 2026
e435333
deno test was looking for the wrong version
cpinn Jan 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions .github/workflows/js.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ jobs:
PACKED_TARBALL=$(npm pack --pack-destination artifacts)
echo "packed_tarball=$PACKED_TARBALL" >> "$GITHUB_OUTPUT"

- name: Pack @braintrust/browser
id: prepare_browser_artifact
working-directory: integrations/browser-js
shell: bash
run: |
PACKED_BROWSER_TARBALL=$(npm pack --pack-destination ../../js/artifacts)
echo "packed_browser_tarball=$PACKED_BROWSER_TARBALL" >> "$GITHUB_OUTPUT"

- name: Build and pack @braintrust/otel
id: prepare_otel_artifact
shell: bash
Expand Down Expand Up @@ -89,11 +97,22 @@ jobs:
PACKED_OTEL_TARBALL=$(npm pack --pack-destination ../../js/artifacts)
echo "packed_otel_tarball=$PACKED_OTEL_TARBALL" >> "$GITHUB_OUTPUT"

- name: Build and pack @braintrust/templates-nunjucks
id: prepare_templates_nunjucks_artifact
shell: bash
run: |
cd integrations/templates-nunjucks
pnpm run build
PACKED_NUNJUCKS_TARBALL=$(npm pack --pack-destination ../../js/artifacts)
echo "packed_nunjucks_tarball=$PACKED_NUNJUCKS_TARBALL" >> "$GITHUB_OUTPUT"

- name: List artifacts before upload
shell: bash
run: |
echo "Braintrust tarball: ${{ steps.prepare_artifact.outputs.packed_tarball }}"
echo "Browser tarball: ${{ steps.prepare_browser_artifact.outputs.packed_browser_tarball }}"
echo "Otel tarball: ${{ steps.prepare_otel_artifact.outputs.packed_otel_tarball }}"
echo "Templates-nunjucks tarball: ${{ steps.prepare_templates_nunjucks_artifact.outputs.packed_nunjucks_tarball }}"
ls -la js/artifacts/

- name: Upload build artifacts
Expand All @@ -102,7 +121,9 @@ jobs:
name: ${{ steps.artifact.outputs.name }}-${{ matrix.node-version }}-dist
path: |
js/artifacts/${{ steps.prepare_artifact.outputs.packed_tarball }}
js/artifacts/${{ steps.prepare_browser_artifact.outputs.packed_browser_tarball }}
js/artifacts/${{ steps.prepare_otel_artifact.outputs.packed_otel_tarball }}
js/artifacts/${{ steps.prepare_templates_nunjucks_artifact.outputs.packed_nunjucks_tarball }}
retention-days: 1

api-compatibility:
Expand Down Expand Up @@ -210,8 +231,15 @@ jobs:
working-directory: js/smoke
shell: bash
run: |
# Use the same auto-discovery logic as the Makefile
SCENARIOS=$(command find scenarios -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Makefile \; -print | sed 's|scenarios/||' | sort | jq -R -s -c 'split("\n") | map(select(length > 0))')
echo "Discovering local and integration scenarios..."
SCRIPTDIR="../../integrations"
# Local scenarios (under js/smoke/scenarios): emit their directory names
LOCAL=$(find scenarios -mindepth 1 -maxdepth 1 -type d -exec test -f {}/Makefile \; -print | sed 's|scenarios/||' | tr '\n' ' ')
# Integration scenarios: emit as integration/name
INTEGRATIONS=$(find "$SCRIPTDIR" -type f -path '*/smoke/scenarios/*/Makefile' 2>/dev/null | sed "s|^$SCRIPTDIR/||" | sed 's|/Makefile$||' | sed 's|/smoke/scenarios/|/|' | tr '\n' ' ')
ALL="${LOCAL} ${INTEGRATIONS}"
# Convert space-separated list to JSON array
SCENARIOS=$(printf "%s\n" $ALL | jq -R -s -c 'split("\n") | map(select(length>0))')
echo "scenarios=$SCENARIOS" >> "$GITHUB_OUTPUT"
echo "Discovered scenarios: $SCENARIOS"

Expand Down Expand Up @@ -255,6 +283,15 @@ jobs:
fi
done

# Copy browser tarball to well-known path
for f in braintrust-browser-[0-9]*.tgz; do
if [ -f "$f" ]; then
cp "$f" braintrust-browser-latest.tgz
echo "Copied $f to braintrust-browser-latest.tgz"
break
fi
done

# Copy otel tarball to well-known path
for f in braintrust-otel-[0-9]*.tgz; do
if [ -f "$f" ]; then
Expand All @@ -264,6 +301,15 @@ jobs:
fi
done

# Copy templates-nunjucks-js tarball to well-known path
for f in braintrust-templates-nunjucks-js-[0-9]*.tgz; do
if [ -f "$f" ]; then
cp "$f" braintrust-templates-nunjucks-js-latest.tgz
echo "Copied $f to braintrust-templates-nunjucks-js-latest.tgz"
break
fi
done

- name: Build shared test package (once for all scenarios)
working-directory: js/smoke/shared
shell: bash
Expand All @@ -278,7 +324,9 @@ jobs:
BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }}
CI: true
BRAINTRUST_TAR: ../artifacts/braintrust-latest.tgz
BRAINTRUST_BROWSER_TAR: ../artifacts/braintrust-browser-latest.tgz
BRAINTRUST_OTEL_TAR: ../artifacts/braintrust-otel-latest.tgz
BRAINTRUST_TEMPLATES_NUNJUCKS_JS_TAR: ../artifacts/braintrust-templates-nunjucks-js-latest.tgz
SMOKE_V2_SHARED_DIST: shared/dist
run: |
make test ${{ matrix.scenario }}
46 changes: 46 additions & 0 deletions .github/workflows/templates-nunjucks-build-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: templates-nunjucks-js

on:
pull_request:
paths:
- "integrations/templates-nunjucks/**"
- "js/**"
- ".github/workflows/templates-nunjucks-build-test.yaml"
push:
branches: [main]
paths:
- "integrations/templates-nunjucks/**"
- "js/**"

jobs:
build-and-test:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
node-version: [20, 22]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}

- uses: pnpm/action-setup@v4

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build braintrust
working-directory: js
run: pnpm run build

- name: Build @braintrust/templates-nunjucks-js
working-directory: integrations/templates-nunjucks
run: pnpm run build

- name: Run @braintrust/templates-nunjucks-js tests
working-directory: integrations/templates-nunjucks
run: pnpm run test
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ js-build:
pnpm run build

js-test: js-build
pnpm run test
# Run tests only for the JS workspace packages and exclude integration scenario tests
pnpm --filter ./js... run test
cd js && make test

js-docs: js-build
Expand Down
75 changes: 75 additions & 0 deletions integrations/browser-js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Braintrust Browser SDK

Official browser-only SDK for [Braintrust](https://braintrust.dev).

This is an integration package that provides browser-optimized builds of the Braintrust SDK with AsyncLocalStorage polyfill support for standard browsers.

## Installation

```bash
npm install @braintrust/browser braintrust
# or
pnpm add @braintrust/browser braintrust
# or
yarn add @braintrust/browser braintrust
```

Note: `braintrust` is a peer dependency and must be installed alongside `@braintrust/browser`.

## Usage

```typescript
import * as braintrust from "@braintrust/browser";

const experiment = await braintrust.init("BrowserExperiment", {
apiKey: "YOUR_API_KEY",
});

// Use tracing in browser
const result = await braintrust.traced(
async () => {
// Your code here
return "result";
},
{ name: "myOperation" },
);
```

## Differences from Main Package

This package:

- **Includes** `als-browser` polyfill for AsyncLocalStorage (bundled)
- **Requires** `braintrust` as a peer dependency

## When to Use

Use `@braintrust/browser` when:

- Building browser-only applications
- Need AsyncLocalStorage support in standard browsers

Use `braintrust` directly when:

- Building Node.js applications
- Using in Next.js or other full-stack frameworks (with proper module resolution)
- Need CLI tools or filesystem access

## Features

All browser-compatible features from the main SDK:

- Logging and tracing
- Experiments and datasets
- Prompt management
- AI provider wrappers (OpenAI, Anthropic, Google)
- Evaluation framework
- OpenTelemetry integration

## Documentation

For full documentation, visit [https://www.braintrust.dev/docs](https://www.braintrust.dev/docs)

## License

Apache-2.0
58 changes: 58 additions & 0 deletions integrations/browser-js/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@braintrust/browser",
"version": "0.0.2",
"description": "Braintrust SDK for browser environments with AsyncLocalStorage polyfill",
"type": "module",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "tsup",
"watch": "tsup --watch",
"clean": "rm -rf dist",
"test": "vitest run"
},
"dependencies": {
"als-browser": "^1.0.1"
},
"devDependencies": {
"@types/node": "^20.10.5",
"braintrust": "workspace:*",
"tsup": "^8.3.5",
"typescript": "^5.3.3",
"vitest": "^2.1.9"
},
"peerDependencies": {
"braintrust": ">=3.0.0",
"zod": "^3.25.34 || ^4.0"
},
"peerDependenciesMeta": {
"braintrust": {
"optional": false
},
"zod": {
"optional": false
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/braintrustdata/braintrust-sdk.git",
"directory": "sdk/integrations/browser-js"
},
"homepage": "https://www.braintrust.dev/docs",
"license": "Apache-2.0",
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
}
}
48 changes: 48 additions & 0 deletions integrations/browser-js/src/browser-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { _internalIso as iso, _internalSetInitialState } from "braintrust";
import { AsyncLocalStorage as BrowserAsyncLocalStorage } from "als-browser";

let browserConfigured = false;

export function configureBrowser() {
if (browserConfigured) {
return;
}

// Set build type indicator
iso.buildType = "browser";

iso.newAsyncLocalStorage = <T>() => new BrowserAsyncLocalStorage<T>();

iso.getEnv = (name: string) => {
if (typeof process === "undefined" || typeof process.env === "undefined") {
return undefined;
}
return process.env[name];
};

// noop implementations for git config
iso.getRepoInfo = async () => ({
commit: null,
branch: null,
tag: null,
dirty: false,
});
iso.getCallerLocation = () => undefined;

// Implement browser-compatible hash function using a simple hash algorithm
iso.hash = (data: string): string => {
// Simple hash function for browser compatibility
let hash = 0;
for (let i = 0; i < data.length; i++) {
const char = data.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash; // Convert to 32bit integer
}
// Convert to hex string
const hashHex = (hash >>> 0).toString(16).padStart(8, "0");
return hashHex.repeat(8).substring(0, 64); // Make it look like a SHA-256 hash length
};

_internalSetInitialState();
browserConfigured = true;
}
5 changes: 5 additions & 0 deletions integrations/browser-js/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { configureBrowser } from "./browser-config";

configureBrowser();

export * from "braintrust";
15 changes: 15 additions & 0 deletions integrations/browser-js/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"declaration": true,
"lib": ["es2022", "dom"],
"module": "esnext",
"target": "es2022",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
14 changes: 14 additions & 0 deletions integrations/browser-js/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineConfig } from "tsup";

export default defineConfig({
entry: ["src/index.ts"],
format: ["esm"],
dts: true,
sourcemap: true,
clean: true,
external: ["braintrust", "zod"],
target: "es2022",
platform: "browser",
outDir: "./dist",
treeshake: true,
});
10 changes: 10 additions & 0 deletions integrations/browser-js/turbo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "https://turbo.build/schema.json",
"extends": ["//"],
"tasks": {
"build": {
"dependsOn": ["braintrust#build"],
"outputs": ["dist/**"]
}
}
}
Loading
Loading