Skip to content

Commit 1b57022

Browse files
authored
feat: Add user-configurable settings for reasoning and text verbosity
Merge pull request #6 from ben-vargas/config-support
2 parents 6c9e225 + 6ce2713 commit 1b57022

File tree

6 files changed

+351
-26
lines changed

6 files changed

+351
-26
lines changed

README.md

Lines changed: 145 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Follow me on [X @nummanthinks](https://x.com/nummanthinks) for future updates an
1616
-**Smart auto-updating Codex instructions** - Tracks latest stable release with ETag caching
1717
- ✅ Full tool support (write, edit, bash, grep, etc.)
1818
- ✅ Automatic tool remapping (Codex tools → opencode tools)
19-
-High reasoning effort with detailed thinking blocks
19+
-Configurable reasoning effort and summaries (defaults: medium/auto)
2020
- ✅ Modular architecture for easy maintenance
2121

2222
## Installation
@@ -82,17 +82,151 @@ Select "OpenAI" and choose:
8282
## Usage
8383

8484
```bash
85-
# Use gpt-5-codex with high reasoning (default)
85+
# Use gpt-5-codex with plugin defaults (medium/auto/medium)
8686
opencode run "create a hello world file" --model=openai/gpt-5-codex
8787

88-
# Or set as default in opencode.json
89-
opencode run "solve this complex algorithm problem"
88+
# Or use regular gpt-5 via ChatGPT subscription
89+
opencode run "solve this complex problem" --model=openai/gpt-5
90+
91+
# Set as default model in opencode.json
92+
opencode run "build a web app"
93+
```
94+
95+
### Plugin Defaults
96+
97+
When no configuration is specified, the plugin uses these defaults for all GPT-5 models:
98+
99+
```json
100+
{
101+
"reasoningEffort": "medium",
102+
"reasoningSummary": "auto",
103+
"textVerbosity": "medium"
104+
}
105+
```
106+
107+
- **`reasoningEffort: "medium"`** - Balanced computational effort for reasoning
108+
- **`reasoningSummary: "auto"`** - Automatically adapts summary verbosity
109+
- **`textVerbosity: "medium"`** - Balanced output length
110+
111+
These defaults match the official Codex CLI behavior and can be customized (see Configuration below).
112+
113+
## Configuration
114+
115+
You can customize model behavior for both `gpt-5` and `gpt-5-codex` models accessed via ChatGPT subscription.
116+
117+
### Available Settings
118+
119+
⚠️ **Important**: The two models have different supported values. Only use values listed in the tables below to avoid API errors.
120+
121+
#### GPT-5 Model
122+
123+
| Setting | Supported Values | Plugin Default | Description |
124+
|---------|-----------------|----------------|-------------|
125+
| `reasoningEffort` | `minimal`, `low`, `medium`, `high` | **`medium`** | Computational effort for reasoning |
126+
| `reasoningSummary` | `auto`, `detailed` | **`auto`** | Verbosity of reasoning summaries |
127+
| `textVerbosity` | `low`, `medium`, `high` | **`medium`** | Output length and detail level |
128+
129+
#### GPT-5-Codex Model
130+
131+
| Setting | Supported Values | Plugin Default | Description |
132+
|---------|-----------------|----------------|-------------|
133+
| `reasoningEffort` | `minimal`*, `low`, `medium`, `high` | **`medium`** | Computational effort for reasoning |
134+
| `reasoningSummary` | `auto`, `detailed` | **`auto`** | Verbosity of reasoning summaries |
135+
| `textVerbosity` | `medium` only | **`medium`** | Output length (codex only supports medium) |
136+
137+
\* `minimal` is auto-normalized to `low` for gpt-5-codex
138+
139+
#### Shared Settings (Both Models)
140+
141+
| Setting | Values | Plugin Default | Description |
142+
|---------|--------|----------------|-------------|
143+
| `include` | Array of strings | `["reasoning.encrypted_content"]` | Additional response fields (for stateless reasoning) |
144+
145+
### Configuration Examples
146+
147+
#### Global Configuration
148+
149+
Apply the same settings to all GPT-5 models:
150+
151+
```json
152+
{
153+
"$schema": "https://opencode.ai/config.json",
154+
"plugin": ["opencode-openai-codex-auth"],
155+
"model": "openai/gpt-5-codex",
156+
"provider": {
157+
"openai": {
158+
"options": {
159+
"reasoningEffort": "high",
160+
"reasoningSummary": "detailed",
161+
"textVerbosity": "medium"
162+
}
163+
}
164+
}
165+
}
166+
```
167+
168+
#### Per-Model Configuration
169+
170+
Different settings for different models:
171+
172+
```json
173+
{
174+
"$schema": "https://opencode.ai/config.json",
175+
"plugin": ["opencode-openai-codex-auth"],
176+
"provider": {
177+
"openai": {
178+
"models": {
179+
"gpt-5-codex": {
180+
"options": {
181+
"reasoningEffort": "high",
182+
"reasoningSummary": "detailed",
183+
"textVerbosity": "medium"
184+
}
185+
},
186+
"gpt-5": {
187+
"options": {
188+
"reasoningEffort": "high",
189+
"reasoningSummary": "detailed",
190+
"textVerbosity": "low"
191+
}
192+
}
193+
}
194+
}
195+
}
196+
}
197+
```
198+
199+
#### Mixed Configuration
200+
201+
Global defaults with per-model overrides:
202+
203+
```json
204+
{
205+
"$schema": "https://opencode.ai/config.json",
206+
"plugin": ["opencode-openai-codex-auth"],
207+
"model": "openai/gpt-5-codex",
208+
"provider": {
209+
"openai": {
210+
"options": {
211+
"reasoningEffort": "medium",
212+
"reasoningSummary": "auto",
213+
"textVerbosity": "medium"
214+
},
215+
"models": {
216+
"gpt-5-codex": {
217+
"options": {
218+
"reasoningSummary": "detailed"
219+
}
220+
}
221+
}
222+
}
223+
}
224+
}
90225
```
91226

92-
The plugin automatically configures:
93-
- **High reasoning effort** for deep thinking
94-
- **Detailed reasoning summaries** to show thought process
95-
- **Medium text verbosity** for balanced output
227+
In this example:
228+
- `gpt-5-codex` uses: `reasoningEffort: "medium"`, `reasoningSummary: "detailed"` (overridden), `textVerbosity: "medium"`
229+
- `gpt-5` uses all global defaults: `reasoningEffort: "medium"`, `reasoningSummary: "auto"`, `textVerbosity: "medium"`
96230

97231
## How It Works
98232

@@ -111,13 +245,13 @@ The plugin:
111245
6. **Tool Remapping**: Injects instructions to map Codex tools to opencode tools:
112246
- `apply_patch``edit`
113247
- `update_plan``todowrite`
114-
7. **Reasoning Configuration**: Forces high reasoning effort with detailed summaries
115-
8. **History Filtering**: Removes stored conversation IDs since Codex uses `store: false`
248+
7. **Reasoning Configuration**: Defaults to medium effort and auto summaries (configurable per-model)
249+
8. **Encrypted Reasoning**: Includes encrypted reasoning content for stateless multi-turn conversations
250+
9. **History Filtering**: Removes stored conversation IDs since Codex uses `store: false`
116251

117252
## Limitations
118253

119254
- **ChatGPT Plus/Pro required**: Must have an active ChatGPT Plus or Pro subscription
120-
- **Medium text verbosity**: Codex only supports `medium` for text verbosity
121255

122256
## Troubleshooting
123257

index.mjs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ export async function OpenAIAuthPlugin({ client }) {
2121
provider: "openai",
2222
/**
2323
* @param {() => Promise<any>} getAuth
24-
* @param {any} _provider
24+
* @param {any} provider - Provider configuration from opencode.json
2525
*/
26-
async loader(getAuth, _provider) {
26+
async loader(getAuth, provider) {
2727
const auth = await getAuth();
2828

2929
// Only handle OAuth auth type, skip API key auth
@@ -43,6 +43,13 @@ export async function OpenAIAuthPlugin({ client }) {
4343
return {};
4444
}
4545

46+
// Extract user configuration from provider structure
47+
// Supports both global options and per-model options following Anthropic pattern
48+
const userConfig = {
49+
global: provider?.options || {},
50+
models: provider?.models || {},
51+
};
52+
4653
// Fetch Codex instructions (cached with ETag)
4754
const CODEX_INSTRUCTIONS = await getCodexInstructions();
4855

@@ -118,8 +125,8 @@ export async function OpenAIAuthPlugin({ client }) {
118125
body,
119126
});
120127

121-
// Transform request body for Codex API
122-
body = transformRequestBody(body, CODEX_INSTRUCTIONS);
128+
// Transform request body for Codex API with user configuration
129+
body = transformRequestBody(body, CODEX_INSTRUCTIONS, userConfig);
123130

124131
// Log transformed request
125132
logRequest("after-transform", {
@@ -130,6 +137,8 @@ export async function OpenAIAuthPlugin({ client }) {
130137
hasInput: !!body.input,
131138
inputLength: body.input?.length,
132139
reasoning: body.reasoning,
140+
textVerbosity: body.text?.verbosity,
141+
include: body.include,
133142
body,
134143
});
135144

lib/request-transformer.mjs

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,53 @@ export function normalizeModel(model) {
1919
}
2020

2121
/**
22-
* Configure reasoning parameters based on model variant
22+
* Extract configuration for a specific model
23+
* Merges global options with model-specific options (model-specific takes precedence)
24+
* @param {string} modelName - Model name (e.g., "gpt-5-codex")
25+
* @param {object} userConfig - Full user configuration object
26+
* @returns {object} Merged configuration for this model
27+
*/
28+
export function getModelConfig(modelName, userConfig = {}) {
29+
const globalOptions = userConfig.global || {};
30+
const modelOptions = userConfig.models?.[modelName]?.options || {};
31+
32+
// Model-specific options override global options
33+
return { ...globalOptions, ...modelOptions };
34+
}
35+
36+
/**
37+
* Configure reasoning parameters based on model variant and user config
38+
*
39+
* NOTE: This plugin follows Codex CLI defaults instead of opencode defaults because:
40+
* - We're accessing the ChatGPT backend API (not OpenAI Platform API)
41+
* - opencode explicitly excludes gpt-5-codex from automatic reasoning configuration
42+
* - Codex CLI has been thoroughly tested against this backend
43+
*
2344
* @param {string} originalModel - Original model name before normalization
45+
* @param {object} userConfig - User configuration object
2446
* @returns {object} Reasoning configuration
2547
*/
26-
export function getReasoningConfig(originalModel) {
48+
export function getReasoningConfig(originalModel, userConfig = {}) {
2749
const isLightweight =
2850
originalModel?.includes("nano") || originalModel?.includes("mini");
51+
const isCodex = originalModel?.includes("codex");
52+
53+
// Default based on model type (Codex CLI defaults)
54+
const defaultEffort = isLightweight ? "minimal" : "medium";
55+
56+
// Get user-requested effort
57+
let effort = userConfig.reasoningEffort || defaultEffort;
58+
59+
// Normalize "minimal" to "low" for gpt-5-codex
60+
// Codex CLI does not provide a "minimal" preset for gpt-5-codex
61+
// (only low/medium/high - see model_presets.rs:20-40)
62+
if (isCodex && effort === "minimal") {
63+
effort = "low";
64+
}
2965

3066
return {
31-
effort: isLightweight ? "minimal" : "high",
32-
summary: "detailed", // Only supported value for gpt-5
67+
effort,
68+
summary: userConfig.reasoningSummary || "auto", // Changed from "detailed" to match Codex CLI
3369
};
3470
}
3571

@@ -75,15 +111,26 @@ export function addToolRemapMessage(input, hasTools) {
75111

76112
/**
77113
* Transform request body for Codex API
114+
*
115+
* NOTE: Configuration follows Codex CLI patterns instead of opencode defaults:
116+
* - opencode sets textVerbosity="low" for gpt-5, but Codex CLI uses "medium"
117+
* - opencode excludes gpt-5-codex from reasoning configuration
118+
* - This plugin uses store=false (stateless), requiring encrypted reasoning content
119+
*
78120
* @param {object} body - Original request body
79121
* @param {string} codexInstructions - Codex system instructions
122+
* @param {object} userConfig - User configuration from loader
80123
* @returns {object} Transformed request body
81124
*/
82-
export function transformRequestBody(body, codexInstructions) {
125+
export function transformRequestBody(body, codexInstructions, userConfig = {}) {
83126
const originalModel = body.model;
127+
const normalizedModel = normalizeModel(body.model);
128+
129+
// Get model-specific configuration (merges global + per-model options)
130+
const modelConfig = getModelConfig(normalizedModel, userConfig);
84131

85132
// Normalize model name
86-
body.model = normalizeModel(body.model);
133+
body.model = normalizedModel;
87134

88135
// Codex required fields
89136
body.store = false;
@@ -96,19 +143,25 @@ export function transformRequestBody(body, codexInstructions) {
96143
body.input = addToolRemapMessage(body.input, !!body.tools);
97144
}
98145

99-
// Configure reasoning
100-
const reasoningConfig = getReasoningConfig(originalModel);
146+
// Configure reasoning (use model-specific config)
147+
const reasoningConfig = getReasoningConfig(originalModel, modelConfig);
101148
body.reasoning = {
102149
...body.reasoning,
103150
...reasoningConfig,
104151
};
105152

106-
// Configure text verbosity
153+
// Configure text verbosity (support user config)
154+
// Default: "medium" (matches Codex CLI default for all GPT-5 models)
107155
body.text = {
108156
...body.text,
109-
verbosity: "medium",
157+
verbosity: modelConfig.textVerbosity || "medium",
110158
};
111159

160+
// Add include for encrypted reasoning content
161+
// Default: ["reasoning.encrypted_content"] (required for stateless operation with store=false)
162+
// This allows reasoning context to persist across turns without server-side storage
163+
body.include = modelConfig.include || ["reasoning.encrypted_content"];
164+
112165
// Remove unsupported parameters
113166
body.max_output_tokens = undefined;
114167
body.max_completion_tokens = undefined;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "opencode-openai-codex-auth",
3-
"version": "1.0.3",
3+
"version": "1.0.4",
44
"description": "OpenAI ChatGPT (Codex backend) OAuth auth plugin for opencode - use your ChatGPT Plus/Pro subscription instead of API credits",
55
"main": "./index.mjs",
66
"type": "module",

test-config.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://opencode.ai/config.json",
3+
"plugin": ["file:///home/code/projects/ben-vargas/ai-opencode-openai-codex-auth/config-support"],
4+
"model": "openai/gpt-5-codex",
5+
"provider": {
6+
"openai": {
7+
"options": {
8+
"reasoningEffort": "medium",
9+
"reasoningSummary": "auto",
10+
"textVerbosity": "medium"
11+
},
12+
"models": {
13+
"gpt-5-codex": {
14+
"options": {
15+
"reasoningSummary": "concise"
16+
}
17+
}
18+
}
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)