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,7 +1,7 @@
import { Type } from "typebox";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { convertMessages } from "../src/api/openai-completions.ts";
import { getModel, stream, streamSimple } from "../src/compat.ts";
import { getModel, normalizeContext, stream, streamSimple } from "../src/compat.ts";
import type { AssistantMessage, Model, SimpleStreamOptions, Tool, ToolResultMessage } from "../src/types.ts";
const mockState = vi.hoisted(() => ({
@@ -219,6 +219,82 @@ describe("openai-completions tool_choice", () => {
expect("strict" in (tool ?? {})).toBe(false);
});
it("defaults unknown OpenAI-compatible endpoints to non-strict tools", async () => {
// Regression test for #9816.
const model = {
...localOpenAICompletionsModel,
id: "local-model",
name: "Local Model",
} satisfies Model<"openai-completions">;
const tool: Tool = {
name: "ping",
description: "Ping tool",
parameters: Type.Object({
required: Type.String(),
optional: Type.Optional(Type.String()),
}),
constrainedSampling: { type: "json_schema", strict: "prefer" },
};
let payload: unknown;
await streamSimple(
model,
{
messages: [{ role: "user", content: "Call ping", timestamp: Date.now() }],
tools: [tool],
},
{
apiKey: "test",
onPayload: (params: unknown) => {
payload = params;
},
},
).result();
const params = (payload ?? mockState.lastParams) as {
tools?: Array<{ function?: { strict?: boolean; parameters?: { required?: string[] } } }>;
};
const functionTool = params.tools?.[0]?.function;
expect(functionTool).not.toHaveProperty("strict");
expect(functionTool?.parameters?.required).toEqual(["required"]);
});
it("preserves strict tools for capable built-in Chat Completions models", async () => {
const model = getModel("groq", "openai/gpt-oss-20b")!;
expect(model.compat?.supportsStrictMode).toBe(true);
const tool: Tool = {
name: "ping",
description: "Ping tool",
parameters: Type.Object({
required: Type.String(),
optional: Type.Optional(Type.String()),
}),
constrainedSampling: { type: "json_schema", strict: "prefer" },
};
let payload: unknown;
await streamSimple(
model,
{
messages: [{ role: "user", content: "Call ping", timestamp: Date.now() }],
tools: [tool],
},
{
apiKey: "test",
onPayload: (params: unknown) => {
payload = params;
},
},
).result();
const params = (payload ?? mockState.lastParams) as {
tools?: Array<{ function?: { strict?: boolean; parameters?: { required?: string[] } } }>;
};
const functionTool = params.tools?.[0]?.function;
expect(functionTool?.strict).toBe(true);
expect(functionTool?.parameters?.required).toEqual(["required", "optional"]);
});
it("maps Groq Qwen reasoning levels to default reasoning_effort", async () => {
const model = getModel("groq", "qwen/qwen3.6-27b")!;
let payload: unknown;
@@ -320,21 +396,21 @@ describe("openai-completions tool_choice", () => {
});
it("stores z.ai effort metadata", () => {
for (const provider of ["zai", "zai-coding-cn"] as const) {
for (const modelId of ["glm-5.2", "glm-5.2-highspeed"] as const) {
const model = getModel(provider, modelId)!;
expect(model.compat?.supportsReasoningEffort).toBe(true);
expect(model.thinkingLevelMap).toEqual({
off: "none",
minimal: null,
low: null,
medium: null,
high: "high",
xhigh: null,
max: "max",
});
}
for (const modelId of ["glm-5.2", "glm-5.2-highspeed"] as const) {
const model = getModel("zai", modelId)!;
expect(model.compat?.supportsReasoningEffort).toBe(true);
expect(model.thinkingLevelMap).toEqual({
off: "none",
minimal: null,
low: null,
medium: null,
high: "high",
xhigh: null,
max: "max",
});
}
for (const provider of ["zai", "zai-coding-cn"] as const) {
const glm53 = getModel(provider, "glm-5.3")!;
expect(glm53.compat?.supportsReasoningEffort).toBe(true);
expect(glm53.thinkingLevelMap).toEqual({
@@ -1030,12 +1106,12 @@ describe("openai-completions tool_choice", () => {
]);
expect(response.content).toHaveLength(6);
expect(response.content[0]).toEqual({ type: "text", text: "answer 1 answer 2\n" });
expect(response.content[1]).toEqual({
expect(response.content[0]).toEqual({
type: "thinking",
thinking: "think 1 think 2",
thinkingSignature: "reasoning_content",
});
expect(response.content[1]).toEqual({ type: "text", text: "answer 1 answer 2\n" });
const readCall = response.content[2];
const grepCall = response.content[3];
const listCall = response.content[4];
@@ -1233,7 +1309,7 @@ describe("openai-completions tool_choice", () => {
const replayedAssistant = params.messages?.find((message) => message.role === "assistant");
expect(replayedAssistant).toMatchObject({ role: "assistant", reasoning_content: "" });
expect(params.thinking).toEqual({ type: "enabled" });
expect(params.reasoning_effort).toBe("high");
expect(params.reasoning_effort).toBeUndefined();
});
it("normalizes OpenCode Go reasoning deltas to reasoning_content for replay", async () => {
@@ -1244,7 +1320,7 @@ describe("openai-completions tool_choice", () => {
},
];
const { compat: _compat, ...baseModel } = getModel("opencode-go", "kimi-k2.6")!;
const { compat: _compat, ...baseModel } = getModel("opencode-go", "kimi-k3")!;
const model = { ...baseModel, api: "openai-completions" } as const;
const response = await streamSimple(
model,
@@ -1291,17 +1367,17 @@ describe("openai-completions tool_choice", () => {
});
it("replays OpenCode Go reasoning thinking blocks as reasoning_content", () => {
const { compat: _compat, ...baseModel } = getModel("opencode-go", "kimi-k2.6")!;
const { compat: _compat, ...baseModel } = getModel("opencode-go", "kimi-k3")!;
const model = { ...baseModel, api: "openai-completions" } as Model<"openai-completions">;
const messages = convertMessages(
model,
{
normalizeContext({
messages: [
{
role: "assistant",
api: "openai-completions",
provider: "opencode-go",
model: "kimi-k2.6",
model: "kimi-k3",
content: [
{ type: "thinking", thinking: "think", thinkingSignature: "reasoning" },
{ type: "toolCall", id: "call_1", name: "read", arguments: { path: "README.md" } },
@@ -1318,7 +1394,7 @@ describe("openai-completions tool_choice", () => {
timestamp: Date.now(),
},
],
},
}),
{
...model.compat,
supportsStore: false,
@@ -1349,8 +1425,8 @@ describe("openai-completions tool_choice", () => {
expect(messages[0]).not.toHaveProperty("reasoning");
});
it("sends thinking disabled for OpenCode Go Kimi K2.6 when thinking is off", async () => {
const model = getModel("opencode-go", "kimi-k2.6")!;
it("sends thinking disabled for OpenCode Kimi K2.6 when thinking is off", async () => {
const model = getModel("opencode", "kimi-k2.6")!;
let payload: unknown;
await streamSimple(
@@ -1371,8 +1447,8 @@ describe("openai-completions tool_choice", () => {
expect(params.reasoning_effort).toBeUndefined();
});
it("sends thinking enabled for OpenCode Go Kimi K2.6 when thinking is enabled", async () => {
const model = getModel("opencode-go", "kimi-k2.6")!;
it("sends thinking enabled for OpenCode Kimi K2.6 when thinking is enabled", async () => {
const model = getModel("opencode", "kimi-k2.6")!;
let payload: unknown;
await streamSimple(
@@ -1443,7 +1519,7 @@ describe("openai-completions tool_choice", () => {
});
it("sends max_tokens for OpenCode completions models", async () => {
const cases = [getModel("opencode-go", "kimi-k2.6")!, getModel("opencode", "kimi-k2.6")!] as const;
const cases = [getModel("opencode-go", "kimi-k3")!, getModel("opencode", "kimi-k2.6")!] as const;
for (const model of cases) {
let payload: unknown;
@@ -1483,10 +1559,7 @@ describe("openai-completions tool_choice", () => {
name: "Custom Uppercase DeepSeek Model",
baseUrl: "https://API.DeepSeek.COM",
} satisfies Model<"openai-completions">;
const nativeModels = [
getModel("deepseek", "deepseek-v4-flash")!,
getModel("deepseek", "deepseek-v4-pro")!,
] as const;
const nativeModels = [getModel("deepseek", "deepseek-flash")!, getModel("deepseek", "deepseek-v4-pro")!] as const;
const cases = [...nativeModels, customModel, customUppercaseModel] as const;
for (const model of nativeModels) {
@@ -1802,7 +1875,7 @@ describe("openai-completions tool_choice", () => {
thinkingFormat: "ant-ling",
supportsLongCacheRetention: false,
});
expect(model.compat?.supportsStrictMode).toBeUndefined();
expect(model.compat?.supportsStrictMode).toBe(true);
expect(model.compat?.requiresReasoningContentOnAssistantMessages).toBeUndefined();
await streamSimple(