From ffeb6a13217021dfce3a0cfd1d57fdc70e0ca30c Mon Sep 17 00:00:00 2001 From: Filip Stastny Date: Sat, 3 Oct 2026 23:03:10 +0200 Subject: [PATCH 1/4] fix(agents): preserve extended reasoning effort levels --- .../__tests__/codemie-code-reasoning.test.ts | 8 +++++ .../__tests__/opencode-gpt55-routing.test.ts | 13 +++++++ src/agents/plugins/codemie-code.plugin.ts | 8 +++++ .../opencode/opencode-dynamic-models.ts | 4 ++- .../opencode/opencode-model-configs.ts | 28 +++++++++++++++ src/agents/plugins/pi/pi.models.ts | 4 +-- tmp/opencode-max-effort-level.md | 36 +++++++++++++++++++ 7 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 tmp/opencode-max-effort-level.md diff --git a/src/agents/plugins/__tests__/codemie-code-reasoning.test.ts b/src/agents/plugins/__tests__/codemie-code-reasoning.test.ts index f64c30ff3..c66b9d809 100644 --- a/src/agents/plugins/__tests__/codemie-code-reasoning.test.ts +++ b/src/agents/plugins/__tests__/codemie-code-reasoning.test.ts @@ -134,6 +134,14 @@ describe('CodeMie Code Plugin — Reasoning Sanitization Integration', () => { const beforeRun = CodeMieCodePluginMetadata.lifecycle!.beforeRun!; const onSessionEnd = CodeMieCodePluginMetadata.lifecycle!.onSessionEnd!; + it('declares the complete reasoning-effort range for OpenCode forwarding', () => { + expect(CodeMieCodePluginMetadata.reasoningEffort).toMatchObject({ + strategy: 'cli-flag', + flag: '--variant', + supportedLevels: ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'], + }); + }); + beforeEach(() => { vi.clearAllMocks(); mockDiscoverSessions.mockResolvedValue([]); diff --git a/src/agents/plugins/__tests__/opencode-gpt55-routing.test.ts b/src/agents/plugins/__tests__/opencode-gpt55-routing.test.ts index b415963df..76c095fdb 100644 --- a/src/agents/plugins/__tests__/opencode-gpt55-routing.test.ts +++ b/src/agents/plugins/__tests__/opencode-gpt55-routing.test.ts @@ -150,6 +150,13 @@ describe('GPT-5.6 → Responses API routing', () => { expect(config.limit.context).toBe(1050000); }); + it('dynamic GPT-5.6 config preserves the complete effort-level map', () => { + const config = convertApiModelToOpenCodeConfig(makeLlmModel('openai.gpt-5.6-luna')); + expect(Object.keys(config.variants ?? {})).toEqual(['minimal', 'low', 'medium', 'high', 'xhigh', 'max']); + expect(config.variants?.xhigh?.reasoningEffort).toBe('xhigh'); + expect(config.variants?.max?.reasoningEffort).toBe('max'); + }); + // ── Static fallback path (OPENCODE_MODEL_CONFIGS) ────────────────────────── it('static config has gpt-5.6-sol-2026-07-09 with use_responses_api: true', () => { @@ -164,6 +171,12 @@ describe('GPT-5.6 → Responses API routing', () => { it('static config gpt-5.6-sol-2026-07-09 reports context limit of 1050000', () => { expect(OPENCODE_MODEL_CONFIGS['gpt-5.6-sol-2026-07-09']!.limit.context).toBe(1050000); }); + + it('static GPT-5.6 config preserves xhigh and max', () => { + const variants = OPENCODE_MODEL_CONFIGS['gpt-5.6-sol-2026-07-09']!.variants; + expect(variants?.xhigh?.reasoningEffort).toBe('xhigh'); + expect(variants?.max?.reasoningEffort).toBe('max'); + }); }); describe('GPT-6 → Responses API routing', () => { diff --git a/src/agents/plugins/codemie-code.plugin.ts b/src/agents/plugins/codemie-code.plugin.ts index 4f31e0f44..7db9baeb8 100644 --- a/src/agents/plugins/codemie-code.plugin.ts +++ b/src/agents/plugins/codemie-code.plugin.ts @@ -223,6 +223,14 @@ export const CodeMieCodePluginMetadata: AgentMetadata = { supportedProviders: ['litellm', 'ai-run-sso', 'ollama', 'bedrock', 'bearer-auth'], + reasoningEffort: { + strategy: 'cli-flag', + flag: '--variant', + placement: 'append', + supportedLevels: ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'], + userOverrideFlags: ['--variant'], + }, + ssoConfig: { enabled: true, clientType: 'codemie-code' }, lifecycle: { diff --git a/src/agents/plugins/opencode/opencode-dynamic-models.ts b/src/agents/plugins/opencode/opencode-dynamic-models.ts index 0b2b4aaa4..e23afb924 100644 --- a/src/agents/plugins/opencode/opencode-dynamic-models.ts +++ b/src/agents/plugins/opencode/opencode-dynamic-models.ts @@ -16,7 +16,7 @@ import type { LlmModel } from '../../../providers/plugins/sso/sso.http-client.js'; import { fetchCodeMieLlmModels, isRouterModel } from '../../../providers/plugins/sso/sso.http-client.js'; import type { OpenCodeModelConfig } from './opencode-model-configs.js'; -import { OPENCODE_MODEL_CONFIGS } from './opencode-model-configs.js'; +import { getExtendedReasoningVariants, OPENCODE_MODEL_CONFIGS } from './opencode-model-configs.js'; import { CodeMieSSO } from '../../../providers/plugins/sso/sso.auth.js'; import { logger } from '../../../utils/logger.js'; @@ -109,6 +109,7 @@ export function convertApiModelToOpenCodeConfig(model: LlmModel, isSelected = fa const family = detectFamily(id); const limit = detectLimits(id, family); const responsesApi = isResponsesApiModel(id); + const extendedVariants = responsesApi ? getExtendedReasoningVariants(id) : undefined; const toPerMillion = (v: number | undefined) => (v ?? 0) * 1_000_000; @@ -131,6 +132,7 @@ export function convertApiModelToOpenCodeConfig(model: LlmModel, isSelected = fa temperature: model.features?.temperature ?? true, structured_output: model.features?.tools ? true : undefined, ...(responsesApi && { use_responses_api: true }), + ...(extendedVariants && { variants: extendedVariants }), modalities: { input: model.multimodal ? ['text', 'image'] : ['text'], output: ['text'], diff --git a/src/agents/plugins/opencode/opencode-model-configs.ts b/src/agents/plugins/opencode/opencode-model-configs.ts index af5992bc6..02148c238 100644 --- a/src/agents/plugins/opencode/opencode-model-configs.ts +++ b/src/agents/plugins/opencode/opencode-model-configs.ts @@ -52,6 +52,33 @@ export interface OpenCodeModelConfig { headers?: Record; timeout?: number; }; + /** Named model variants used by OpenCode's --variant flag. */ + variants?: Record>; +} + +const EXTENDED_REASONING_MODEL_PATTERN = /gpt-5[.-]6|gpt-6/; +const EXTENDED_REASONING_LEVELS = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max']; + +/** + * Return explicit OpenAI Responses variants for models that support CodeMie's + * complete reasoning-effort vocabulary. OpenCode's provider defaults do not + * define `max`, so it must be present in the injected model configuration. + */ +export function getExtendedReasoningVariants( + modelId: string, +): Record> | undefined { + if (!EXTENDED_REASONING_MODEL_PATTERN.test(modelId)) return undefined; + + return Object.fromEntries( + EXTENDED_REASONING_LEVELS.map(level => [ + level, + { + reasoningEffort: level, + reasoningSummary: 'auto', + include: ['reasoning.encrypted_content'], + }, + ]), + ); } export const OPENCODE_MODEL_CONFIGS: Record = { @@ -269,6 +296,7 @@ export const OPENCODE_MODEL_CONFIGS: Record = { temperature: false, structured_output: true, use_responses_api: true, + variants: getExtendedReasoningVariants('gpt-5.6-sol-2026-07-09'), modalities: { input: ['text', 'image'], output: ['text'] diff --git a/src/agents/plugins/pi/pi.models.ts b/src/agents/plugins/pi/pi.models.ts index 9a4a47e43..e3e9ad2cd 100644 --- a/src/agents/plugins/pi/pi.models.ts +++ b/src/agents/plugins/pi/pi.models.ts @@ -89,8 +89,8 @@ function defaultThinkingLevelMap(): Record { low: 'low', medium: 'medium', high: 'high', - xhigh: 'high', - max: 'high', + xhigh: 'xhigh', + max: 'max', }; } diff --git a/tmp/opencode-max-effort-level.md b/tmp/opencode-max-effort-level.md new file mode 100644 index 000000000..07da3b024 --- /dev/null +++ b/tmp/opencode-max-effort-level.md @@ -0,0 +1,36 @@ +# OpenCode and Pi effort-level fix + +## Findings + +- The CodeMie CLI already defines the canonical levels as `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. +- `codemie-opencode` already forwards its selected level as `--variant `. +- The built-in `codemie-code` wrapper uses the same OpenCode binary but does not currently declare the reasoning-effort forwarding block. +- OpenCode selects a named model variant. Passing `--variant max` is not enough unless the injected model definition contains a `max` variant with the correct request options. +- The current OpenCode provider defaults expose only part of the desired palette. The CodeMie model catalogue should explicitly provide the extended variants for GPT-5.6 and GPT-6-family Responses API models. +- Pi's generated `models.json` currently maps both `xhigh` and `max` to `high` in `src/agents/plugins/pi/pi.models.ts`. The generated `.pi/codemie/agent/models.json` is not the source of truth. +- GPT-6 routing/classification is intentionally out of scope here because it is already addressed by a separate PR. +- The current Pi package configured by CodeMie is `@earendil-works/pi-coding-agent`; no Pi fork change is needed for this mapping fix. + +## Minimal implementation + +1. Add the OpenCode reasoning-effort declaration to the built-in `codemie-code` metadata so the CLI forwards all six canonical levels as `--variant`. +2. Add an explicit OpenCode variant map for GPT-5.6 and GPT-6-family model IDs. Each level will send the corresponding `reasoningEffort` value, together with the existing OpenAI reasoning metadata. +3. Include the same variant map in static GPT-5.6 fallback configurations and dynamic model configurations. +4. Change Pi's generated `thinkingLevelMap` so `xhigh` remains `xhigh` and `max` remains `max`. +5. Add focused regression tests for dynamic/static OpenCode variants, built-in CLI forwarding, and Pi's generated map. + +## Non-goals + +- Do not modify GPT-6 Responses API detection, context limits, or family classification. +- Do not modify the `@codemieai/codemie-opencode` binary fork or publish a new binary. +- Do not edit generated `.pi` files manually. + +## Verification + +- Run the focused OpenCode, Pi, and effort-injection unit tests. +- Run TypeScript type-checking and linting for changed files. +- Review the final diff, commit the plan and implementation, and push the existing fork branch. + +## Expected scope + +Approximately 7 source/test files plus this plan, with a small implementation change. The existing unrelated `.codemie/codemie-cli.config.json` worktree change must remain untouched. From b910705a59130abb2155bfe03fe7514b0a82c4b5 Mon Sep 17 00:00:00 2001 From: Filip Stastny Date: Sun, 4 Oct 2026 10:35:57 +0200 Subject: [PATCH 2/4] fix(agents): align GPT reasoning levels --- .../__tests__/opencode-gpt55-routing.test.ts | 18 +++++- .../opencode/opencode-model-configs.ts | 61 +++++++++++++++---- .../plugins/pi/__tests__/pi.models.test.ts | 15 +++++ src/agents/plugins/pi/pi.models.ts | 18 +++++- tmp/opencode-max-effort-level.md | 36 ----------- 5 files changed, 97 insertions(+), 51 deletions(-) delete mode 100644 tmp/opencode-max-effort-level.md diff --git a/src/agents/plugins/__tests__/opencode-gpt55-routing.test.ts b/src/agents/plugins/__tests__/opencode-gpt55-routing.test.ts index 76c095fdb..bd70eed7f 100644 --- a/src/agents/plugins/__tests__/opencode-gpt55-routing.test.ts +++ b/src/agents/plugins/__tests__/opencode-gpt55-routing.test.ts @@ -152,11 +152,26 @@ describe('GPT-5.6 → Responses API routing', () => { it('dynamic GPT-5.6 config preserves the complete effort-level map', () => { const config = convertApiModelToOpenCodeConfig(makeLlmModel('openai.gpt-5.6-luna')); - expect(Object.keys(config.variants ?? {})).toEqual(['minimal', 'low', 'medium', 'high', 'xhigh', 'max']); + expect(Object.keys(config.variants ?? {})).toEqual(['minimal', 'none', 'low', 'medium', 'high', 'xhigh', 'max']); + expect(config.variants?.minimal?.reasoningEffort).toBe('none'); + expect(config.variants?.none?.reasoningEffort).toBe('none'); expect(config.variants?.xhigh?.reasoningEffort).toBe('xhigh'); expect(config.variants?.max?.reasoningEffort).toBe('max'); }); + it.each([ + ['gpt-5.6-luna', 'none'], + ['gpt-5.6-terra', 'none'], + ['gpt-6-sol', 'none'], + ['gpt-6-luna', 'none'], + ['gpt-6-astra', 'low'], + ['gpt-6.1-sol', 'low'], + ])('%s maps CodeMie minimal to native %s', (modelId, nativeMinimal) => { + const config = convertApiModelToOpenCodeConfig(makeLlmModel(modelId)); + expect(config.use_responses_api).toBe(true); + expect(config.variants?.minimal?.reasoningEffort).toBe(nativeMinimal); + }); + // ── Static fallback path (OPENCODE_MODEL_CONFIGS) ────────────────────────── it('static config has gpt-5.6-sol-2026-07-09 with use_responses_api: true', () => { @@ -174,6 +189,7 @@ describe('GPT-5.6 → Responses API routing', () => { it('static GPT-5.6 config preserves xhigh and max', () => { const variants = OPENCODE_MODEL_CONFIGS['gpt-5.6-sol-2026-07-09']!.variants; + expect(variants?.minimal?.reasoningEffort).toBe('none'); expect(variants?.xhigh?.reasoningEffort).toBe('xhigh'); expect(variants?.max?.reasoningEffort).toBe('max'); }); diff --git a/src/agents/plugins/opencode/opencode-model-configs.ts b/src/agents/plugins/opencode/opencode-model-configs.ts index 02148c238..ffa7de6b2 100644 --- a/src/agents/plugins/opencode/opencode-model-configs.ts +++ b/src/agents/plugins/opencode/opencode-model-configs.ts @@ -56,27 +56,64 @@ export interface OpenCodeModelConfig { variants?: Record>; } -const EXTENDED_REASONING_MODEL_PATTERN = /gpt-5[.-]6|gpt-6/; -const EXTENDED_REASONING_LEVELS = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max']; +const GPT_56_REASONING_LEVELS = ['none', 'low', 'medium', 'high', 'xhigh', 'max'] as const; +const GPT_6_LOWEST_REASONING_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'] as const; + +function getNativeReasoningLevels(modelId: string): readonly string[] | undefined { + if (/gpt-5[.-]6(?:[.-]|$)/.test(modelId)) { + return GPT_56_REASONING_LEVELS; + } + + // GPT-6 Astra and GPT-6.1 Sol do not expose either `none` or `minimal`. + if ( + /gpt-6[.-]astra(?:[.-]|$)/.test(modelId) || + /gpt-6[.-]1(?:[.-]|$)/.test(modelId) + ) { + return GPT_6_LOWEST_REASONING_LEVELS; + } + + // GPT-6 Sol and Luna expose `none`, but not `minimal`. + if (/gpt-6(?:[.-]|$)/.test(modelId)) { + return GPT_56_REASONING_LEVELS; + } + + return undefined; +} /** - * Return explicit OpenAI Responses variants for models that support CodeMie's - * complete reasoning-effort vocabulary. OpenCode's provider defaults do not - * define `max`, so it must be present in the injected model configuration. + * Return explicit OpenAI Responses variants for models with model-specific + * reasoning vocabularies. CodeMie's `minimal` is an alias for the model's + * lowest native setting when OpenAI does not expose a native `minimal` value. + * OpenCode's provider defaults do not define `max`, so it must be present in + * the injected model configuration. */ export function getExtendedReasoningVariants( modelId: string, ): Record> | undefined { - if (!EXTENDED_REASONING_MODEL_PATTERN.test(modelId)) return undefined; + const nativeLevels = getNativeReasoningLevels(modelId); + if (!nativeLevels) return undefined; + + const minimalTarget = nativeLevels.includes('none') ? 'none' : 'low'; + const nativeVariants = nativeLevels.map(level => [ + level, + { + reasoningEffort: level, + reasoningSummary: 'auto', + include: ['reasoning.encrypted_content'], + }, + ] as const); return Object.fromEntries( - EXTENDED_REASONING_LEVELS.map(level => [ - level, - { - reasoningEffort: level, + [ + ['minimal', { + reasoningEffort: minimalTarget, reasoningSummary: 'auto', include: ['reasoning.encrypted_content'], - }, + }], + ...nativeVariants, + ].map(([level, options]) => [ + level, + options, ]), ); } @@ -844,6 +881,7 @@ export function getModelConfig(modelId: string): OpenCodeModelConfig { prefix => modelId.startsWith(prefix) ); const familyDefaults = familyPrefix ? MODEL_FAMILY_DEFAULTS[familyPrefix] : {}; + const extendedVariants = getExtendedReasoningVariants(modelId); // Extract family from model ID (e.g., "gpt-4o" -> "gpt-4", "claude-4-5-sonnet" -> "claude-4") const family = familyDefaults.family @@ -867,6 +905,7 @@ export function getModelConfig(modelId: string): OpenCodeModelConfig { release_date: today, last_updated: today, open_weights: false, + ...(extendedVariants && { use_responses_api: true, variants: extendedVariants }), cost: { input: 0, output: 0 }, limit: familyDefaults.limit ?? { context: 128000, output: 4096 } }; diff --git a/src/agents/plugins/pi/__tests__/pi.models.test.ts b/src/agents/plugins/pi/__tests__/pi.models.test.ts index 47829cc06..c6f8d85af 100644 --- a/src/agents/plugins/pi/__tests__/pi.models.test.ts +++ b/src/agents/plugins/pi/__tests__/pi.models.test.ts @@ -284,4 +284,19 @@ describe('convertLlmModelToPiEntry — GPT-6 limits and routing', () => { expect(entry.api).toBe('openai-responses'); expect(entry.reasoning).toBe(true); }); + + it.each([ + ['gpt-5.6-luna', 'none'], + ['gpt-5.6-terra', 'none'], + ['gpt-6-sol', 'none'], + ['gpt-6-luna', 'none'], + ['gpt-6-astra', 'low'], + ['gpt-6.1-sol', 'low'], + ])('%s maps CodeMie minimal to native %s', (modelId, nativeMinimal) => { + const entry = convertLlmModelToPiEntry(llmModel({ deployment_name: modelId })); + expect(entry.reasoning).toBe(true); + expect(entry.thinkingLevelMap?.minimal).toBe(nativeMinimal); + expect(entry.thinkingLevelMap?.xhigh).toBe('xhigh'); + expect(entry.thinkingLevelMap?.max).toBe('max'); + }); }); diff --git a/src/agents/plugins/pi/pi.models.ts b/src/agents/plugins/pi/pi.models.ts index e3e9ad2cd..0043d3b4d 100644 --- a/src/agents/plugins/pi/pi.models.ts +++ b/src/agents/plugins/pi/pi.models.ts @@ -82,10 +82,10 @@ function detectLimits(id: string): { contextWindow: number; maxTokens: number } return { contextWindow: 128000, maxTokens: 4096 }; } -function defaultThinkingLevelMap(): Record { +function defaultThinkingLevelMap(minimalTarget = 'minimal'): Record { return { off: null, - minimal: 'minimal', + minimal: minimalTarget, low: 'low', medium: 'medium', high: 'high', @@ -94,6 +94,18 @@ function defaultThinkingLevelMap(): Record { }; } +function thinkingLevelMapForModel(id: string): Record { + if (/gpt-5[.-]6(?:[.-]|$)/.test(id) || /gpt-6(?:[.-](?:sol|luna)|$)/.test(id)) { + return defaultThinkingLevelMap('none'); + } + + if (/gpt-6[.-]astra(?:[.-]|$)/.test(id) || /gpt-6[.-]1(?:[.-]|$)/.test(id)) { + return defaultThinkingLevelMap('low'); + } + + return defaultThinkingLevelMap(); +} + function isReasoningModel(id: string): boolean { return ( id.startsWith('claude') || @@ -220,7 +232,7 @@ export function convertLlmModelToPiEntry(model: LlmModel): PiModelEntry { if (isReasoningModel(id)) { entry.reasoning = true; - entry.thinkingLevelMap = defaultThinkingLevelMap(); + entry.thinkingLevelMap = thinkingLevelMapForModel(id); } if ( diff --git a/tmp/opencode-max-effort-level.md b/tmp/opencode-max-effort-level.md deleted file mode 100644 index 07da3b024..000000000 --- a/tmp/opencode-max-effort-level.md +++ /dev/null @@ -1,36 +0,0 @@ -# OpenCode and Pi effort-level fix - -## Findings - -- The CodeMie CLI already defines the canonical levels as `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. -- `codemie-opencode` already forwards its selected level as `--variant `. -- The built-in `codemie-code` wrapper uses the same OpenCode binary but does not currently declare the reasoning-effort forwarding block. -- OpenCode selects a named model variant. Passing `--variant max` is not enough unless the injected model definition contains a `max` variant with the correct request options. -- The current OpenCode provider defaults expose only part of the desired palette. The CodeMie model catalogue should explicitly provide the extended variants for GPT-5.6 and GPT-6-family Responses API models. -- Pi's generated `models.json` currently maps both `xhigh` and `max` to `high` in `src/agents/plugins/pi/pi.models.ts`. The generated `.pi/codemie/agent/models.json` is not the source of truth. -- GPT-6 routing/classification is intentionally out of scope here because it is already addressed by a separate PR. -- The current Pi package configured by CodeMie is `@earendil-works/pi-coding-agent`; no Pi fork change is needed for this mapping fix. - -## Minimal implementation - -1. Add the OpenCode reasoning-effort declaration to the built-in `codemie-code` metadata so the CLI forwards all six canonical levels as `--variant`. -2. Add an explicit OpenCode variant map for GPT-5.6 and GPT-6-family model IDs. Each level will send the corresponding `reasoningEffort` value, together with the existing OpenAI reasoning metadata. -3. Include the same variant map in static GPT-5.6 fallback configurations and dynamic model configurations. -4. Change Pi's generated `thinkingLevelMap` so `xhigh` remains `xhigh` and `max` remains `max`. -5. Add focused regression tests for dynamic/static OpenCode variants, built-in CLI forwarding, and Pi's generated map. - -## Non-goals - -- Do not modify GPT-6 Responses API detection, context limits, or family classification. -- Do not modify the `@codemieai/codemie-opencode` binary fork or publish a new binary. -- Do not edit generated `.pi` files manually. - -## Verification - -- Run the focused OpenCode, Pi, and effort-injection unit tests. -- Run TypeScript type-checking and linting for changed files. -- Review the final diff, commit the plan and implementation, and push the existing fork branch. - -## Expected scope - -Approximately 7 source/test files plus this plan, with a small implementation change. The existing unrelated `.codemie/codemie-cli.config.json` worktree change must remain untouched. From 0abc8b831c006e34c446342c81523b0967f094c0 Mon Sep 17 00:00:00 2001 From: Filip Stastny Date: Sun, 4 Oct 2026 17:00:44 +0200 Subject: [PATCH 3/4] refactor(agents): clarify GPT reasoning level names --- src/agents/plugins/opencode/opencode-model-configs.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/agents/plugins/opencode/opencode-model-configs.ts b/src/agents/plugins/opencode/opencode-model-configs.ts index ffa7de6b2..ef6f3f3cd 100644 --- a/src/agents/plugins/opencode/opencode-model-configs.ts +++ b/src/agents/plugins/opencode/opencode-model-configs.ts @@ -56,12 +56,12 @@ export interface OpenCodeModelConfig { variants?: Record>; } -const GPT_56_REASONING_LEVELS = ['none', 'low', 'medium', 'high', 'xhigh', 'max'] as const; -const GPT_6_LOWEST_REASONING_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'] as const; +const GPT_5_6_REASONING_LEVELS = ['none', 'low', 'medium', 'high', 'xhigh', 'max'] as const; +const GPT_6_REASONING_LEVELS_FROM_LOW = ['low', 'medium', 'high', 'xhigh', 'max'] as const; function getNativeReasoningLevels(modelId: string): readonly string[] | undefined { if (/gpt-5[.-]6(?:[.-]|$)/.test(modelId)) { - return GPT_56_REASONING_LEVELS; + return GPT_5_6_REASONING_LEVELS; } // GPT-6 Astra and GPT-6.1 Sol do not expose either `none` or `minimal`. @@ -69,12 +69,12 @@ function getNativeReasoningLevels(modelId: string): readonly string[] | undefine /gpt-6[.-]astra(?:[.-]|$)/.test(modelId) || /gpt-6[.-]1(?:[.-]|$)/.test(modelId) ) { - return GPT_6_LOWEST_REASONING_LEVELS; + return GPT_6_REASONING_LEVELS_FROM_LOW; } // GPT-6 Sol and Luna expose `none`, but not `minimal`. if (/gpt-6(?:[.-]|$)/.test(modelId)) { - return GPT_56_REASONING_LEVELS; + return GPT_5_6_REASONING_LEVELS; } return undefined; From fcfa1a972bd45c27aa62025e97e3e455f426459b Mon Sep 17 00:00:00 2001 From: Filip Stastny Date: Wed, 7 Oct 2026 23:52:09 +0200 Subject: [PATCH 4/4] refactor(agents): separate Pi reasoning changes --- .../plugins/pi/__tests__/pi.models.test.ts | 15 ------------- src/agents/plugins/pi/pi.models.ts | 22 +++++-------------- 2 files changed, 5 insertions(+), 32 deletions(-) diff --git a/src/agents/plugins/pi/__tests__/pi.models.test.ts b/src/agents/plugins/pi/__tests__/pi.models.test.ts index c6f8d85af..47829cc06 100644 --- a/src/agents/plugins/pi/__tests__/pi.models.test.ts +++ b/src/agents/plugins/pi/__tests__/pi.models.test.ts @@ -284,19 +284,4 @@ describe('convertLlmModelToPiEntry — GPT-6 limits and routing', () => { expect(entry.api).toBe('openai-responses'); expect(entry.reasoning).toBe(true); }); - - it.each([ - ['gpt-5.6-luna', 'none'], - ['gpt-5.6-terra', 'none'], - ['gpt-6-sol', 'none'], - ['gpt-6-luna', 'none'], - ['gpt-6-astra', 'low'], - ['gpt-6.1-sol', 'low'], - ])('%s maps CodeMie minimal to native %s', (modelId, nativeMinimal) => { - const entry = convertLlmModelToPiEntry(llmModel({ deployment_name: modelId })); - expect(entry.reasoning).toBe(true); - expect(entry.thinkingLevelMap?.minimal).toBe(nativeMinimal); - expect(entry.thinkingLevelMap?.xhigh).toBe('xhigh'); - expect(entry.thinkingLevelMap?.max).toBe('max'); - }); }); diff --git a/src/agents/plugins/pi/pi.models.ts b/src/agents/plugins/pi/pi.models.ts index 0043d3b4d..9a4a47e43 100644 --- a/src/agents/plugins/pi/pi.models.ts +++ b/src/agents/plugins/pi/pi.models.ts @@ -82,30 +82,18 @@ function detectLimits(id: string): { contextWindow: number; maxTokens: number } return { contextWindow: 128000, maxTokens: 4096 }; } -function defaultThinkingLevelMap(minimalTarget = 'minimal'): Record { +function defaultThinkingLevelMap(): Record { return { off: null, - minimal: minimalTarget, + minimal: 'minimal', low: 'low', medium: 'medium', high: 'high', - xhigh: 'xhigh', - max: 'max', + xhigh: 'high', + max: 'high', }; } -function thinkingLevelMapForModel(id: string): Record { - if (/gpt-5[.-]6(?:[.-]|$)/.test(id) || /gpt-6(?:[.-](?:sol|luna)|$)/.test(id)) { - return defaultThinkingLevelMap('none'); - } - - if (/gpt-6[.-]astra(?:[.-]|$)/.test(id) || /gpt-6[.-]1(?:[.-]|$)/.test(id)) { - return defaultThinkingLevelMap('low'); - } - - return defaultThinkingLevelMap(); -} - function isReasoningModel(id: string): boolean { return ( id.startsWith('claude') || @@ -232,7 +220,7 @@ export function convertLlmModelToPiEntry(model: LlmModel): PiModelEntry { if (isReasoningModel(id)) { entry.reasoning = true; - entry.thinkingLevelMap = thinkingLevelMapForModel(id); + entry.thinkingLevelMap = defaultThinkingLevelMap(); } if (