Files
HealthLog/src/lib/ai/openai-capabilities.ts
T
Marc-André Bombeck 316e52dee3 Widen the Coach turn budget and keep its rounds on the prompt cache
Own-plan turns get 165k tokens, 200 s and 16 rounds, operator turns 55k,
120 s and 8; the final-answer reserve, the concurrent-turn slot and the
step cap move with them.

Codex requests carry a per-conversation prompt_cache_key and a stable
session id, api.openai.com gets the same key, Anthropic usage counts
cache reads and writes in the gross, and local servers report cached
prompt tokens, so the turn budget discounts cached input on every
provider.
2026-10-07 22:48:48 +02:00

68 lines
1.9 KiB
TypeScript

export type OpenAIChatCompletionsCapabilities =
| {
tokenBudgetField: "max_completion_tokens";
supportsSamplingControls: false;
}
| {
tokenBudgetField: "max_tokens";
supportsSamplingControls: true;
};
const MODERN_CANONICAL_CAPABILITIES = {
tokenBudgetField: "max_completion_tokens",
supportsSamplingControls: false,
} as const;
const LEGACY_COMPATIBLE_CAPABILITIES = {
tokenBudgetField: "max_tokens",
supportsSamplingControls: true,
} as const;
function isModernCanonicalModel(model: string): boolean {
const normalizedModel = model.toLowerCase();
return (
normalizedModel === "gpt-5" ||
normalizedModel.startsWith("gpt-5-") ||
normalizedModel.startsWith("gpt-5.") ||
normalizedModel === "o1" ||
normalizedModel.startsWith("o1-") ||
normalizedModel === "o3" ||
normalizedModel.startsWith("o3-") ||
normalizedModel === "o4" ||
normalizedModel.startsWith("o4-")
);
}
export function isCanonicalOpenAIEndpoint(baseUrl: string): boolean {
try {
const url = new URL(baseUrl);
return (
url.protocol === "https:" &&
url.hostname === "api.openai.com" &&
url.port === "" &&
url.pathname.replace(/\/+$/, "") === "/v1" &&
url.username === "" &&
url.password === "" &&
url.search === "" &&
url.hash === ""
);
} catch {
return false;
}
}
/**
* Select Chat Completions request capabilities from both endpoint and model.
* Custom OpenAI-compatible gateways retain the broadly supported legacy wire,
* even when their model name resembles a modern OpenAI model.
*/
export function selectOpenAIChatCompletionsCapabilities(
baseUrl: string,
model: string,
): OpenAIChatCompletionsCapabilities {
return isCanonicalOpenAIEndpoint(baseUrl) && isModernCanonicalModel(model)
? MODERN_CANONICAL_CAPABILITIES
: LEGACY_COMPATIBLE_CAPABILITIES;
}