Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 59 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/cli/src/providers/aliases/codex.config
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"description": "OpenAI Codex (ChatGPT backend with OAuth)",
"ephemeralSettings": {
"context-limit": 262144,
"prompt-caching": "24h"
"prompt-caching": "24h",
"reasoning.effort": "medium",
"reasoning.summary": "auto"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @license
* Copyright 2025 Vybestack LLC
* SPDX-License-Identifier: Apache-2.0
*
* TDD tests for codex.config reasoning.summary default
* @issue #922 - GPT-5.2-Codex thinking blocks not visible
*/

import { describe, it, expect } from 'vitest';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { loadProviderAliasEntries } from './providerAliases.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

describe('codex.config reasoning.summary default @issue:922', () => {
it('should have a codex.config file', () => {
const codexConfigPath = path.join(__dirname, 'aliases', 'codex.config');
expect(fs.existsSync(codexConfigPath)).toBe(true);
});

it('should set reasoning.summary=auto in ephemerals', () => {
const aliases = loadProviderAliasEntries();
const codexAlias = aliases.find((a) => a.alias === 'codex');

expect(codexAlias).toBeDefined();
expect(codexAlias?.config.ephemeralSettings).toBeDefined();
expect(codexAlias?.config.ephemeralSettings?.['reasoning.summary']).toBe(
'auto',
);
});

it('should set reasoning.effort in ephemerals (existing behavior)', () => {
const aliases = loadProviderAliasEntries();
const codexAlias = aliases.find((a) => a.alias === 'codex');

expect(codexAlias).toBeDefined();
// Codex should have some default effort level
expect(
codexAlias?.config.ephemeralSettings?.['reasoning.effort'],
).toBeDefined();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @license
* Copyright 2025 Vybestack LLC
* SPDX-License-Identifier: Apache-2.0
*
* TDD tests for reasoning.summary profile save/load
* @issue #922 - GPT-5.2-Codex thinking blocks not visible
*/

import { describe, it, expect } from 'vitest';
import { PROFILE_EPHEMERAL_KEYS } from './runtimeSettings.js';

describe('reasoning.summary profile save/load @issue:922', () => {
it('should include reasoning.summary in PROFILE_EPHEMERAL_KEYS', () => {
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.summary');
});

it('should include all reasoning.* keys in PROFILE_EPHEMERAL_KEYS', () => {
// Verify all reasoning settings are saveable
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.enabled');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.includeInContext');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.includeInResponse');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.format');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.stripFromContext');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.effort');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.maxTokens');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.summary');
Comment on lines +18 to +27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add reasoning.verbosity to the “all reasoning. keys” assertion.*

The test promises full reasoning coverage but omits reasoning.verbosity, so a regression could slip through unnoticed.

✅ Proposed fix
   expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.maxTokens');
   expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.summary');
+  expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.verbosity');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should include all reasoning.* keys in PROFILE_EPHEMERAL_KEYS', () => {
// Verify all reasoning settings are saveable
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.enabled');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.includeInContext');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.includeInResponse');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.format');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.stripFromContext');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.effort');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.maxTokens');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.summary');
it('should include all reasoning.* keys in PROFILE_EPHEMERAL_KEYS', () => {
// Verify all reasoning settings are saveable
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.enabled');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.includeInContext');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.includeInResponse');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.format');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.stripFromContext');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.effort');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.maxTokens');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.summary');
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.verbosity');
🤖 Prompt for AI Agents
In `@packages/cli/src/runtime/runtimeSettings.reasoningSummary.test.ts` around
lines 18 - 27, The test checking that PROFILE_EPHEMERAL_KEYS includes all
reasoning.* keys is missing the 'reasoning.verbosity' key; update the test in
runtimeSettings.reasoningSummary.test.ts to add an expectation that
PROFILE_EPHEMERAL_KEYS contains 'reasoning.verbosity' (i.e., add
expect(PROFILE_EPHEMERAL_KEYS).toContain('reasoning.verbosity'); alongside the
other reasoning.* assertions) so the PROFILE_EPHEMERAL_KEYS coverage remains
complete.

});
});
2 changes: 2 additions & 0 deletions packages/cli/src/runtime/runtimeSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,8 @@ export const PROFILE_EPHEMERAL_KEYS: readonly string[] = [
'reasoning.stripFromContext',
'reasoning.effort',
'reasoning.maxTokens',
'reasoning.summary',
'text.verbosity',
// Prompt caching settings (Issue #680)
'prompt-caching',
'include-folder-structure',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* @license
* Copyright 2025 Vybestack LLC
* SPDX-License-Identifier: Apache-2.0
*
* TDD tests for reasoning.summary ephemeral setting
* @issue #922 - GPT-5.2-Codex thinking blocks not visible
*/

import { describe, it, expect } from 'vitest';
import {
isValidEphemeralSetting,
ephemeralSettingHelp,
} from './ephemeralSettings.js';

describe('reasoning.summary ephemeral setting @issue:922', () => {
describe('ephemeralSettingHelp', () => {
it('should include reasoning.summary in descriptions', () => {
expect(ephemeralSettingHelp['reasoning.summary']).toBeDefined();
});

it('should mention OpenAI in the description', () => {
const description = ephemeralSettingHelp['reasoning.summary'];
expect(description?.toLowerCase()).toContain('openai');
});

it('should mention valid values in the description', () => {
const description = ephemeralSettingHelp['reasoning.summary'];
expect(description).toContain('auto');
expect(description).toContain('concise');
expect(description).toContain('detailed');
expect(description).toContain('none');
});
});

describe('isValidEphemeralSetting validation', () => {
it('should accept reasoning.summary=auto', () => {
expect(isValidEphemeralSetting('reasoning.summary', 'auto')).toBe(true);
});

it('should accept reasoning.summary=concise', () => {
expect(isValidEphemeralSetting('reasoning.summary', 'concise')).toBe(
true,
);
});

it('should accept reasoning.summary=detailed', () => {
expect(isValidEphemeralSetting('reasoning.summary', 'detailed')).toBe(
true,
);
});

it('should accept reasoning.summary=none', () => {
expect(isValidEphemeralSetting('reasoning.summary', 'none')).toBe(true);
});

it('should reject reasoning.summary=invalid', () => {
expect(isValidEphemeralSetting('reasoning.summary', 'invalid')).toBe(
false,
);
});

it('should reject reasoning.summary=true (wrong type)', () => {
expect(isValidEphemeralSetting('reasoning.summary', true)).toBe(false);
});

it('should reject reasoning.summary=123 (wrong type)', () => {
expect(isValidEphemeralSetting('reasoning.summary', 123)).toBe(false);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* @license
* Copyright 2025 Vybestack LLC
* SPDX-License-Identifier: Apache-2.0
*/

import { describe, expect, it } from 'vitest';
import {
parseEphemeralSettingValue,
ephemeralSettingHelp,
} from './ephemeralSettings.js';

describe('text.verbosity ephemeral setting', () => {
describe('parseEphemeralSettingValue', () => {
it('should accept "low" as valid verbosity', () => {
const result = parseEphemeralSettingValue('text.verbosity', 'low');
expect(result.success).toBe(true);
if (result.success) {
expect(result.value).toBe('low');
}
});

it('should accept "medium" as valid verbosity', () => {
const result = parseEphemeralSettingValue('text.verbosity', 'medium');
expect(result.success).toBe(true);
if (result.success) {
expect(result.value).toBe('medium');
}
});

it('should accept "high" as valid verbosity', () => {
const result = parseEphemeralSettingValue('text.verbosity', 'high');
expect(result.success).toBe(true);
if (result.success) {
expect(result.value).toBe('high');
}
});

it('should normalize case to lowercase', () => {
const result = parseEphemeralSettingValue('text.verbosity', 'HIGH');
expect(result.success).toBe(true);
if (result.success) {
expect(result.value).toBe('high');
}
});

it('should reject invalid verbosity values', () => {
const result = parseEphemeralSettingValue('text.verbosity', 'invalid');
expect(result.success).toBe(false);
if (!result.success) {
expect(result.message).toContain('must be one of: low, medium, high');
}
});
});

describe('ephemeralSettingHelp', () => {
it('should have help text for text.verbosity', () => {
expect(ephemeralSettingHelp['text.verbosity']).toBeDefined();
expect(ephemeralSettingHelp['text.verbosity']).toContain('verbosity');
expect(ephemeralSettingHelp['text.verbosity']).toContain('OpenAI');
});
});
});
Loading
Loading