@@ -519,9 +519,15 @@ function createClient(
|
||||
}
|
||||
|
||||
if (sessionId && compat.sendSessionAffinityHeaders) {
|
||||
headers.session_id = sessionId;
|
||||
headers["x-client-request-id"] = sessionId;
|
||||
headers["x-session-affinity"] = sessionId;
|
||||
if (compat.sessionAffinityFormat === "openrouter") {
|
||||
headers["x-session-id"] = sessionId;
|
||||
} else {
|
||||
if (compat.sessionAffinityFormat === "openai") {
|
||||
headers.session_id = sessionId;
|
||||
}
|
||||
headers["x-client-request-id"] = sessionId;
|
||||
headers["x-session-affinity"] = sessionId;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge options headers last so they can override defaults
|
||||
@@ -1250,6 +1256,7 @@ function detectCompat(model: Model<"openai-completions">): ResolvedOpenAIComplet
|
||||
supportsStrictMode: !isMoonshot && !isTogether && !isCloudflareAiGateway && !isNvidia,
|
||||
cacheControlFormat,
|
||||
sendSessionAffinityHeaders: false,
|
||||
sessionAffinityFormat: isOpenRouter ? "openrouter" : "openai",
|
||||
supportsLongCacheRetention: !(
|
||||
isTogether ||
|
||||
isCloudflareWorkersAI ||
|
||||
@@ -1289,6 +1296,7 @@ function getCompat(model: Model<"openai-completions">): ResolvedOpenAICompletion
|
||||
supportsStrictMode: model.compat.supportsStrictMode ?? detected.supportsStrictMode,
|
||||
cacheControlFormat: model.compat.cacheControlFormat ?? detected.cacheControlFormat,
|
||||
sendSessionAffinityHeaders: model.compat.sendSessionAffinityHeaders ?? detected.sendSessionAffinityHeaders,
|
||||
sessionAffinityFormat: model.compat.sessionAffinityFormat ?? detected.sessionAffinityFormat,
|
||||
supportsLongCacheRetention: model.compat.supportsLongCacheRetention ?? detected.supportsLongCacheRetention,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ function getClientApiKey(provider: string, apiKey: string | undefined, headers:
|
||||
throw new Error(`No API key for provider: ${provider}`);
|
||||
}
|
||||
|
||||
function detectSessionAffinityFormat(model: Pick<Model<"openai-responses">, "provider" | "baseUrl">) {
|
||||
return model.provider === "openrouter" || model.baseUrl.includes("openrouter.ai") ? "openrouter" : "openai";
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve cache retention preference.
|
||||
* Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
|
||||
@@ -61,7 +65,7 @@ function resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEn
|
||||
function getCompat(model: Model<"openai-responses">): Required<OpenAIResponsesCompat> {
|
||||
return {
|
||||
supportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,
|
||||
sendSessionIdHeader: model.compat?.sendSessionIdHeader ?? true,
|
||||
sessionAffinityFormat: model.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model),
|
||||
supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,
|
||||
supportsToolSearch: model.compat?.supportsToolSearch ?? false,
|
||||
};
|
||||
@@ -203,10 +207,14 @@ function createClient(
|
||||
}
|
||||
|
||||
if (sessionId) {
|
||||
if (compat.sendSessionIdHeader) {
|
||||
headers.session_id = sessionId;
|
||||
if (compat.sessionAffinityFormat === "openrouter") {
|
||||
headers["x-session-id"] = sessionId;
|
||||
} else {
|
||||
if (compat.sessionAffinityFormat === "openai") {
|
||||
headers.session_id = sessionId;
|
||||
}
|
||||
headers["x-client-request-id"] = sessionId;
|
||||
}
|
||||
headers["x-client-request-id"] = sessionId;
|
||||
}
|
||||
|
||||
// Merge options headers last so they can override defaults
|
||||
|
||||
@@ -100,6 +100,7 @@ export type Transport = "sse" | "websocket" | "websocket-cached" | "auto";
|
||||
/** Provider-scoped environment overrides. Values take precedence over process.env. */
|
||||
export type ProviderEnv = Record<string, string>;
|
||||
export type ProviderHeaders = Record<string, string | null>;
|
||||
export type SessionAffinityFormat = "openai" | "openai-nosession" | "openrouter";
|
||||
|
||||
export interface ProviderResponse {
|
||||
status: number;
|
||||
@@ -517,8 +518,10 @@ export interface OpenAICompletionsCompat {
|
||||
supportsStrictMode?: boolean;
|
||||
/** Cache control convention for prompt caching. "anthropic" applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user/assistant text content. */
|
||||
cacheControlFormat?: "anthropic";
|
||||
/** Whether to send known session-affinity headers (`session_id`, `x-client-request-id`, `x-session-affinity`) from `options.sessionId` when caching is enabled. Default: false. */
|
||||
/** Whether to send session-affinity data from `options.sessionId`. Default: false. */
|
||||
sendSessionAffinityHeaders?: boolean;
|
||||
/** Session-affinity header format: `openai` sends `session_id`, `x-client-request-id`, and `x-session-affinity`; `openai-nosession` sends `x-client-request-id` and `x-session-affinity`; `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param, which is governed by cache retention. Default: auto-detected. */
|
||||
sessionAffinityFormat?: SessionAffinityFormat;
|
||||
/** Whether the provider supports long prompt cache retention (`prompt_cache_retention: "24h"` or Anthropic-style `cache_control.ttl: "1h"`, depending on format). Default: true. */
|
||||
supportsLongCacheRetention?: boolean;
|
||||
}
|
||||
@@ -527,8 +530,8 @@ export interface OpenAICompletionsCompat {
|
||||
export interface OpenAIResponsesCompat {
|
||||
/** Whether the provider supports the `developer` role (vs `system`). Default: true. */
|
||||
supportsDeveloperRole?: boolean;
|
||||
/** Whether to send the OpenAI `session_id` cache-affinity header from `options.sessionId` when caching is enabled. Default: true. */
|
||||
sendSessionIdHeader?: boolean;
|
||||
/** Session-affinity header format: `openai` sends `session_id` and `x-client-request-id`; `openai-nosession` sends `x-client-request-id`; `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param, which is governed by cache retention. Default: auto-detected. */
|
||||
sessionAffinityFormat?: SessionAffinityFormat;
|
||||
/** Whether the provider supports `prompt_cache_retention: "24h"`. Default: true. */
|
||||
supportsLongCacheRetention?: boolean;
|
||||
/** Whether the model supports client-executed tool search for deferred tools. Default: false. */
|
||||
|
||||
Reference in New Issue
Block a user