GPT5 OpenAI Fix (#6864)

* fix: add explicit max_output_tokens for GPT-5 Responses API

- Added max_output_tokens parameter to GPT-5 request body using model.maxTokens
- This prevents GPT-5 from defaulting to very large token limits (e.g., 120k)
- Updated tests to expect max_output_tokens in GPT-5 request bodies
- Fixed test for handling unhandled stream events by properly mocking SDK fallback

* fix: add missing translations for reasoningEffort.minimal in Indonesian and Dutch locales

* fix: correct GPT-5 response ID persistence and usage

- Renamed metadata field from 'previous_response_id' to 'response_id' for clarity
- Fixed logic to correctly use the response_id from the previous message as previous_response_id for the next request
- This resolves the 'Previous response with id not found' errors that occurred after multiple turns in the same session

* feat: add robust error handling for GPT-5 previous_response_id failures

- Automatically retry without previous_response_id when it's not found (400 error)
- Clear stored lastResponseId to prevent reusing stale IDs
- Handle errors in both SDK and SSE fallback paths
- Log warnings when retrying to help with debugging

* fix: handle GPT-5 response ID race condition with nano model

- Add promise-based synchronization for response ID persistence
- Wait for pending response ID from previous request before using it
- Resolve promise when response ID is received or cleared
- Add 100ms timeout to avoid blocking too long on ID resolution
- Properly clean up resolver on errors to prevent memory leaks

This fixes the race condition where fast nano model responses could cause
the next request to be initiated before the response ID was fully persisted.

* fix: address PR review comments for GPT-5 implementation

- Extract usage normalization helper to reduce duplication
- Suppress conversation continuity for first message (but respect explicit metadata)
- Deduplicate response ID resolver logic
- Remove dead enableGpt5ReasoningSummary option references
- DRY up GPT-5 event/usage handling with normalizeGpt5Usage helper
- Centralize default GPT-5 reasoning effort using model info
- Fix Indonesian locale minimal string misplacement
- Add clarifying comments for Developer prefix usage
- Add TODO for future verbosity UI capability gating
- Fix failing test in reasoning.spec.ts

* fix(openai-native): address Roomote inline feedback\n\n- Delegate standard GPT-5 SSE event types to shared processor to reduce duplication\n- Add JSDoc for response ID accessors\n- Standardize key error messages for GPT-5 Responses API fallback\n- Extract persistGpt5Metadata() in Task to simplify metadata writes\n- Add malformed JSON SSE parsing test\n

* fix(openai-native,gpt5): correct usage cost calc (use calculateApiCostOpenAI incl. cache); enforce 'skip once' continuity via suppressPreviousResponseId; dedupe responseId resolver on SSE 400; feat: gate reasoning.summary by enableGpt5ReasoningSummary; centralize default reasoning effort; types/ui: add ModelInfo.supportsVerbosity and gate Verbosity UI by capability; refactor: avoid duplicate usage emission in SSE done/completed

* fix(gpt5): default enableGpt5ReasoningSummary=true to preserve tests and expected behavior

* fix(gpt5): canonicalize GPT-5 metadata key to previous_response_id and align enableGpt5ReasoningSummary default docs

* fix(openai-native): remove review artifact comments and guard GPT-5 in completePrompt
This commit is contained in:
Hannes Rudolph 2025-08-09 11:52:06 -07:00 committed by GitHub
parent cdc31f7c26
commit cda67a86f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 2195 additions and 264 deletions

View file

@ -176,6 +176,17 @@ export const clineMessageSchema = z.object({
contextCondense: contextCondenseSchema.optional(),
isProtected: z.boolean().optional(),
apiProtocol: z.union([z.literal("openai"), z.literal("anthropic")]).optional(),
metadata: z
.object({
gpt5: z
.object({
previous_response_id: z.string().optional(),
instructions: z.string().optional(),
reasoning_summary: z.string().optional(),
})
.optional(),
})
.optional(),
})
export type ClineMessage = z.infer<typeof clineMessageSchema>

View file

@ -44,6 +44,8 @@ export const modelInfoSchema = z.object({
supportsImages: z.boolean().optional(),
supportsComputerUse: z.boolean().optional(),
supportsPromptCache: z.boolean(),
// Capability flag to indicate whether the model supports an output verbosity parameter
supportsVerbosity: z.boolean().optional(),
supportsReasoningBudget: z.boolean().optional(),
requiredReasoningBudget: z.boolean().optional(),
supportsReasoningEffort: z.boolean().optional(),

View file

@ -3,6 +3,11 @@ import { z } from "zod"
import { reasoningEffortsSchema, verbosityLevelsSchema, modelInfoSchema } from "./model.js"
import { codebaseIndexProviderSchema } from "./codebase-index.js"
// Extended schema that includes "minimal" for GPT-5 models
export const extendedReasoningEffortsSchema = z.union([reasoningEffortsSchema, z.literal("minimal")])
export type ReasoningEffortWithMinimal = z.infer<typeof extendedReasoningEffortsSchema>
/**
* ProviderName
*/
@ -76,7 +81,7 @@ const baseProviderSettingsSchema = z.object({
// Model reasoning.
enableReasoningEffort: z.boolean().optional(),
reasoningEffort: reasoningEffortsSchema.optional(),
reasoningEffort: extendedReasoningEffortsSchema.optional(),
modelMaxTokens: z.number().optional(),
modelMaxThinkingTokens: z.number().optional(),

View file

@ -12,10 +12,13 @@ export const openAiNativeModels = {
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
reasoningEffort: "medium",
inputPrice: 1.25,
outputPrice: 10.0,
cacheReadsPrice: 0.13,
description: "GPT-5: The best model for coding and agentic tasks across domains",
// supportsVerbosity is a new capability; ensure ModelInfo includes it
supportsVerbosity: true,
},
"gpt-5-mini-2025-08-07": {
maxTokens: 128000,
@ -23,10 +26,12 @@ export const openAiNativeModels = {
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
reasoningEffort: "medium",
inputPrice: 0.25,
outputPrice: 2.0,
cacheReadsPrice: 0.03,
description: "GPT-5 Mini: A faster, more cost-efficient version of GPT-5 for well-defined tasks",
supportsVerbosity: true,
},
"gpt-5-nano-2025-08-07": {
maxTokens: 128000,
@ -34,10 +39,12 @@ export const openAiNativeModels = {
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
reasoningEffort: "medium",
inputPrice: 0.05,
outputPrice: 0.4,
cacheReadsPrice: 0.01,
description: "GPT-5 Nano: Fastest, most cost-efficient version of GPT-5",
supportsVerbosity: true,
},
"gpt-4.1": {
maxTokens: 32_768,
@ -229,5 +236,6 @@ export const openAiModelInfoSaneDefaults: ModelInfo = {
export const azureOpenAiDefaultApiVersion = "2024-08-01-preview"
export const OPENAI_NATIVE_DEFAULT_TEMPERATURE = 0
export const GPT5_DEFAULT_TEMPERATURE = 1.0
export const OPENAI_AZURE_AI_INFERENCE_PATH = "/models/chat/completions"

View file

@ -44,6 +44,13 @@ export interface SingleCompletionHandler {
export interface ApiHandlerCreateMessageMetadata {
mode?: string
taskId: string
previousResponseId?: string
/**
* When true, the provider must NOT fall back to internal continuity state
* (e.g., lastResponseId) if previousResponseId is absent.
* Used to enforce "skip once" after a condense operation.
*/
suppressPreviousResponseId?: boolean
}
export interface ApiHandler {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -305,7 +305,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
],
stream: true,
...(isGrokXAI ? {} : { stream_options: { include_usage: true } }),
reasoning_effort: modelInfo.reasoningEffort,
reasoning_effort: modelInfo.reasoningEffort as "low" | "medium" | "high" | undefined,
temperature: undefined,
}
@ -330,7 +330,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
},
...convertToOpenAiMessages(messages),
],
reasoning_effort: modelInfo.reasoningEffort,
reasoning_effort: modelInfo.reasoningEffort as "low" | "medium" | "high" | undefined,
temperature: undefined,
}

View file

@ -116,7 +116,7 @@ export class RequestyHandler extends BaseProvider implements SingleCompletionHan
model,
max_tokens,
temperature,
...(reasoning_effort && { reasoning_effort }),
...(reasoning_effort && reasoning_effort !== "minimal" && { reasoning_effort }),
...(thinking && { thinking }),
stream: true,
stream_options: { include_usage: true },

View file

@ -2,6 +2,7 @@ import {
type ModelInfo,
type ProviderSettings,
type VerbosityLevel,
type ReasoningEffortWithMinimal,
ANTHROPIC_DEFAULT_MAX_TOKENS,
} from "@roo-code/types"
@ -38,7 +39,7 @@ type GetModelParamsOptions<T extends Format> = {
type BaseModelParams = {
maxTokens: number | undefined
temperature: number | undefined
reasoningEffort: "low" | "medium" | "high" | undefined
reasoningEffort: ReasoningEffortWithMinimal | undefined
reasoningBudget: number | undefined
verbosity: VerbosityLevel | undefined
}
@ -128,7 +129,8 @@ export function getModelParams({
temperature = 1.0
} else if (shouldUseReasoningEffort({ model, settings })) {
// "Traditional" reasoning models use the `reasoningEffort` parameter.
reasoningEffort = customReasoningEffort ?? model.reasoningEffort
const effort = customReasoningEffort ?? model.reasoningEffort
reasoningEffort = effort as ReasoningEffortWithMinimal
}
const params: BaseModelParams = { maxTokens, temperature, reasoningEffort, reasoningBudget, verbosity }

View file

@ -2,7 +2,7 @@ import { BetaThinkingConfigParam } from "@anthropic-ai/sdk/resources/beta"
import OpenAI from "openai"
import type { GenerateContentConfig } from "@google/genai"
import type { ModelInfo, ProviderSettings } from "@roo-code/types"
import type { ModelInfo, ProviderSettings, ReasoningEffortWithMinimal } from "@roo-code/types"
import { shouldUseReasoningBudget, shouldUseReasoningEffort } from "../../shared/api"
@ -23,7 +23,7 @@ export type GeminiReasoningParams = GenerateContentConfig["thinkingConfig"]
export type GetModelReasoningOptions = {
model: ModelInfo
reasoningBudget: number | undefined
reasoningEffort: ReasoningEffort | undefined
reasoningEffort: ReasoningEffortWithMinimal | undefined
settings: ProviderSettings
}
@ -36,7 +36,9 @@ export const getOpenRouterReasoning = ({
shouldUseReasoningBudget({ model, settings })
? { max_tokens: reasoningBudget }
: shouldUseReasoningEffort({ model, settings })
? { effort: reasoningEffort }
? reasoningEffort !== "minimal"
? { effort: reasoningEffort }
: undefined
: undefined
export const getAnthropicReasoning = ({
@ -50,8 +52,19 @@ export const getOpenAiReasoning = ({
model,
reasoningEffort,
settings,
}: GetModelReasoningOptions): OpenAiReasoningParams | undefined =>
shouldUseReasoningEffort({ model, settings }) ? { reasoning_effort: reasoningEffort } : undefined
}: GetModelReasoningOptions): OpenAiReasoningParams | undefined => {
if (!shouldUseReasoningEffort({ model, settings })) {
return undefined
}
// If model has reasoning effort capability, return object even if effort is undefined
// This preserves the reasoning_effort field in the API call
if (reasoningEffort === "minimal") {
return undefined
}
return { reasoning_effort: reasoningEffort }
}
export const getGeminiReasoning = ({
model,

View file

@ -252,6 +252,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
didCompleteReadingStream = false
assistantMessageParser?: AssistantMessageParser
isAssistantMessageParserEnabled = false
private lastUsedInstructions?: string
private skipPrevResponseIdOnce: boolean = false
constructor({
provider,
@ -824,6 +826,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
progressStatus?: ToolProgressStatus,
options: {
isNonInteractive?: boolean
metadata?: Record<string, unknown>
} = {},
contextCondense?: ContextCondense,
): Promise<undefined> {
@ -861,6 +864,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
images,
partial,
contextCondense,
metadata: options.metadata,
})
}
} else {
@ -876,6 +880,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
lastMessage.images = images
lastMessage.partial = false
lastMessage.progressStatus = progressStatus
if (options.metadata) {
;(lastMessage as any).metadata = options.metadata
}
// Instead of streaming partialMessage events, we do a save
// and post like normal to persist to disk.
@ -891,7 +898,15 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
this.lastMessageTs = sayTs
}
await this.addToClineMessages({ ts: sayTs, type: "say", say: type, text, images, contextCondense })
await this.addToClineMessages({
ts: sayTs,
type: "say",
say: type,
text,
images,
contextCondense,
metadata: options.metadata,
})
}
}
} else {
@ -1736,6 +1751,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
presentAssistantMessage(this)
}
await this.persistGpt5Metadata(reasoningMessage)
updateApiReqMsg()
await this.saveClineMessages()
await this.providerRef.deref()?.postStateToWebview()
@ -1954,6 +1971,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
Task.lastGlobalApiRequestTime = Date.now()
const systemPrompt = await this.getSystemPrompt()
this.lastUsedInstructions = systemPrompt
const { contextTokens } = this.getTokenUsage()
if (contextTokens) {
@ -1992,6 +2010,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
if (truncateResult.error) {
await this.say("condense_context_error", truncateResult.error)
} else if (truncateResult.summary) {
// A condense operation occurred; for the next GPT5 API call we should NOT
// send previous_response_id so the request reflects the fresh condensed context.
this.skipPrevResponseIdOnce = true
const { summary, cost, prevContextTokens, newContextTokens = 0 } = truncateResult
const contextCondense: ContextCondense = { summary, cost, newContextTokens, prevContextTokens }
await this.say(
@ -2008,7 +2030,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
}
const messagesSinceLastSummary = getMessagesSinceLastSummary(this.apiConversationHistory)
const cleanConversationHistory = maybeRemoveImageBlocks(messagesSinceLastSummary, this.api).map(
let cleanConversationHistory = maybeRemoveImageBlocks(messagesSinceLastSummary, this.api).map(
({ role, content }) => ({ role, content }),
)
@ -2024,9 +2046,41 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
throw new Error("Auto-approval limit reached and user did not approve continuation")
}
// Determine GPT5 previous_response_id from last persisted assistant turn (if available),
// unless a condense just occurred (skip once after condense).
let previousResponseId: string | undefined = undefined
try {
const modelId = this.api.getModel().id
if (modelId && modelId.startsWith("gpt-5") && !this.skipPrevResponseIdOnce) {
// Find the last assistant message that has a previous_response_id stored
const idx = findLastIndex(
this.clineMessages,
(m) =>
m.type === "say" &&
(m as any).say === "text" &&
(m as any).metadata?.gpt5?.previous_response_id,
)
if (idx !== -1) {
// Use the previous_response_id from the last assistant message for this request
previousResponseId = ((this.clineMessages[idx] as any).metadata.gpt5.previous_response_id ||
undefined) as string | undefined
}
}
} catch {
// non-fatal
}
const metadata: ApiHandlerCreateMessageMetadata = {
mode: mode,
taskId: this.taskId,
...(previousResponseId ? { previousResponseId } : {}),
// If a condense just occurred, explicitly suppress continuity fallback for the next call
...(this.skipPrevResponseIdOnce ? { suppressPreviousResponseId: true } : {}),
}
// Reset skip flag after applying (it only affects the immediate next call)
if (this.skipPrevResponseIdOnce) {
this.skipPrevResponseIdOnce = false
}
const stream = this.api.createMessage(systemPrompt, cleanConversationHistory, metadata)
@ -2172,6 +2226,35 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
}
}
/**
* Persist GPT-5 per-turn metadata (previous_response_id, instructions, reasoning_summary)
* onto the last complete assistant say("text") message.
*/
private async persistGpt5Metadata(reasoningMessage?: string): Promise<void> {
try {
const modelId = this.api.getModel().id
if (!modelId || !modelId.startsWith("gpt-5")) return
const lastResponseId: string | undefined = (this.api as any)?.getLastResponseId?.()
const idx = findLastIndex(
this.clineMessages,
(m) => m.type === "say" && (m as any).say === "text" && m.partial !== true,
)
if (idx !== -1) {
const msg = this.clineMessages[idx] as any
msg.metadata = msg.metadata ?? {}
msg.metadata.gpt5 = {
...(msg.metadata.gpt5 ?? {}),
previous_response_id: lastResponseId,
instructions: this.lastUsedInstructions,
reasoning_summary: (reasoningMessage ?? "").trim() || undefined,
}
}
} catch {
// Non-fatal error in metadata persistence
}
}
// Getters
public get cwd() {

View file

@ -6,8 +6,15 @@ import {
} from "@roo-code/types"
// ApiHandlerOptions
export type ApiHandlerOptions = Omit<ProviderSettings, "apiProvider">
// Extend ProviderSettings (minus apiProvider) with handler-specific toggles.
export type ApiHandlerOptions = Omit<ProviderSettings, "apiProvider"> & {
/**
* When true and using GPT5 Responses API, include reasoning.summary: "auto"
* so the API returns reasoning summaries (we already parse and surface them).
* Defaults to true; set to false to disable summaries.
*/
enableGpt5ReasoningSummary?: boolean
}
// RouterName

View file

@ -576,6 +576,12 @@ const ApiOptions = ({
if (value !== "custom-arn" && selectedProvider === "bedrock") {
setApiConfigurationField("awsCustomArn", "")
}
// Clear reasoning effort when switching models to allow the new model's default to take effect
// This is especially important for GPT-5 models which default to "medium"
if (selectedProvider === "openai-native") {
setApiConfigurationField("reasoningEffort", undefined)
}
}}>
<SelectTrigger className="w-full">
<SelectValue placeholder={t("settings:common.select")} />
@ -617,11 +623,14 @@ const ApiOptions = ({
modelInfo={selectedModelInfo}
/>
<Verbosity
apiConfiguration={apiConfiguration}
setApiConfigurationField={setApiConfigurationField}
modelInfo={selectedModelInfo}
/>
{/* Gate Verbosity UI by capability flag */}
{selectedModelInfo?.supportsVerbosity && (
<Verbosity
apiConfiguration={apiConfiguration}
setApiConfigurationField={setApiConfigurationField}
modelInfo={selectedModelInfo}
/>
)}
{!fromWelcomeView && (
<Collapsible open={isAdvancedSettingsOpen} onOpenChange={setIsAdvancedSettingsOpen}>

View file

@ -1,7 +1,12 @@
import { useEffect } from "react"
import { Checkbox } from "vscrui"
import { type ProviderSettings, type ModelInfo, type ReasoningEffort, reasoningEfforts } from "@roo-code/types"
import {
type ProviderSettings,
type ModelInfo,
type ReasoningEffortWithMinimal,
reasoningEfforts,
} from "@roo-code/types"
import {
DEFAULT_HYBRID_REASONING_MODEL_MAX_TOKENS,
@ -27,10 +32,35 @@ export const ThinkingBudget = ({ apiConfiguration, setApiConfigurationField, mod
const isGemini25Pro = selectedModelId && selectedModelId.includes("gemini-2.5-pro")
const minThinkingTokens = isGemini25Pro ? GEMINI_25_PRO_MIN_THINKING_TOKENS : 1024
// Check if this is a GPT-5 model to show "minimal" option
// Only show minimal for OpenAI Native provider GPT-5 models
const isOpenAiNativeProvider = apiConfiguration.apiProvider === "openai-native"
const isGpt5Model = isOpenAiNativeProvider && selectedModelId && selectedModelId.startsWith("gpt-5")
// Add "minimal" option for GPT-5 models
// Spread to convert readonly tuple into a mutable array, then expose as readonly for safety
const baseEfforts = [...reasoningEfforts] as ReasoningEffortWithMinimal[]
const availableReasoningEfforts: ReadonlyArray<ReasoningEffortWithMinimal> = isGpt5Model
? (["minimal", ...baseEfforts] as ReasoningEffortWithMinimal[])
: baseEfforts
// Default reasoning effort - use model's default if available
// GPT-5 models have "medium" as their default in the model configuration
const modelDefaultReasoningEffort = modelInfo?.reasoningEffort as ReasoningEffortWithMinimal | undefined
const defaultReasoningEffort: ReasoningEffortWithMinimal = modelDefaultReasoningEffort || "medium"
const currentReasoningEffort: ReasoningEffortWithMinimal =
(apiConfiguration.reasoningEffort as ReasoningEffortWithMinimal | undefined) || defaultReasoningEffort
const isReasoningBudgetSupported = !!modelInfo && modelInfo.supportsReasoningBudget
const isReasoningBudgetRequired = !!modelInfo && modelInfo.requiredReasoningBudget
const isReasoningEffortSupported = !!modelInfo && modelInfo.supportsReasoningEffort
// Set default reasoning effort when model supports it and no value is set
useEffect(() => {
if (isReasoningEffortSupported && !apiConfiguration.reasoningEffort && defaultReasoningEffort) {
setApiConfigurationField("reasoningEffort", defaultReasoningEffort)
}
}, [isReasoningEffortSupported, apiConfiguration.reasoningEffort, defaultReasoningEffort, setApiConfigurationField])
const enableReasoningEffort = apiConfiguration.enableReasoningEffort
const customMaxOutputTokens = apiConfiguration.modelMaxTokens || DEFAULT_HYBRID_REASONING_MODEL_MAX_TOKENS
const customMaxThinkingTokens =
@ -109,13 +139,21 @@ export const ThinkingBudget = ({ apiConfiguration, setApiConfigurationField, mod
<label className="block font-medium mb-1">{t("settings:providers.reasoningEffort.label")}</label>
</div>
<Select
value={apiConfiguration.reasoningEffort}
onValueChange={(value) => setApiConfigurationField("reasoningEffort", value as ReasoningEffort)}>
value={currentReasoningEffort}
onValueChange={(value: ReasoningEffortWithMinimal) => {
setApiConfigurationField("reasoningEffort", value)
}}>
<SelectTrigger className="w-full">
<SelectValue placeholder={t("settings:common.select")} />
<SelectValue
placeholder={
currentReasoningEffort
? t(`settings:providers.reasoningEffort.${currentReasoningEffort}`)
: t("settings:common.select")
}
/>
</SelectTrigger>
<SelectContent>
{reasoningEfforts.map((value) => (
{availableReasoningEfforts.map((value) => (
<SelectItem key={value} value={value}>
{t(`settings:providers.reasoningEffort.${value}`)}
</SelectItem>

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Esforç de raonament del model",
"minimal": "Mínim (el més ràpid)",
"high": "Alt",
"medium": "Mitjà",
"low": "Baix"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Modell-Denkaufwand",
"minimal": "Minimal (schnellste)",
"high": "Hoch",
"medium": "Mittel",
"low": "Niedrig"

View file

@ -428,9 +428,10 @@
},
"reasoningEffort": {
"label": "Model Reasoning Effort",
"high": "High",
"minimal": "Minimal (Fastest)",
"low": "Low",
"medium": "Medium",
"low": "Low"
"high": "High"
},
"verbosity": {
"label": "Output Verbosity",

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Esfuerzo de razonamiento del modelo",
"minimal": "Mínimo (el más rápido)",
"high": "Alto",
"medium": "Medio",
"low": "Bajo"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Effort de raisonnement du modèle",
"minimal": "Minimal (le plus rapide)",
"high": "Élevé",
"medium": "Moyen",
"low": "Faible"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "मॉडल तर्क प्रयास",
"minimal": "न्यूनतम (सबसे तेज़)",
"high": "उच्च",
"medium": "मध्यम",
"low": "निम्न"

View file

@ -433,6 +433,7 @@
},
"reasoningEffort": {
"label": "Upaya Reasoning Model",
"minimal": "Minimal (Tercepat)",
"high": "Tinggi",
"medium": "Sedang",
"low": "Rendah"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Sforzo di ragionamento del modello",
"minimal": "Minimo (più veloce)",
"high": "Alto",
"medium": "Medio",
"low": "Basso"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "モデル推論の労力",
"minimal": "最小 (最速)",
"high": "高",
"medium": "中",
"low": "低"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "모델 추론 노력",
"minimal": "최소 (가장 빠름)",
"high": "높음",
"medium": "중간",
"low": "낮음"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Model redeneervermogen",
"minimal": "Minimaal (Snelst)",
"high": "Hoog",
"medium": "Middel",
"low": "Laag"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Wysiłek rozumowania modelu",
"minimal": "Minimalny (najszybszy)",
"high": "Wysoki",
"medium": "Średni",
"low": "Niski"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Esforço de raciocínio do modelo",
"minimal": "Mínimo (mais rápido)",
"high": "Alto",
"medium": "Médio",
"low": "Baixo"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Усилия по рассуждению модели",
"minimal": "Минимальный (самый быстрый)",
"high": "Высокие",
"medium": "Средние",
"low": "Низкие"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Model Akıl Yürütme Çabası",
"minimal": "Minimal (en hızlı)",
"high": "Yüksek",
"medium": "Orta",
"low": "Düşük"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "Nỗ lực suy luận của mô hình",
"minimal": "Tối thiểu (nhanh nhất)",
"high": "Cao",
"medium": "Trung bình",
"low": "Thấp"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "模型推理强度",
"minimal": "最小 (最快)",
"high": "高",
"medium": "中",
"low": "低"

View file

@ -429,6 +429,7 @@
},
"reasoningEffort": {
"label": "模型推理強度",
"minimal": "最小 (最快)",
"high": "高",
"medium": "中",
"low": "低"