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:
1 parent
719370c8f7
commit
6081e3e325
1743 files changed
+205459
-131704
No files matched your search
+83
-10
@@ -2,9 +2,9 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { stream as streamAnthropic } from "../src/api/anthropic-messages.ts";
|
||||
import { stream as streamOpenAICompletions } from "../src/api/openai-completions.ts";
|
||||
import { stream as streamOpenAIResponses } from "../src/api/openai-responses.ts";
|
||||
import { getModel, stream } from "../src/compat.ts";
|
||||
import { getModel, normalizeContext, stream } from "../src/compat.ts";
|
||||
import { MODELS } from "../src/models.generated.ts";
|
||||
import type { Context, Model } from "../src/types.ts";
|
||||
import type { Model } from "../src/types.ts";
|
||||
|
||||
class PayloadCaptured extends Error {
|
||||
constructor() {
|
||||
@@ -44,10 +44,10 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
}
|
||||
});
|
||||
|
||||
const context: Context = {
|
||||
const context = normalizeContext({
|
||||
systemPrompt: "You are a helpful assistant.",
|
||||
messages: [{ role: "user", content: "Hello", timestamp: Date.now() }],
|
||||
};
|
||||
});
|
||||
|
||||
describe("Anthropic Provider", () => {
|
||||
it.skipIf(!process.env.ANTHROPIC_API_KEY)(
|
||||
@@ -240,6 +240,13 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
});
|
||||
|
||||
describe("OpenAI Responses Provider", () => {
|
||||
it.each(["gpt-5.6-luna", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-6-astra", "gpt-6-luna", "gpt-6-sol"] as const)(
|
||||
"does not enable cache warming from the documented TTL alone for %s",
|
||||
(modelId) => {
|
||||
expect(getModel("openai", modelId).promptCache).toBeUndefined();
|
||||
},
|
||||
);
|
||||
|
||||
it.skipIf(!process.env.OPENAI_API_KEY)(
|
||||
"should not set prompt_cache_retention when PI_CACHE_RETENTION is not set",
|
||||
async () => {
|
||||
@@ -299,7 +306,7 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
|
||||
try {
|
||||
const s = streamOpenAIResponses(proxyModel, context, {
|
||||
apiKey: "fake-key",
|
||||
apiKey: "sk-fake-key",
|
||||
onPayload: stopAfterPayload((payload) => {
|
||||
capturedPayload = payload;
|
||||
}),
|
||||
@@ -326,7 +333,7 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
|
||||
try {
|
||||
const s = streamOpenAIResponses(model, context, {
|
||||
apiKey: "fake-key",
|
||||
apiKey: "sk-fake-key",
|
||||
cacheRetention: "long",
|
||||
sessionId: "session-compat-false",
|
||||
onPayload: stopAfterPayload((payload) => {
|
||||
@@ -351,7 +358,7 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
|
||||
try {
|
||||
const s = streamOpenAIResponses(model, context, {
|
||||
apiKey: "fake-key",
|
||||
apiKey: "sk-fake-key",
|
||||
cacheRetention: "none",
|
||||
sessionId: "session-1",
|
||||
onPayload: stopAfterPayload<OpenAIResponsesCachePayload>((payload) => {
|
||||
@@ -378,7 +385,7 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
|
||||
try {
|
||||
const s = streamOpenAIResponses(model, context, {
|
||||
apiKey: "fake-key",
|
||||
apiKey: "sk-fake-key",
|
||||
cacheRetention: "none",
|
||||
sessionId: "session-1",
|
||||
onPayload: stopAfterPayload<OpenAIResponsesCachePayload>((payload) => {
|
||||
@@ -401,13 +408,15 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
it.each([
|
||||
["gpt-4o-mini", "24h", undefined],
|
||||
["gpt-6-astra", undefined, { ttl: "30m" }],
|
||||
["gpt-6-sol", undefined, { ttl: "30m" }],
|
||||
["gpt-6-luna", undefined, { ttl: "30m" }],
|
||||
] as const)("should use the supported long cache field for %s", async (modelId, retention, cacheOptions) => {
|
||||
const model = getModel("openai", modelId);
|
||||
let capturedPayload: OpenAIResponsesCachePayload | undefined;
|
||||
|
||||
try {
|
||||
const s = streamOpenAIResponses(model, context, {
|
||||
apiKey: "fake-key",
|
||||
apiKey: "sk-fake-key",
|
||||
cacheRetention: "long",
|
||||
sessionId: "session-2",
|
||||
onPayload: stopAfterPayload<OpenAIResponsesCachePayload>((payload) => {
|
||||
@@ -501,7 +510,6 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
MODELS.opencode["kimi-k2.5"],
|
||||
MODELS.opencode["kimi-k2.6"],
|
||||
MODELS.opencode["minimax-m2.7"],
|
||||
MODELS["opencode-go"]["kimi-k2.6"],
|
||||
] as const)("should omit long cache retention for $provider/$id", async (metadata) => {
|
||||
const model = metadata as Model<"openai-completions">;
|
||||
let capturedPayload: OpenAICompletionsCachePayload | undefined;
|
||||
@@ -528,5 +536,70 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||
expect(capturedPayload?.prompt_cache_key).toBeUndefined();
|
||||
expect(capturedPayload?.prompt_cache_retention).toBeUndefined();
|
||||
});
|
||||
|
||||
it.each([MODELS.cerebras["gpt-oss-120b"], MODELS.cerebras["qwen-3.8-27b"]] as const)(
|
||||
"should omit strict field on tools for cerebras/$id",
|
||||
async (metadata) => {
|
||||
const model = metadata as Model<"openai-completions">;
|
||||
|
||||
const contextWithTools = {
|
||||
messages: [
|
||||
{
|
||||
role: "system" as const,
|
||||
content: "test",
|
||||
toolsAdded: [
|
||||
{
|
||||
name: "t1",
|
||||
description: "strict tool",
|
||||
parameters: {
|
||||
type: "object" as const,
|
||||
properties: { x: { type: "string" } },
|
||||
required: ["x"],
|
||||
},
|
||||
constrainedSampling: { type: "json_schema" as const },
|
||||
},
|
||||
{
|
||||
name: "t2",
|
||||
description: "non-strict tool",
|
||||
parameters: {
|
||||
type: "object" as const,
|
||||
properties: { y: { type: "string" } },
|
||||
required: ["y"],
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamp: 0,
|
||||
},
|
||||
{ role: "user" as const, content: "hello", timestamp: 1 },
|
||||
],
|
||||
};
|
||||
|
||||
let capturedPayload: any;
|
||||
|
||||
try {
|
||||
const s = streamOpenAICompletions(model, contextWithTools as any, {
|
||||
apiKey: "fake-key",
|
||||
sessionId: "test",
|
||||
onPayload: stopAfterPayload((payload: any) => {
|
||||
capturedPayload = payload;
|
||||
}),
|
||||
});
|
||||
|
||||
for await (const event of s) {
|
||||
if (event.type === "error") break;
|
||||
}
|
||||
} catch {
|
||||
// Expected to fail
|
||||
}
|
||||
|
||||
expect(model.compat?.supportsStrictMode).toBeUndefined();
|
||||
expect(capturedPayload).toBeDefined();
|
||||
const tools = capturedPayload?.tools as any[] | undefined;
|
||||
expect(tools).toBeDefined();
|
||||
for (const tool of tools!) {
|
||||
expect(tool.function).not.toHaveProperty("strict");
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user