mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
parent
9cb7f493e7
commit
75c7fd6623
2 changed files with 56 additions and 1 deletions
|
|
@ -732,7 +732,10 @@ function applyOpenAICompletionsCompatMetadata(model: Model<Api>): void {
|
|||
}
|
||||
|
||||
function applyStrictToolCompatMetadata(model: Model<Api>): void {
|
||||
if (model.provider === "openai" && model.api === "openai-responses") {
|
||||
if (
|
||||
(model.provider === "openai" || model.provider === "cloudflare-ai-gateway") &&
|
||||
model.api === "openai-responses"
|
||||
) {
|
||||
model.compat = { ...(model.compat as OpenAIResponsesCompat | undefined), supportsStrictMode: true };
|
||||
} else if (model.provider === "anthropic" && model.api === "anthropic-messages") {
|
||||
mergeAnthropicMessagesCompat(model, { supportsStrictTools: true });
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ type CapturedHeaders = Headers | string[][] | Record<string, string | readonly s
|
|||
interface CapturedResponsesPayload {
|
||||
prompt_cache_key?: string;
|
||||
session_id?: string;
|
||||
tools?: Array<{ name?: string; strict?: boolean }>;
|
||||
}
|
||||
|
||||
function getHeader(headers: CapturedHeaders, name: string): string | null {
|
||||
|
|
@ -153,6 +154,57 @@ describe("openai-responses provider defaults", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("sets strict mode explicitly for Cloudflare OpenAI Responses tools", async () => {
|
||||
const model = getModel("cloudflare-ai-gateway", "gpt-5.6-sol");
|
||||
let capturedPayload: CapturedResponsesPayload | undefined;
|
||||
|
||||
vi.spyOn(globalThis, "fetch").mockResolvedValue(
|
||||
new Response("data: [DONE]\n\n", {
|
||||
status: 200,
|
||||
headers: { "content-type": "text/event-stream" },
|
||||
}),
|
||||
);
|
||||
|
||||
const stream = streamOpenAIResponses(
|
||||
model,
|
||||
{
|
||||
messages: [{ role: "user", content: "Use a tool.", timestamp: Date.now() }],
|
||||
tools: [
|
||||
{
|
||||
name: "ordinary",
|
||||
description: "An ordinary tool",
|
||||
parameters: Type.Object({
|
||||
path: Type.String(),
|
||||
offset: Type.Optional(Type.Number()),
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "constrained",
|
||||
description: "A constrained tool",
|
||||
parameters: Type.Object({ value: Type.String() }),
|
||||
constrainedSampling: { type: "json_schema", strict: "prefer" },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
apiKey: "test-key",
|
||||
onPayload: (payload) => {
|
||||
capturedPayload = payload as CapturedResponsesPayload;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
for await (const event of stream) {
|
||||
if (event.type === "done" || event.type === "error") break;
|
||||
}
|
||||
|
||||
expect(model.compat?.supportsStrictMode).toBe(true);
|
||||
expect(capturedPayload?.tools).toEqual([
|
||||
expect.objectContaining({ name: "ordinary", strict: false }),
|
||||
expect.objectContaining({ name: "constrained", strict: true }),
|
||||
]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
"gpt-5.1",
|
||||
"gpt-5.2",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue