@providerkit/core 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capability.d.ts +51 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +93 -0
- package/dist/capability.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/gemini.d.ts +10 -1
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +16 -3
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/openai.d.ts +28 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +38 -23
- package/dist/providers/openai.js.map +1 -1
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/capability.ts +141 -0
- package/src/index.ts +1 -0
- package/src/providers/gemini.ts +26 -2
- package/src/providers/openai.ts +68 -23
- package/src/types.ts +20 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { JsonWithTools, Provider } from "./types.ts";
|
|
2
|
+
export interface JsonWithToolsProbe {
|
|
3
|
+
/**
|
|
4
|
+
* The shape to configure, or `null` when neither called the tool on every
|
|
5
|
+
* sample — that model cannot be trusted with tools and a schema together,
|
|
6
|
+
* whichever way the schema rides, and the honest fix is a different model.
|
|
7
|
+
*/
|
|
8
|
+
use: JsonWithTools | null;
|
|
9
|
+
/** Samples that produced a tool call, per shape, out of `samples`. */
|
|
10
|
+
calls: Record<JsonWithTools, number>;
|
|
11
|
+
/** How many times each shape was asked. */
|
|
12
|
+
samples: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ProbeOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Samples per shape. Above one because the interesting failures are partial —
|
|
17
|
+
* `gemini-3.8-flash` called its tool 3/10 — and a single sample reports a
|
|
18
|
+
* coin flip as a capability. A shape passes only when EVERY sample calls.
|
|
19
|
+
*/
|
|
20
|
+
samples?: number;
|
|
21
|
+
/** Override the provider's bound model, to probe one it is not built for. */
|
|
22
|
+
model?: string;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Ask a model, on the wire, which {@link JsonWithTools} shape it actually
|
|
27
|
+
* serves — then configure the provider with `probe.use`.
|
|
28
|
+
*
|
|
29
|
+
* Both shapes are always tried, because a result you can read beats a result
|
|
30
|
+
* you have to trust: `calls` is the table to log, and "0/3 and 3/3" is what
|
|
31
|
+
* makes a later regression obvious. It costs `samples × 2` short calls, once,
|
|
32
|
+
* at whatever moment the app decides to ask — boot is the usual one.
|
|
33
|
+
*
|
|
34
|
+
* Errors propagate. A probe that swallowed a bad key or a dead endpoint would
|
|
35
|
+
* report "this model cannot call tools", which is a much worse thing to
|
|
36
|
+
* believe than "the call failed".
|
|
37
|
+
*
|
|
38
|
+
* What it catches is the structural failure — the model that CANNOT emit the
|
|
39
|
+
* call, every time, on the easiest question there is. A model that is merely
|
|
40
|
+
* unreliable will pass: `gemini-3.8-flash` answers this probe 3/3 and a real
|
|
41
|
+
* sales turn 3/10. That is the right line to draw. A harder probe would start
|
|
42
|
+
* failing good models for being terse, and "sometimes forgets its tools" is a
|
|
43
|
+
* prompt and eval problem, not a wire shape one.
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* const probe = await probeJsonWithTools(provider);
|
|
47
|
+
* if (!probe.use) throw new Error(`${model} cannot use tools with a schema`);
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function probeJsonWithTools(provider: Provider, opts?: ProbeOptions): Promise<JsonWithToolsProbe>;
|
|
51
|
+
//# sourceMappingURL=capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA2B1D,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1B,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACrC,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,QAAQ,EAClB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAiB7B"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Asking a model what it can actually do, instead of reading its model card.
|
|
2
|
+
//
|
|
3
|
+
// One capability needs this badly enough to ship a prober: whether a model
|
|
4
|
+
// still emits a tool call when the same request also constrains its output to
|
|
5
|
+
// a schema. Most do. Several — measured 2026-09-07: `z-ai/glm-5.3-flash`,
|
|
6
|
+
// `z-ai/glm-5.3`, `deepseek-v4-flash` — never do, and they fail in the worst
|
|
7
|
+
// available way. The decoder is pinned to the schema, the tool call has nowhere
|
|
8
|
+
// to go, and the model writes the announcement instead ("let me look that up
|
|
9
|
+
// for you") and stops. No error, no warning, no finish reason to branch on: on
|
|
10
|
+
// the wire the turn succeeded. Downstream it reads as a model that will not use
|
|
11
|
+
// its tools, and no amount of prompting moves it, because the call was never
|
|
12
|
+
// representable.
|
|
13
|
+
//
|
|
14
|
+
// `jsonWithTools: "prompt"` is the remedy, and it cannot be a default: the same
|
|
15
|
+
// run put `qwen3.8-flash` at 10/10 with the response format and 1/6 without it,
|
|
16
|
+
// so a global flip only moves the silence to different models. One call each
|
|
17
|
+
// way settles it for the model actually being served.
|
|
18
|
+
/** Nothing a model can answer from memory — so a tool call is the only correct
|
|
19
|
+
* turn, and NOT making one is a real signal rather than a judgement call. */
|
|
20
|
+
const PROBE_TOOL = {
|
|
21
|
+
name: "get_current_time",
|
|
22
|
+
description: "The only source of the current time. You cannot know the time without calling this — never answer a time question from memory or guess.",
|
|
23
|
+
inputSchema: {
|
|
24
|
+
type: "object",
|
|
25
|
+
properties: { timezone: { type: "string", description: "IANA timezone, e.g. Asia/Tokyo" } },
|
|
26
|
+
required: [],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
const PROBE_JSON = {
|
|
30
|
+
name: "probe",
|
|
31
|
+
schema: {
|
|
32
|
+
type: "object",
|
|
33
|
+
properties: { message: { type: "string", description: "Your reply to the user." } },
|
|
34
|
+
required: ["message"],
|
|
35
|
+
additionalProperties: false,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
const SHAPES = ["response_format", "prompt"];
|
|
39
|
+
async function callsTool(provider, shape, opts) {
|
|
40
|
+
const stream = provider.createStream([{ role: "user", content: "What time is it in Tokyo right now?" }], [PROBE_TOOL], {
|
|
41
|
+
json: PROBE_JSON,
|
|
42
|
+
jsonWithTools: shape,
|
|
43
|
+
// Deterministic, so a rerun of the probe answers the same way.
|
|
44
|
+
temperature: 0,
|
|
45
|
+
...(opts.model ? { model: opts.model } : {}),
|
|
46
|
+
...(opts.signal ? { signal: opts.signal } : {}),
|
|
47
|
+
});
|
|
48
|
+
// No token cap: on a thinking model a small one is spent before the answer
|
|
49
|
+
// starts, and an empty completion would read here as "did not call the tool".
|
|
50
|
+
for await (const chunk of stream) {
|
|
51
|
+
if (chunk.toolCalls?.some((call) => call.name))
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Ask a model, on the wire, which {@link JsonWithTools} shape it actually
|
|
58
|
+
* serves — then configure the provider with `probe.use`.
|
|
59
|
+
*
|
|
60
|
+
* Both shapes are always tried, because a result you can read beats a result
|
|
61
|
+
* you have to trust: `calls` is the table to log, and "0/3 and 3/3" is what
|
|
62
|
+
* makes a later regression obvious. It costs `samples × 2` short calls, once,
|
|
63
|
+
* at whatever moment the app decides to ask — boot is the usual one.
|
|
64
|
+
*
|
|
65
|
+
* Errors propagate. A probe that swallowed a bad key or a dead endpoint would
|
|
66
|
+
* report "this model cannot call tools", which is a much worse thing to
|
|
67
|
+
* believe than "the call failed".
|
|
68
|
+
*
|
|
69
|
+
* What it catches is the structural failure — the model that CANNOT emit the
|
|
70
|
+
* call, every time, on the easiest question there is. A model that is merely
|
|
71
|
+
* unreliable will pass: `gemini-3.8-flash` answers this probe 3/3 and a real
|
|
72
|
+
* sales turn 3/10. That is the right line to draw. A harder probe would start
|
|
73
|
+
* failing good models for being terse, and "sometimes forgets its tools" is a
|
|
74
|
+
* prompt and eval problem, not a wire shape one.
|
|
75
|
+
*
|
|
76
|
+
* ```ts
|
|
77
|
+
* const probe = await probeJsonWithTools(provider);
|
|
78
|
+
* if (!probe.use) throw new Error(`${model} cannot use tools with a schema`);
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export async function probeJsonWithTools(provider, opts = {}) {
|
|
82
|
+
const samples = Math.max(1, opts.samples ?? 3);
|
|
83
|
+
const counted = await Promise.all(SHAPES.map(async (shape) => {
|
|
84
|
+
const runs = await Promise.all(Array.from({ length: samples }, () => callsTool(provider, shape, opts)));
|
|
85
|
+
return [shape, runs.filter(Boolean).length];
|
|
86
|
+
}));
|
|
87
|
+
const calls = Object.fromEntries(counted);
|
|
88
|
+
// `response_format` first when both are clean: it is the only one of the two
|
|
89
|
+
// the endpoint actually enforces, so the prompt shape is the fallback rather
|
|
90
|
+
// than the equal.
|
|
91
|
+
return { use: SHAPES.find((shape) => calls[shape] === samples) ?? null, calls, samples };
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./tool-args.ts";
|
|
|
10
10
|
export * from "./tools.ts";
|
|
11
11
|
export * from "./schema.ts";
|
|
12
12
|
export * from "./context.ts";
|
|
13
|
+
export * from "./capability.ts";
|
|
13
14
|
export * from "./providers/anthropic.ts";
|
|
14
15
|
export * from "./providers/openai.ts";
|
|
15
16
|
export * from "./providers/responses.ts";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./tool-args.js";
|
|
|
10
10
|
export * from "./tools.js";
|
|
11
11
|
export * from "./schema.js";
|
|
12
12
|
export * from "./context.js";
|
|
13
|
+
export * from "./capability.js";
|
|
13
14
|
export * from "./providers/anthropic.js";
|
|
14
15
|
export * from "./providers/openai.js";
|
|
15
16
|
export * from "./providers/responses.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChatMessage, Effort, Provider } from "../types.ts";
|
|
1
|
+
import type { ChatMessage, Effort, JsonWithTools, Provider } from "../types.ts";
|
|
2
2
|
export interface GeminiConfig {
|
|
3
3
|
apiKey: string;
|
|
4
4
|
model: string;
|
|
@@ -13,6 +13,15 @@ export interface GeminiConfig {
|
|
|
13
13
|
id?: string;
|
|
14
14
|
/** Bound default; a per-call `effort` overrides it. */
|
|
15
15
|
effort?: Effort;
|
|
16
|
+
/**
|
|
17
|
+
* How the schema rides on a call that also carries tools. See
|
|
18
|
+
* {@link JsonWithTools} — and note that it is the MODEL's answer, not the
|
|
19
|
+
* endpoint's: measured 2026-09-07, `gemini-3.5-flash` and
|
|
20
|
+
* `gemini-3.5-flash-lite` called their tool under `responseJsonSchema` every
|
|
21
|
+
* time, while `gemini-3.8-flash` managed 3/10. `probeJsonWithTools` asks the
|
|
22
|
+
* one you actually serve. Overridable per call.
|
|
23
|
+
*/
|
|
24
|
+
jsonWithTools?: JsonWithTools;
|
|
16
25
|
maxTokens?: number;
|
|
17
26
|
fetchImpl?: typeof fetch;
|
|
18
27
|
headers?: Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,WAAW,EACX,MAAM,EAEN,aAAa,EACb,QAAQ,EAMT,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd;;;;;oFAKgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAoBD,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB;AAqCD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B,CA+DA;AA0DD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,CAsKnE"}
|
package/dist/providers/gemini.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// wire rather than @google/genai, because this package ships zero dependencies
|
|
7
7
|
// and the SDK is a Node-shaped one.
|
|
8
8
|
import { streamError } from "../errors.js";
|
|
9
|
+
import { schemaPrompt } from "../schema.js";
|
|
9
10
|
import { parseToolArgs } from "../tool-args.js";
|
|
10
11
|
import { streamSse, apiUrl } from "../transport.js";
|
|
11
12
|
const DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com";
|
|
@@ -176,7 +177,12 @@ export function createGeminiProvider(config) {
|
|
|
176
177
|
// reason the seam treats an absent effort as "never sent".
|
|
177
178
|
if (effort)
|
|
178
179
|
generationConfig.thinkingConfig = { thinkingLevel: THINKING_LEVEL[effort] };
|
|
179
|
-
|
|
180
|
+
// A schema that shares its call with tools pins the decoder, and a pinned
|
|
181
|
+
// decoder cannot emit a functionCall — the model narrates the call it
|
|
182
|
+
// could not make and the turn ends, with nothing logged. See
|
|
183
|
+
// `jsonWithTools` for what that costs and which models it costs it on.
|
|
184
|
+
const promptCarried = tools.length > 0 && (opts.jsonWithTools ?? config.jsonWithTools) === "prompt";
|
|
185
|
+
if (opts.json && !promptCarried) {
|
|
180
186
|
generationConfig.responseMimeType = "application/json";
|
|
181
187
|
// `responseJsonSchema` takes JSON Schema as written; `responseSchema`
|
|
182
188
|
// is Gemini's own trimmed dialect and rejects most of what a real
|
|
@@ -185,8 +191,15 @@ export function createGeminiProvider(config) {
|
|
|
185
191
|
}
|
|
186
192
|
const request = { contents, generationConfig };
|
|
187
193
|
// A Content, not the bare string the SDK accepts — REST rejects a string.
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
// The prompt-carried schema rides as a second part, after the caller's
|
|
195
|
+
// own text: this shape's cache is a prefix too, so a per-call schema in
|
|
196
|
+
// front of the conversation would cold-start it on every change.
|
|
197
|
+
const systemParts = [
|
|
198
|
+
...(system ? [{ text: system }] : []),
|
|
199
|
+
...(opts.json && promptCarried ? [{ text: schemaPrompt(opts.json.schema) }] : []),
|
|
200
|
+
];
|
|
201
|
+
if (systemParts.length > 0)
|
|
202
|
+
request.systemInstruction = { parts: systemParts };
|
|
190
203
|
if (tools.length > 0) {
|
|
191
204
|
request.tools = [
|
|
192
205
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAC/E,oCAAoC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChatMessage, Effort, Provider } from "../types.ts";
|
|
1
|
+
import type { ChatMessage, Effort, JsonWithTools, Provider } from "../types.ts";
|
|
2
2
|
export interface OpenAIConfig {
|
|
3
3
|
apiKey: string;
|
|
4
4
|
model: string;
|
|
@@ -20,6 +20,33 @@ export interface OpenAIConfig {
|
|
|
20
20
|
* is the only setting every gateway accepts.
|
|
21
21
|
*/
|
|
22
22
|
jsonMode?: "schema" | "object";
|
|
23
|
+
/**
|
|
24
|
+
* How a json request rides when the SAME call also carries tools.
|
|
25
|
+
*
|
|
26
|
+
* `response_format` — the default — sends both, which is what the shape
|
|
27
|
+
* documents and what most models honour. `prompt` drops the response format
|
|
28
|
+
* from those calls only and sends the schema as prompt instead: the shape the
|
|
29
|
+
* Anthropic adapter has always used, and the reason this failure cannot
|
|
30
|
+
* happen there.
|
|
31
|
+
*
|
|
32
|
+
* It needs a knob because a model that cannot serve both does not say so. Its
|
|
33
|
+
* decoder is pinned to the schema, the tool call has nowhere to go, and the
|
|
34
|
+
* model writes the announcement instead — "let me look that up for you" — and
|
|
35
|
+
* the turn ends looking like a model with no initiative rather than a request
|
|
36
|
+
* that made the call impossible. Nothing is logged, because nothing failed.
|
|
37
|
+
*
|
|
38
|
+
* Measured 2026-09-07, one request, sampled: `z-ai/glm-5.3-flash` called its
|
|
39
|
+
* tool 0/10 under a response format and 8/8 without one, `z-ai/glm-5.3` 0/5,
|
|
40
|
+
* `deepseek-v4-flash-0731` 0/5, `gemini-3.8-flash` 3/10, while
|
|
41
|
+
* `gemini-3.5-flash-lite`, `gpt-5.6-luna` and `qwen3.8-flash` were 10/10.
|
|
42
|
+
*
|
|
43
|
+
* No default is right for everyone, which is why this stays a setting rather
|
|
44
|
+
* than becoming a rule: the same run put `qwen3.8-flash` at 1/6 with the
|
|
45
|
+
* schema in the prompt against 6/6 with the response format. Don't guess it
|
|
46
|
+
* from the model card — `probeJsonWithTools` asks the model itself, in one
|
|
47
|
+
* call. `StreamOptions.jsonWithTools` overrides this per call.
|
|
48
|
+
*/
|
|
49
|
+
jsonWithTools?: JsonWithTools;
|
|
23
50
|
maxTokens?: number;
|
|
24
51
|
fetchImpl?: typeof fetch;
|
|
25
52
|
headers?: Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,WAAW,EAEX,MAAM,EAEN,QAAQ,EAIT,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;iFAC6E;IAC7E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAID;4EAC4E;AAC5E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,KAAK,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzB;AAmCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,EAAE,CAyD5E;AA+BD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,WAAW,EAEX,MAAM,EAEN,aAAa,EACb,QAAQ,EAIT,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;iFAC6E;IAC7E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAID;4EAC4E;AAC5E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,KAAK,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzB;AAmCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,EAAE,CAyD5E;AA+BD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,CA4LnE"}
|
package/dist/providers/openai.js
CHANGED
|
@@ -204,30 +204,45 @@ export function createOpenAIProvider(config) {
|
|
|
204
204
|
: { type: "function", function: { name: opts.toolChoice.name } };
|
|
205
205
|
}
|
|
206
206
|
if (opts.json) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
207
|
+
// A json request sharing its call with tools is a bet that the model
|
|
208
|
+
// serves both at once, and on several models it silently loses — see
|
|
209
|
+
// `jsonWithTools` on OpenAIConfig for what that costs and what it was
|
|
210
|
+
// measured at. A caller that has measured its own model says so there;
|
|
211
|
+
// here the only job is to leave the response format off those calls, so
|
|
212
|
+
// the schema reaches the model the one way nothing can suppress.
|
|
213
|
+
const promptCarried = tools.length > 0 && (opts.jsonWithTools ?? config.jsonWithTools) === "prompt";
|
|
214
|
+
const enforced = !promptCarried &&
|
|
215
|
+
(config.jsonMode ?? (id === "openai" ? "schema" : "object")) === "schema";
|
|
216
|
+
// Nothing at all on a prompt-carried call: `json_object` pins the
|
|
217
|
+
// decoder every bit as hard as `json_schema` does — 0/8 tool calls on
|
|
218
|
+
// the same model — so half-dropping the format would buy nothing.
|
|
219
|
+
if (!promptCarried) {
|
|
220
|
+
request.response_format = enforced
|
|
221
|
+
? {
|
|
222
|
+
type: "json_schema",
|
|
223
|
+
json_schema: {
|
|
224
|
+
name: opts.json.name,
|
|
225
|
+
schema: opts.json.schema,
|
|
226
|
+
strict: opts.json.strict ?? isStrictSchema(opts.json.schema),
|
|
227
|
+
},
|
|
228
|
+
}
|
|
229
|
+
: // Everything else gets plain JSON mode. Schema ENFORCEMENT is
|
|
230
|
+
// OpenAI's; the gateways and the vendors behind them offer JSON
|
|
231
|
+
// mode at best, and several answer a flat 400 to a `json_schema`
|
|
232
|
+
// block. The seam's rule makes this safe either way: a provider's
|
|
233
|
+
// "guaranteed" JSON is not one, so the caller validates regardless —
|
|
234
|
+
// this only decides whether the request is accepted.
|
|
235
|
+
{ type: "json_object" };
|
|
236
|
+
}
|
|
224
237
|
if (!enforced) {
|
|
225
|
-
// …but
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
//
|
|
238
|
+
// …but nothing left standing carries the shape. `json_object` asks
|
|
239
|
+
// for valid JSON and says NOTHING about what is in it, and a
|
|
240
|
+
// prompt-carried call sends no format at all — either way `opts.json`
|
|
241
|
+
// is half a request: the model returns syntactically perfect JSON of
|
|
242
|
+
// a shape nobody asked for, and the caller's parse fails on the happy
|
|
243
|
+
// path where no retry looks. The schema has to reach the model as
|
|
244
|
+
// prompt — the same promise the Anthropic adapter keeps, for the same
|
|
245
|
+
// reason.
|
|
231
246
|
//
|
|
232
247
|
// Appended rather than folded into the system prompt, because the
|
|
233
248
|
// cache on this shape is a PREFIX cache: a per-call schema placed up
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,yEAAyE;AACzE,+EAA+E;AAC/E,2DAA2D;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -142,6 +142,20 @@ export interface JsonOutput {
|
|
|
142
142
|
*/
|
|
143
143
|
strict?: boolean;
|
|
144
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* How the schema rides on a call that ALSO carries tools.
|
|
147
|
+
*
|
|
148
|
+
* `"response_format"` sends both — what the shapes document, what most models
|
|
149
|
+
* honour. `"prompt"` leaves the format off that call and sends the schema as
|
|
150
|
+
* prompt instead, which is what the Anthropic shape has always done.
|
|
151
|
+
*
|
|
152
|
+
* It is a setting because a model that cannot serve both never says so: its
|
|
153
|
+
* decoder is pinned to the schema, the tool call has nowhere to go, and it
|
|
154
|
+
* writes the announcement instead — "let me look that up" — and stops. Nothing
|
|
155
|
+
* is logged, because nothing failed. `probeJsonWithTools` answers it in one
|
|
156
|
+
* call; there is no default that is right for every model.
|
|
157
|
+
*/
|
|
158
|
+
export type JsonWithTools = "response_format" | "prompt";
|
|
145
159
|
export interface StreamOptions {
|
|
146
160
|
/** Override the provider's bound model for this call. */
|
|
147
161
|
model?: string;
|
|
@@ -168,6 +182,11 @@ export interface StreamOptions {
|
|
|
168
182
|
signal?: AbortSignal;
|
|
169
183
|
toolChoice?: ToolChoice;
|
|
170
184
|
json?: JsonOutput;
|
|
185
|
+
/**
|
|
186
|
+
* Overrides the provider's own setting for this call — how `probeJsonWithTools`
|
|
187
|
+
* asks the same model both ways. See {@link JsonWithTools}.
|
|
188
|
+
*/
|
|
189
|
+
jsonWithTools?: JsonWithTools;
|
|
171
190
|
}
|
|
172
191
|
export interface Provider {
|
|
173
192
|
readonly id: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,2EAA2E;AAC3E,mEAAmE;AACnE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,0BAA0B;AAE1B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAU,CAAC;AAGzE,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AACpD,CAAC;AA4GD,MAAM,CAAC,MAAM,WAAW,GAAe;IACrC,WAAW,EAAE,CAAC;IACd,iBAAiB,EAAE,CAAC;IACpB,YAAY,EAAE,CAAC;CAChB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,2EAA2E;AAC3E,mEAAmE;AACnE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,0BAA0B;AAE1B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAU,CAAC;AAGzE,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AACpD,CAAC;AA4GD,MAAM,CAAC,MAAM,WAAW,GAAe;IACrC,WAAW,EAAE,CAAC;IACd,iBAAiB,EAAE,CAAC;IACpB,YAAY,EAAE,CAAC;CAChB,CAAC;AAwGF;kEACkE;AAClE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAoC,EACpC,KAAa;IAEb,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,4EAA4E;IAC5E,4EAA4E;IAC5E,yEAAyE;IACzE,6DAA6D;IAC7D,IAAI,gBAAuC,CAAC;IAC5C,IAAI,KAAK,GAAe,WAAW,CAAC;IACpC,IAAI,YAAY,GAAwB,IAAI,CAAC;IAC7C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,OAAO;gBAAE,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC;YACzC,IAAI,KAAK,CAAC,SAAS;gBAAE,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;YAClD,IAAI,KAAK,CAAC,gBAAgB,EAAE,MAAM;gBAAE,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;QAChF,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACjD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACtB,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACzD,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QACpC,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI;QACJ,SAAS;QACT,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,KAAK;QACL,YAAY;QACZ,KAAK;KACN,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgC;IAC7D,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,OAAO,CAAC;QACjD,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,gBAAgB,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC;QAC9F,yEAAyE;QACzE,yEAAyE;QACzE,iEAAiE;QACjE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;QAC1E,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CAAC,IAAe;IACvC,OAAO,QAAQ,IAAI,CAAC,QAAQ,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Asking a model what it can actually do, instead of reading its model card.
|
|
2
|
+
//
|
|
3
|
+
// One capability needs this badly enough to ship a prober: whether a model
|
|
4
|
+
// still emits a tool call when the same request also constrains its output to
|
|
5
|
+
// a schema. Most do. Several — measured 2026-09-07: `z-ai/glm-5.3-flash`,
|
|
6
|
+
// `z-ai/glm-5.3`, `deepseek-v4-flash` — never do, and they fail in the worst
|
|
7
|
+
// available way. The decoder is pinned to the schema, the tool call has nowhere
|
|
8
|
+
// to go, and the model writes the announcement instead ("let me look that up
|
|
9
|
+
// for you") and stops. No error, no warning, no finish reason to branch on: on
|
|
10
|
+
// the wire the turn succeeded. Downstream it reads as a model that will not use
|
|
11
|
+
// its tools, and no amount of prompting moves it, because the call was never
|
|
12
|
+
// representable.
|
|
13
|
+
//
|
|
14
|
+
// `jsonWithTools: "prompt"` is the remedy, and it cannot be a default: the same
|
|
15
|
+
// run put `qwen3.8-flash` at 10/10 with the response format and 1/6 without it,
|
|
16
|
+
// so a global flip only moves the silence to different models. One call each
|
|
17
|
+
// way settles it for the model actually being served.
|
|
18
|
+
|
|
19
|
+
import type { JsonWithTools, Provider } from "./types.ts";
|
|
20
|
+
|
|
21
|
+
/** Nothing a model can answer from memory — so a tool call is the only correct
|
|
22
|
+
* turn, and NOT making one is a real signal rather than a judgement call. */
|
|
23
|
+
const PROBE_TOOL = {
|
|
24
|
+
name: "get_current_time",
|
|
25
|
+
description:
|
|
26
|
+
"The only source of the current time. You cannot know the time without calling this — never answer a time question from memory or guess.",
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: "object" as const,
|
|
29
|
+
properties: { timezone: { type: "string", description: "IANA timezone, e.g. Asia/Tokyo" } },
|
|
30
|
+
required: [],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const PROBE_JSON = {
|
|
35
|
+
name: "probe",
|
|
36
|
+
schema: {
|
|
37
|
+
type: "object" as const,
|
|
38
|
+
properties: { message: { type: "string", description: "Your reply to the user." } },
|
|
39
|
+
required: ["message"],
|
|
40
|
+
additionalProperties: false,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const SHAPES: JsonWithTools[] = ["response_format", "prompt"];
|
|
45
|
+
|
|
46
|
+
export interface JsonWithToolsProbe {
|
|
47
|
+
/**
|
|
48
|
+
* The shape to configure, or `null` when neither called the tool on every
|
|
49
|
+
* sample — that model cannot be trusted with tools and a schema together,
|
|
50
|
+
* whichever way the schema rides, and the honest fix is a different model.
|
|
51
|
+
*/
|
|
52
|
+
use: JsonWithTools | null;
|
|
53
|
+
/** Samples that produced a tool call, per shape, out of `samples`. */
|
|
54
|
+
calls: Record<JsonWithTools, number>;
|
|
55
|
+
/** How many times each shape was asked. */
|
|
56
|
+
samples: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ProbeOptions {
|
|
60
|
+
/**
|
|
61
|
+
* Samples per shape. Above one because the interesting failures are partial —
|
|
62
|
+
* `gemini-3.8-flash` called its tool 3/10 — and a single sample reports a
|
|
63
|
+
* coin flip as a capability. A shape passes only when EVERY sample calls.
|
|
64
|
+
*/
|
|
65
|
+
samples?: number;
|
|
66
|
+
/** Override the provider's bound model, to probe one it is not built for. */
|
|
67
|
+
model?: string;
|
|
68
|
+
signal?: AbortSignal;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function callsTool(
|
|
72
|
+
provider: Provider,
|
|
73
|
+
shape: JsonWithTools,
|
|
74
|
+
opts: ProbeOptions,
|
|
75
|
+
): Promise<boolean> {
|
|
76
|
+
const stream = provider.createStream(
|
|
77
|
+
[{ role: "user", content: "What time is it in Tokyo right now?" }],
|
|
78
|
+
[PROBE_TOOL],
|
|
79
|
+
{
|
|
80
|
+
json: PROBE_JSON,
|
|
81
|
+
jsonWithTools: shape,
|
|
82
|
+
// Deterministic, so a rerun of the probe answers the same way.
|
|
83
|
+
temperature: 0,
|
|
84
|
+
...(opts.model ? { model: opts.model } : {}),
|
|
85
|
+
...(opts.signal ? { signal: opts.signal } : {}),
|
|
86
|
+
},
|
|
87
|
+
);
|
|
88
|
+
// No token cap: on a thinking model a small one is spent before the answer
|
|
89
|
+
// starts, and an empty completion would read here as "did not call the tool".
|
|
90
|
+
for await (const chunk of stream) {
|
|
91
|
+
if (chunk.toolCalls?.some((call) => call.name)) return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Ask a model, on the wire, which {@link JsonWithTools} shape it actually
|
|
98
|
+
* serves — then configure the provider with `probe.use`.
|
|
99
|
+
*
|
|
100
|
+
* Both shapes are always tried, because a result you can read beats a result
|
|
101
|
+
* you have to trust: `calls` is the table to log, and "0/3 and 3/3" is what
|
|
102
|
+
* makes a later regression obvious. It costs `samples × 2` short calls, once,
|
|
103
|
+
* at whatever moment the app decides to ask — boot is the usual one.
|
|
104
|
+
*
|
|
105
|
+
* Errors propagate. A probe that swallowed a bad key or a dead endpoint would
|
|
106
|
+
* report "this model cannot call tools", which is a much worse thing to
|
|
107
|
+
* believe than "the call failed".
|
|
108
|
+
*
|
|
109
|
+
* What it catches is the structural failure — the model that CANNOT emit the
|
|
110
|
+
* call, every time, on the easiest question there is. A model that is merely
|
|
111
|
+
* unreliable will pass: `gemini-3.8-flash` answers this probe 3/3 and a real
|
|
112
|
+
* sales turn 3/10. That is the right line to draw. A harder probe would start
|
|
113
|
+
* failing good models for being terse, and "sometimes forgets its tools" is a
|
|
114
|
+
* prompt and eval problem, not a wire shape one.
|
|
115
|
+
*
|
|
116
|
+
* ```ts
|
|
117
|
+
* const probe = await probeJsonWithTools(provider);
|
|
118
|
+
* if (!probe.use) throw new Error(`${model} cannot use tools with a schema`);
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export async function probeJsonWithTools(
|
|
122
|
+
provider: Provider,
|
|
123
|
+
opts: ProbeOptions = {},
|
|
124
|
+
): Promise<JsonWithToolsProbe> {
|
|
125
|
+
const samples = Math.max(1, opts.samples ?? 3);
|
|
126
|
+
|
|
127
|
+
const counted = await Promise.all(
|
|
128
|
+
SHAPES.map(async (shape) => {
|
|
129
|
+
const runs = await Promise.all(
|
|
130
|
+
Array.from({ length: samples }, () => callsTool(provider, shape, opts)),
|
|
131
|
+
);
|
|
132
|
+
return [shape, runs.filter(Boolean).length] as const;
|
|
133
|
+
}),
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const calls = Object.fromEntries(counted) as Record<JsonWithTools, number>;
|
|
137
|
+
// `response_format` first when both are clean: it is the only one of the two
|
|
138
|
+
// the endpoint actually enforces, so the prompt shape is the fallback rather
|
|
139
|
+
// than the equal.
|
|
140
|
+
return { use: SHAPES.find((shape) => calls[shape] === samples) ?? null, calls, samples };
|
|
141
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./tool-args.ts";
|
|
|
10
10
|
export * from "./tools.ts";
|
|
11
11
|
export * from "./schema.ts";
|
|
12
12
|
export * from "./context.ts";
|
|
13
|
+
export * from "./capability.ts";
|
|
13
14
|
export * from "./providers/anthropic.ts";
|
|
14
15
|
export * from "./providers/openai.ts";
|
|
15
16
|
export * from "./providers/responses.ts";
|
package/src/providers/gemini.ts
CHANGED
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
// wire rather than @google/genai, because this package ships zero dependencies
|
|
7
7
|
// and the SDK is a Node-shaped one.
|
|
8
8
|
import { streamError } from "../errors.ts";
|
|
9
|
+
import { schemaPrompt } from "../schema.ts";
|
|
9
10
|
import { parseToolArgs } from "../tool-args.ts";
|
|
10
11
|
import { streamSse, apiUrl } from "../transport.ts";
|
|
11
12
|
import type {
|
|
12
13
|
ChatMessage,
|
|
13
14
|
Effort,
|
|
14
15
|
FinishReason,
|
|
16
|
+
JsonWithTools,
|
|
15
17
|
Provider,
|
|
16
18
|
ProviderChunk,
|
|
17
19
|
StreamOptions,
|
|
@@ -34,6 +36,15 @@ export interface GeminiConfig {
|
|
|
34
36
|
id?: string;
|
|
35
37
|
/** Bound default; a per-call `effort` overrides it. */
|
|
36
38
|
effort?: Effort;
|
|
39
|
+
/**
|
|
40
|
+
* How the schema rides on a call that also carries tools. See
|
|
41
|
+
* {@link JsonWithTools} — and note that it is the MODEL's answer, not the
|
|
42
|
+
* endpoint's: measured 2026-09-07, `gemini-3.5-flash` and
|
|
43
|
+
* `gemini-3.5-flash-lite` called their tool under `responseJsonSchema` every
|
|
44
|
+
* time, while `gemini-3.8-flash` managed 3/10. `probeJsonWithTools` asks the
|
|
45
|
+
* one you actually serve. Overridable per call.
|
|
46
|
+
*/
|
|
47
|
+
jsonWithTools?: JsonWithTools;
|
|
37
48
|
maxTokens?: number;
|
|
38
49
|
fetchImpl?: typeof fetch;
|
|
39
50
|
headers?: Record<string, string>;
|
|
@@ -258,7 +269,13 @@ export function createGeminiProvider(config: GeminiConfig): Provider {
|
|
|
258
269
|
// would switch that off for a caller who never asked, which is the whole
|
|
259
270
|
// reason the seam treats an absent effort as "never sent".
|
|
260
271
|
if (effort) generationConfig.thinkingConfig = { thinkingLevel: THINKING_LEVEL[effort] };
|
|
261
|
-
|
|
272
|
+
// A schema that shares its call with tools pins the decoder, and a pinned
|
|
273
|
+
// decoder cannot emit a functionCall — the model narrates the call it
|
|
274
|
+
// could not make and the turn ends, with nothing logged. See
|
|
275
|
+
// `jsonWithTools` for what that costs and which models it costs it on.
|
|
276
|
+
const promptCarried =
|
|
277
|
+
tools.length > 0 && (opts.jsonWithTools ?? config.jsonWithTools) === "prompt";
|
|
278
|
+
if (opts.json && !promptCarried) {
|
|
262
279
|
generationConfig.responseMimeType = "application/json";
|
|
263
280
|
// `responseJsonSchema` takes JSON Schema as written; `responseSchema`
|
|
264
281
|
// is Gemini's own trimmed dialect and rejects most of what a real
|
|
@@ -268,7 +285,14 @@ export function createGeminiProvider(config: GeminiConfig): Provider {
|
|
|
268
285
|
|
|
269
286
|
const request: Record<string, unknown> = { contents, generationConfig };
|
|
270
287
|
// A Content, not the bare string the SDK accepts — REST rejects a string.
|
|
271
|
-
|
|
288
|
+
// The prompt-carried schema rides as a second part, after the caller's
|
|
289
|
+
// own text: this shape's cache is a prefix too, so a per-call schema in
|
|
290
|
+
// front of the conversation would cold-start it on every change.
|
|
291
|
+
const systemParts = [
|
|
292
|
+
...(system ? [{ text: system }] : []),
|
|
293
|
+
...(opts.json && promptCarried ? [{ text: schemaPrompt(opts.json.schema) }] : []),
|
|
294
|
+
];
|
|
295
|
+
if (systemParts.length > 0) request.systemInstruction = { parts: systemParts };
|
|
272
296
|
if (tools.length > 0) {
|
|
273
297
|
request.tools = [
|
|
274
298
|
{
|
package/src/providers/openai.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
ContentPart,
|
|
11
11
|
Effort,
|
|
12
12
|
FinishReason,
|
|
13
|
+
JsonWithTools,
|
|
13
14
|
Provider,
|
|
14
15
|
ProviderChunk,
|
|
15
16
|
StreamOptions,
|
|
@@ -39,6 +40,33 @@ export interface OpenAIConfig {
|
|
|
39
40
|
* is the only setting every gateway accepts.
|
|
40
41
|
*/
|
|
41
42
|
jsonMode?: "schema" | "object";
|
|
43
|
+
/**
|
|
44
|
+
* How a json request rides when the SAME call also carries tools.
|
|
45
|
+
*
|
|
46
|
+
* `response_format` — the default — sends both, which is what the shape
|
|
47
|
+
* documents and what most models honour. `prompt` drops the response format
|
|
48
|
+
* from those calls only and sends the schema as prompt instead: the shape the
|
|
49
|
+
* Anthropic adapter has always used, and the reason this failure cannot
|
|
50
|
+
* happen there.
|
|
51
|
+
*
|
|
52
|
+
* It needs a knob because a model that cannot serve both does not say so. Its
|
|
53
|
+
* decoder is pinned to the schema, the tool call has nowhere to go, and the
|
|
54
|
+
* model writes the announcement instead — "let me look that up for you" — and
|
|
55
|
+
* the turn ends looking like a model with no initiative rather than a request
|
|
56
|
+
* that made the call impossible. Nothing is logged, because nothing failed.
|
|
57
|
+
*
|
|
58
|
+
* Measured 2026-09-07, one request, sampled: `z-ai/glm-5.3-flash` called its
|
|
59
|
+
* tool 0/10 under a response format and 8/8 without one, `z-ai/glm-5.3` 0/5,
|
|
60
|
+
* `deepseek-v4-flash-0731` 0/5, `gemini-3.8-flash` 3/10, while
|
|
61
|
+
* `gemini-3.5-flash-lite`, `gpt-5.6-luna` and `qwen3.8-flash` were 10/10.
|
|
62
|
+
*
|
|
63
|
+
* No default is right for everyone, which is why this stays a setting rather
|
|
64
|
+
* than becoming a rule: the same run put `qwen3.8-flash` at 1/6 with the
|
|
65
|
+
* schema in the prompt against 6/6 with the response format. Don't guess it
|
|
66
|
+
* from the model card — `probeJsonWithTools` asks the model itself, in one
|
|
67
|
+
* call. `StreamOptions.jsonWithTools` overrides this per call.
|
|
68
|
+
*/
|
|
69
|
+
jsonWithTools?: JsonWithTools;
|
|
42
70
|
maxTokens?: number;
|
|
43
71
|
fetchImpl?: typeof fetch;
|
|
44
72
|
headers?: Record<string, string>;
|
|
@@ -293,30 +321,47 @@ export function createOpenAIProvider(config: OpenAIConfig): Provider {
|
|
|
293
321
|
: { type: "function", function: { name: opts.toolChoice.name } };
|
|
294
322
|
}
|
|
295
323
|
if (opts.json) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
{
|
|
324
|
+
// A json request sharing its call with tools is a bet that the model
|
|
325
|
+
// serves both at once, and on several models it silently loses — see
|
|
326
|
+
// `jsonWithTools` on OpenAIConfig for what that costs and what it was
|
|
327
|
+
// measured at. A caller that has measured its own model says so there;
|
|
328
|
+
// here the only job is to leave the response format off those calls, so
|
|
329
|
+
// the schema reaches the model the one way nothing can suppress.
|
|
330
|
+
const promptCarried =
|
|
331
|
+
tools.length > 0 && (opts.jsonWithTools ?? config.jsonWithTools) === "prompt";
|
|
332
|
+
const enforced =
|
|
333
|
+
!promptCarried &&
|
|
334
|
+
(config.jsonMode ?? (id === "openai" ? "schema" : "object")) === "schema";
|
|
335
|
+
// Nothing at all on a prompt-carried call: `json_object` pins the
|
|
336
|
+
// decoder every bit as hard as `json_schema` does — 0/8 tool calls on
|
|
337
|
+
// the same model — so half-dropping the format would buy nothing.
|
|
338
|
+
if (!promptCarried) {
|
|
339
|
+
request.response_format = enforced
|
|
340
|
+
? {
|
|
341
|
+
type: "json_schema",
|
|
342
|
+
json_schema: {
|
|
343
|
+
name: opts.json.name,
|
|
344
|
+
schema: opts.json.schema,
|
|
345
|
+
strict: opts.json.strict ?? isStrictSchema(opts.json.schema),
|
|
346
|
+
},
|
|
347
|
+
}
|
|
348
|
+
: // Everything else gets plain JSON mode. Schema ENFORCEMENT is
|
|
349
|
+
// OpenAI's; the gateways and the vendors behind them offer JSON
|
|
350
|
+
// mode at best, and several answer a flat 400 to a `json_schema`
|
|
351
|
+
// block. The seam's rule makes this safe either way: a provider's
|
|
352
|
+
// "guaranteed" JSON is not one, so the caller validates regardless —
|
|
353
|
+
// this only decides whether the request is accepted.
|
|
354
|
+
{ type: "json_object" };
|
|
355
|
+
}
|
|
313
356
|
if (!enforced) {
|
|
314
|
-
// …but
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
//
|
|
319
|
-
//
|
|
357
|
+
// …but nothing left standing carries the shape. `json_object` asks
|
|
358
|
+
// for valid JSON and says NOTHING about what is in it, and a
|
|
359
|
+
// prompt-carried call sends no format at all — either way `opts.json`
|
|
360
|
+
// is half a request: the model returns syntactically perfect JSON of
|
|
361
|
+
// a shape nobody asked for, and the caller's parse fails on the happy
|
|
362
|
+
// path where no retry looks. The schema has to reach the model as
|
|
363
|
+
// prompt — the same promise the Anthropic adapter keeps, for the same
|
|
364
|
+
// reason.
|
|
320
365
|
//
|
|
321
366
|
// Appended rather than folded into the system prompt, because the
|
|
322
367
|
// cache on this shape is a PREFIX cache: a per-call schema placed up
|
package/src/types.ts
CHANGED
|
@@ -170,6 +170,21 @@ export interface JsonOutput {
|
|
|
170
170
|
strict?: boolean;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
/**
|
|
174
|
+
* How the schema rides on a call that ALSO carries tools.
|
|
175
|
+
*
|
|
176
|
+
* `"response_format"` sends both — what the shapes document, what most models
|
|
177
|
+
* honour. `"prompt"` leaves the format off that call and sends the schema as
|
|
178
|
+
* prompt instead, which is what the Anthropic shape has always done.
|
|
179
|
+
*
|
|
180
|
+
* It is a setting because a model that cannot serve both never says so: its
|
|
181
|
+
* decoder is pinned to the schema, the tool call has nowhere to go, and it
|
|
182
|
+
* writes the announcement instead — "let me look that up" — and stops. Nothing
|
|
183
|
+
* is logged, because nothing failed. `probeJsonWithTools` answers it in one
|
|
184
|
+
* call; there is no default that is right for every model.
|
|
185
|
+
*/
|
|
186
|
+
export type JsonWithTools = "response_format" | "prompt";
|
|
187
|
+
|
|
173
188
|
export interface StreamOptions {
|
|
174
189
|
/** Override the provider's bound model for this call. */
|
|
175
190
|
model?: string;
|
|
@@ -196,6 +211,11 @@ export interface StreamOptions {
|
|
|
196
211
|
signal?: AbortSignal;
|
|
197
212
|
toolChoice?: ToolChoice;
|
|
198
213
|
json?: JsonOutput;
|
|
214
|
+
/**
|
|
215
|
+
* Overrides the provider's own setting for this call — how `probeJsonWithTools`
|
|
216
|
+
* asks the same model both ways. See {@link JsonWithTools}.
|
|
217
|
+
*/
|
|
218
|
+
jsonWithTools?: JsonWithTools;
|
|
199
219
|
}
|
|
200
220
|
|
|
201
221
|
export interface Provider {
|