Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions e2e/helpers/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const DYNAMIC_HEADER_KEYS = new Set([
"openai-project",
"server-timing",
"set-cookie",
"x-gemini-service-tier",
"x-ratelimit-remaining-requests",
"x-ratelimit-remaining-tokens",
"x-ratelimit-reset-requests",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-gemini-service-tier": "<x-gemini-service-tier>",
"x-xss-protection": "0"
}
},
Expand Down Expand Up @@ -359,6 +360,7 @@
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-gemini-service-tier": "<x-gemini-service-tier>",
"x-xss-protection": "0"
}
},
Expand Down Expand Up @@ -887,6 +889,7 @@
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-gemini-service-tier": "<x-gemini-service-tier>",
"x-xss-protection": "0"
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-gemini-service-tier": "<x-gemini-service-tier>",
"x-xss-protection": "0"
}
},
Expand Down Expand Up @@ -372,6 +373,7 @@
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-gemini-service-tier": "<x-gemini-service-tier>",
"x-xss-protection": "0"
}
},
Expand Down Expand Up @@ -914,6 +916,7 @@
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-gemini-service-tier": "<x-gemini-service-tier>",
"x-xss-protection": "0"
}
},
Expand Down
182 changes: 167 additions & 15 deletions js/src/logger.test.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
/* eslint-disable @typescript-eslint/consistent-type-assertions */
import type {
ChatCompletionContentPartText,
ChatCompletionContentPartImage,
} from "openai/resources";

import { vi, expect, test, describe, beforeEach, afterEach } from "vitest";
import {
_exportsForTestingOnly,
init,
initLogger,
Prompt,
BraintrustState,
loadPrompt,
loadParameters,
wrapTraced,
currentSpan,
withParent,
startSpan,
updateSpan,
Attachment,
deepCopyEvent,
renderMessage,
renderMessageImpl,
} from "./logger";
import {
parseTemplateFormat,
isTemplateFormat,
renderTemplateContent,
} from "./template/renderer";

import { configureNode } from "./node/config";
import { writeFile, unlink } from "node:fs/promises";
import { join } from "node:path";
Expand All @@ -33,11 +27,6 @@ import { SpanComponentsV3 } from "../util/span_identifier_v3";

configureNode();

function getExportVersion(exportedSpan: string): number {
const exportedBytes = base64ToUint8Array(exportedSpan);
return exportedBytes[0];
}

test("renderMessage with file content parts", () => {
const message = {
role: "user" as const,
Expand Down Expand Up @@ -464,6 +453,169 @@ test("init accepts dataset with id and version", () => {
expect(datasetWithVersion.version).toBe("v2");
});

describe("loader version precedence", () => {
let state: BraintrustState;
let getJson: ReturnType<typeof vi.spyOn>;
const promptRow = {
id: "11111111-1111-4111-8111-111111111111",
_xact_id: "v1",
project_id: "22222222-2222-4222-8222-222222222222",
log_id: "p",
org_id: "33333333-3333-4333-8333-333333333333",
name: "Saved prompt",
slug: "saved-prompt",
description: null,
tags: null,
prompt_data: {
prompt: {
type: "chat",
messages: [{ role: "user", content: "Hello" }],
},
options: { model: "gpt-5-mini" },
},
} satisfies {
id: string;
_xact_id: string;
project_id: string;
log_id: "p";
org_id: string;
name: string;
slug: string;
description: null;
tags: null;
prompt_data: {
prompt: {
type: "chat";
messages: Array<{ role: "user"; content: string }>;
};
options: { model: string };
};
};
const parametersRow = {
id: "44444444-4444-4444-8444-444444444444",
_xact_id: "v1",
project_id: "55555555-5555-4555-8555-555555555555",
name: "Saved parameters",
slug: "saved-parameters",
description: null,
function_type: "parameters",
function_data: {
type: "parameters",
data: { prefix: "hello" },
__schema: {
type: "object",
properties: {
prefix: { type: "string", default: "hello" },
},
additionalProperties: true,
},
},
} satisfies {
id: string;
_xact_id: string;
project_id: string;
name: string;
slug: string;
description: null;
function_type: "parameters";
function_data: {
type: "parameters";
data: { prefix: string };
__schema: {
type: string;
properties: { prefix: { type: string; default: string } };
additionalProperties: boolean;
};
};
};

beforeEach(async () => {
state = await _exportsForTestingOnly.simulateLoginForTests();
vi.spyOn(state, "login").mockResolvedValue(state);
getJson = vi.spyOn(state.apiConn(), "get_json");
});

afterEach(() => {
_exportsForTestingOnly.simulateLogoutForTests();
vi.restoreAllMocks();
});

test("loadPrompt prefers version over environment for project lookup", async () => {
getJson.mockResolvedValue({ objects: [promptRow] });

await loadPrompt({
projectName: "test-project",
slug: "saved-prompt",
version: "v1",
environment: "production",
state,
});

expect(getJson).toHaveBeenCalledWith(
"v1/prompt",
expect.objectContaining({
project_name: "test-project",
slug: "saved-prompt",
version: "v1",
}),
);
expect(getJson.mock.calls[0][1]).not.toHaveProperty("environment");
});

test("loadPrompt prefers version over environment for id lookup", async () => {
getJson.mockResolvedValue(promptRow);

await loadPrompt({
id: promptRow.id,
version: "v1",
environment: "production",
state,
});

expect(getJson).toHaveBeenCalledWith(`v1/prompt/${promptRow.id}`, {
version: "v1",
});
});

test("loadParameters prefers version over environment for project lookup", async () => {
getJson.mockResolvedValue({ objects: [parametersRow] });

await loadParameters({
projectName: "test-project",
slug: "saved-parameters",
version: "v1",
environment: "production",
state,
});

expect(getJson).toHaveBeenCalledWith(
"v1/function",
expect.objectContaining({
project_name: "test-project",
slug: "saved-parameters",
version: "v1",
function_type: "parameters",
}),
);
expect(getJson.mock.calls[0][1]).not.toHaveProperty("environment");
});

test("loadParameters prefers version over environment for id lookup", async () => {
getJson.mockResolvedValue(parametersRow);

await loadParameters({
id: parametersRow.id,
version: "v1",
environment: "production",
state,
});

expect(getJson).toHaveBeenCalledWith(`v1/function/${parametersRow.id}`, {
version: "v1",
});
});
});

describe("prompt.build structured output templating", () => {
test("applies nunjucks templating inside schema", () => {
const prompt = new Prompt<false, false>(
Expand Down
Loading
Loading