chore(vendor): import pi 1.3.0

Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
This commit is contained in:
alexion committed 2026-10-15 17:58:48 -04:00
1 parent 719370c8f7
commit 6081e3e325
1743 files changed
+205459 -131704

No files matched your search

@@ -1,8 +1,7 @@
import type Anthropic from "@anthropic-ai/sdk";
import { describe, expect, it } from "vitest";
import { stream as streamAnthropic } from "../src/api/anthropic-messages.ts";
import { getModel } from "../src/compat.ts";
import type { Context } from "../src/types.ts";
import { getModel, normalizeContext } from "../src/compat.ts";
function createSseResponse(events: Array<{ event: string; data: string }>): Response {
const body = events.map(({ event, data }) => `event: ${event}\ndata: ${data}\n`).join("\n");
@@ -57,7 +56,7 @@ function eventsWithCacheCreation(
}
// claude-opus-4-8: input 5, cacheWrite (5m) 6.25 per Mtok. 1h write = 2x input = 10.
const context: Context = { messages: [{ role: "user", content: "hi", timestamp: Date.now() }] };
const context = normalizeContext({ messages: [{ role: "user", content: "hi", timestamp: Date.now() }] });
describe("Anthropic 1h cache write cost", () => {
it("prices the 1h portion at 2x input and the rest at the 5m rate", async () => {
@@ -65,7 +64,9 @@ describe("Anthropic 1h cache write cost", () => {
const response = createSseResponse(
eventsWithCacheCreation({ ephemeral_5m_input_tokens: 600_000, ephemeral_1h_input_tokens: 400_000 }),
);
const result = await streamAnthropic(model, context, { client: createFakeAnthropicClient(response) }).result();
const result = await streamAnthropic(model, context, {
client: createFakeAnthropicClient(response),
}).result();
expect(result.usage.cacheWrite).toBe(1_000_000);
expect(result.usage.cacheWrite1h).toBe(400_000);
@@ -73,10 +74,47 @@ describe("Anthropic 1h cache write cost", () => {
expect(result.usage.cost.cacheWrite).toBeCloseTo(7.75, 10);
});
// Regression for #9210: Vercel AI Gateway sends cache usage in message_delta, not message_start.
it("prices 1h cache writes reported only in message_delta", async () => {
const model = getModel("vercel-ai-gateway", "anthropic/claude-haiku-4.5");
const response = createSseResponse([
{
event: "message_start",
data: JSON.stringify({
type: "message_start",
message: { id: "msg_test", usage: { input_tokens: 0, output_tokens: 0 } },
}),
},
{
event: "message_delta",
data: JSON.stringify({
type: "message_delta",
delta: { stop_reason: "end_turn" },
usage: {
input_tokens: 3,
output_tokens: 4,
cache_creation_input_tokens: 6535,
cache_creation: { ephemeral_5m_input_tokens: 0, ephemeral_1h_input_tokens: 6535 },
},
}),
},
{ event: "message_stop", data: JSON.stringify({ type: "message_stop" }) },
]);
const result = await streamAnthropic(model, context, {
client: createFakeAnthropicClient(response),
}).result();
expect(result.usage.cacheWrite).toBe(6535);
expect(result.usage.cacheWrite1h).toBe(6535);
expect(result.usage.cost.cacheWrite).toBeCloseTo((6535 * model.cost.input * 2) / 1_000_000, 10);
});
it("falls back to the 5m rate when no breakdown is reported", async () => {
const model = getModel("anthropic", "claude-opus-4-8");
const response = createSseResponse(eventsWithCacheCreation(undefined));
const result = await streamAnthropic(model, context, { client: createFakeAnthropicClient(response) }).result();
const result = await streamAnthropic(model, context, {
client: createFakeAnthropicClient(response),
}).result();
expect(result.usage.cacheWrite).toBe(1_000_000);
expect(result.usage.cacheWrite1h ?? 0).toBe(0);