Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Per-model default (fill-when-absent) reasoning effort for OpenAI routes, matching modelDefaultReasoningEfforts on Anthropic

Open
#6,604 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript

Research direction

Start with src/adapters/anthropic.ts to understand the existing per-model default lookup, then compare normalizePinnedChatEffort in src/server/chat-native.ts with applyPinnedEffort in src/server/responses/core-normalize.ts. Trace the relevant tests and configuration handling before changing both OpenAI paths. Done means absent effort gets the configured default, explicit effort remains unchanged, pins and caps retain precedence, and the fill is observable in logs.

Written by the indexing model from the issue text.

Description

enhancement proxy
Area

Proxy and routing

What are you trying to accomplish?

I want a per-model fallback reasoning effort for OpenAI-family models (e.g. gpt-6-astra): used only when the incoming request carries no effort, while an explicit client effort (low … max) still passes through unchanged.

This is the behaviour providers.anthropic.modelDefaultReasoningEfforts already gives Claude models today, so per-session effort selection keeps working and the proxy only fills the gap.

What prevents this today?

modelDefaultReasoningEfforts is only applied in the Anthropic adapter (src/adapters/anthropic.ts, parsed.options.reasoning ?? defaultReasoningEffort(provider, parsed.modelId)). On the OpenAI routes, both the chat-native path (normalizePinnedChatEffort in src/server/chat-native.ts) and the Responses path (applyPinnedEffort in src/server/responses/core-normalize.ts) support only:

  • modelPinnedReasoningEfforts / pinnedReasoningEffort: overrides any client effort
  • effort caps: lower high requests

Neither has a "fill only when absent" option, so the only way to guarantee a non-default effort is a pin, and a pin also removes the client's choice (max → xhigh, low → xhigh).

Real-world trigger: a client (Hermes Agent, NousResearch/hermes-agent#119681) silently dropped reasoning_effort for a named custom provider. From usage.jsonl, desktop sessions on gpt-6-astra sent 100+ requests over several days with requestedEffort absent, with prompts up to ~200k tokens (mostly cache reads) and reasoning output of 0 on most calls. The gap went unnoticed until answers came back too fast. After finding it, I covered the Claude models with modelDefaultReasoningEfforts (per-session selection still works), but for Astra the only option was a pin.

What should OpenCodex do?

When a request routed to an OpenAI-family provider has no reasoning effort, apply provider.modelDefaultReasoningEfforts[modelId] (same lookup semantics as on the Anthropic adapter, including __omit__). When the request already has an effort, leave it alone. Pins and caps keep their current precedence over the default.

Ideally the log records the fill, e.g. requestedEffort: "->xhigh" or "default:xhigh", so a client that stopped sending effort is visible in usage.jsonl instead of looking identical to a client-sent value. (Today the Anthropic fill is invisible in the log: those rows show no requestedEffort at all.)

Example usage or interface
ocx config set providers.openai.modelDefaultReasoningEfforts '{"gpt-6-astra":"xhigh"}'
Incoming reasoning_effort Today (pin) Proposed (default)
absent xhigh xhigh
max xhigh max
low xhigh low
Alternatives or workarounds
  • modelPinnedReasoningEfforts for gpt-6-astra: works as a safety net but forces one effort for every client (Hermes, OmO, Codex) on that model.
  • Patching each client: fixes the root cause per client, but client updates can revert local patches, and the proxy is the one place every client passes through.
Additional context
  • OpenCodex 2.77.0, Windows 11
  • Inbound: Chat Completions (inboundProtocol: chat), translated to Responses upstream (protocolTrace.mode: translated)
  • Related: #5453 (effort not logged on the Messages surface)
Checks
  • I searched existing issues and documentation.
  • This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
  • I removed secrets and personal data.
Dominant language
TypeScript
Stars
16.9k
Forks
1.3k
Avg merge
4h 24m
Merged PRs (30d)
574

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from lidge-jun/opencodex

All issues in lidge-jun/opencodex

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.