diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 7f3b72d0..b72f4718 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Fixed OpenAI Responses custom providers to honor `compat.supportsDeveloperRole: false` for reasoning models ([#5456](https://github.com/earendil-works/pi/issues/5456)). - Fixed OpenRouter routing preferences on OpenAI-compatible custom providers to send `compat.openRouterRouting` even when `baseUrl` does not point directly at OpenRouter ([#5347](https://github.com/earendil-works/pi/issues/5347)). ## [0.78.1] - 2026-06-04 diff --git a/packages/ai/README.md b/packages/ai/README.md index 6be70212..4190fcb8 100644 --- a/packages/ai/README.md +++ b/packages/ai/README.md @@ -926,7 +926,7 @@ const ollamaReasoningModel: Model<'openai-completions'> = { ### OpenAI Compatibility Settings -The `openai-completions` API is implemented by many providers with minor differences. By default, the library auto-detects compatibility settings based on `baseUrl` for a small set of known OpenAI-compatible providers (Cerebras, xAI, Chutes, DeepSeek, NVIDIA NIM, Together AI, zAi, OpenCode, Cloudflare Workers AI, etc.). For custom proxies or unknown endpoints, you can override these settings via the `compat` field. For `openai-responses` models, the compat field only supports Responses-specific flags. +The `openai-completions` API is implemented by many providers with minor differences. By default, the library auto-detects compatibility settings based on `baseUrl` for a small set of known OpenAI-compatible providers (Cerebras, xAI, Chutes, DeepSeek, NVIDIA NIM, Together AI, zAi, OpenCode, Cloudflare Workers AI, etc.). For custom proxies or unknown endpoints, you can override these settings via the `compat` field. For `openai-responses` models, the compat field supports Responses-specific flags. ```typescript interface OpenAICompletionsCompat { @@ -948,7 +948,9 @@ interface OpenAICompletionsCompat { } interface OpenAIResponsesCompat { - // Reserved for future use + supportsDeveloperRole?: boolean; // Whether provider supports `developer` role vs `system` (default: true) + sendSessionIdHeader?: boolean; // Whether to send `session_id` from `sessionId` when caching is enabled (default: true) + supportsLongCacheRetention?: boolean; // Whether provider supports `prompt_cache_retention: "24h"` (default: true) } ``` diff --git a/packages/ai/src/providers/openai-responses-shared.ts b/packages/ai/src/providers/openai-responses-shared.ts index 11a977d5..c006c284 100644 --- a/packages/ai/src/providers/openai-responses-shared.ts +++ b/packages/ai/src/providers/openai-responses-shared.ts @@ -124,7 +124,8 @@ export function convertResponsesMessages( const includeSystemPrompt = options?.includeSystemPrompt ?? true; if (includeSystemPrompt && context.systemPrompt) { - const role = model.reasoning ? "developer" : "system"; + const compat = model.compat as { supportsDeveloperRole?: boolean } | undefined; + const role = model.reasoning && compat?.supportsDeveloperRole !== false ? "developer" : "system"; messages.push({ role, content: sanitizeSurrogates(context.systemPrompt), diff --git a/packages/ai/src/providers/openai-responses.ts b/packages/ai/src/providers/openai-responses.ts index 4b35a24c..9afeff29 100644 --- a/packages/ai/src/providers/openai-responses.ts +++ b/packages/ai/src/providers/openai-responses.ts @@ -39,6 +39,7 @@ function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention function getCompat(model: Model<"openai-responses">): Required { return { + supportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true, sendSessionIdHeader: model.compat?.sendSessionIdHeader ?? true, supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true, }; diff --git a/packages/ai/src/types.ts b/packages/ai/src/types.ts index ed36c7ec..802b8b39 100644 --- a/packages/ai/src/types.ts +++ b/packages/ai/src/types.ts @@ -421,6 +421,8 @@ export interface OpenAICompletionsCompat { /** Compatibility settings for OpenAI Responses APIs. */ 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; /** Whether the provider supports `prompt_cache_retention: "24h"`. Default: true. */ diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 707281c0..c0d45312 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -10,6 +10,7 @@ ### Fixed +- Fixed `models.json` schema support for OpenAI Responses `compat.supportsDeveloperRole` ([#5456](https://github.com/earendil-works/pi/issues/5456)). - Fixed tmux setup documentation to require tmux 3.5 for `extended-keys-format csi-u` and document the tmux 3.2-3.4 fallback ([#5432](https://github.com/earendil-works/pi/issues/5432)). - Fixed built-in tool expand hints to style closing parentheses consistently ([#5359](https://github.com/earendil-works/pi/issues/5359)). diff --git a/packages/coding-agent/src/core/model-registry.ts b/packages/coding-agent/src/core/model-registry.ts index 455ab71f..00c81576 100644 --- a/packages/coding-agent/src/core/model-registry.ts +++ b/packages/coding-agent/src/core/model-registry.ts @@ -127,6 +127,7 @@ const OpenAICompletionsCompatSchema = Type.Object({ }); const OpenAIResponsesCompatSchema = Type.Object({ + supportsDeveloperRole: Type.Optional(Type.Boolean()), sendSessionIdHeader: Type.Optional(Type.Boolean()), supportsLongCacheRetention: Type.Optional(Type.Boolean()), });