mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-14 18:18:21 +00:00
fix(thinking): handle clear no-op and tighten override coverage
This commit is contained in:
1 parent
92e2ec111d
commit
954baecfe4
8 files changed
+298
-28
No files matched your search
@@ -5,6 +5,11 @@ import {
|
||||
CodexReasoningProxy,
|
||||
getEffortForModel,
|
||||
} from '../../../src/cliproxy/codex-reasoning-proxy';
|
||||
import {
|
||||
parseEnvThinkingOverride,
|
||||
resolveRuntimeThinkingOverride,
|
||||
shouldDisableCodexReasoning,
|
||||
} from '../../../src/cliproxy/executor/thinking-override-resolver';
|
||||
|
||||
type JsonRecord = Record<string, unknown>;
|
||||
|
||||
@@ -224,4 +229,122 @@ describe('CodexReasoningProxy extended-context compatibility', () => {
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(capturedBody?.model).toBe('enterprise-internal-high');
|
||||
});
|
||||
|
||||
it('keeps reasoning enabled when CCS_THINKING=high overrides config off', async () => {
|
||||
let capturedBody: JsonRecord | null = null;
|
||||
|
||||
expect(parseEnvThinkingOverride('high')).toBe('high');
|
||||
const { thinkingOverride } = resolveRuntimeThinkingOverride(undefined, 'high');
|
||||
const disableEffort = shouldDisableCodexReasoning(
|
||||
{
|
||||
mode: 'off',
|
||||
tier_defaults: {
|
||||
opus: 'high',
|
||||
sonnet: 'medium',
|
||||
haiku: 'low',
|
||||
},
|
||||
show_warnings: true,
|
||||
},
|
||||
thinkingOverride
|
||||
);
|
||||
|
||||
const upstream = http.createServer((req, res) => {
|
||||
let rawBody = '';
|
||||
req.setEncoding('utf8');
|
||||
req.on('data', (chunk) => {
|
||||
rawBody += chunk;
|
||||
});
|
||||
req.on('end', () => {
|
||||
capturedBody = rawBody ? (JSON.parse(rawBody) as JsonRecord) : {};
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ ok: true }));
|
||||
});
|
||||
});
|
||||
cleanupServers.push(upstream);
|
||||
|
||||
const upstreamPort = await listenOnRandomPort(upstream);
|
||||
const proxy = new CodexReasoningProxy({
|
||||
upstreamBaseUrl: `http://127.0.0.1:${upstreamPort}`,
|
||||
disableEffort,
|
||||
defaultEffort: 'medium',
|
||||
modelMap: {
|
||||
defaultModel: 'gpt-5.3-codex',
|
||||
},
|
||||
});
|
||||
|
||||
const proxyPort = await proxy.start();
|
||||
const response = await postJson(
|
||||
`http://127.0.0.1:${proxyPort}/api/provider/codex/v1/messages`,
|
||||
{
|
||||
model: 'gpt-5.3-codex-high',
|
||||
messages: [],
|
||||
}
|
||||
);
|
||||
|
||||
proxy.stop();
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(disableEffort).toBe(false);
|
||||
expect(capturedBody?.model).toBe('gpt-5.3-codex');
|
||||
expect((capturedBody?.reasoning as JsonRecord | undefined)?.effort).toBe('high');
|
||||
});
|
||||
|
||||
it('disables reasoning when CCS_THINKING=off is provided', async () => {
|
||||
let capturedBody: JsonRecord | null = null;
|
||||
|
||||
expect(parseEnvThinkingOverride('off')).toBe('off');
|
||||
const { thinkingOverride } = resolveRuntimeThinkingOverride(undefined, 'off');
|
||||
const disableEffort = shouldDisableCodexReasoning(
|
||||
{
|
||||
mode: 'auto',
|
||||
tier_defaults: {
|
||||
opus: 'high',
|
||||
sonnet: 'medium',
|
||||
haiku: 'low',
|
||||
},
|
||||
show_warnings: true,
|
||||
},
|
||||
thinkingOverride
|
||||
);
|
||||
|
||||
const upstream = http.createServer((req, res) => {
|
||||
let rawBody = '';
|
||||
req.setEncoding('utf8');
|
||||
req.on('data', (chunk) => {
|
||||
rawBody += chunk;
|
||||
});
|
||||
req.on('end', () => {
|
||||
capturedBody = rawBody ? (JSON.parse(rawBody) as JsonRecord) : {};
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ ok: true }));
|
||||
});
|
||||
});
|
||||
cleanupServers.push(upstream);
|
||||
|
||||
const upstreamPort = await listenOnRandomPort(upstream);
|
||||
const proxy = new CodexReasoningProxy({
|
||||
upstreamBaseUrl: `http://127.0.0.1:${upstreamPort}`,
|
||||
disableEffort,
|
||||
defaultEffort: 'medium',
|
||||
modelMap: {
|
||||
defaultModel: 'gpt-5.3-codex',
|
||||
},
|
||||
});
|
||||
|
||||
const proxyPort = await proxy.start();
|
||||
const response = await postJson(
|
||||
`http://127.0.0.1:${proxyPort}/api/provider/codex/v1/messages`,
|
||||
{
|
||||
model: 'gpt-5.3-codex-high',
|
||||
messages: [],
|
||||
}
|
||||
);
|
||||
|
||||
proxy.stop();
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(disableEffort).toBe(true);
|
||||
expect(capturedBody?.model).toBe('gpt-5.3-codex');
|
||||
expect((capturedBody?.reasoning as JsonRecord | undefined)?.effort).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
parseThinkingCommandArgs,
|
||||
parseThinkingOverrideInput,
|
||||
} from '../../../src/commands/config-thinking-command';
|
||||
import { clearProviderOverride } from '../../../src/commands/config-thinking-parser';
|
||||
|
||||
describe('config thinking command parser', () => {
|
||||
it('rejects missing required option values', () => {
|
||||
@@ -41,3 +42,47 @@ describe('config thinking override normalization', () => {
|
||||
expect(parseThinkingOverrideInput('8192')).toEqual({ value: 8192 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('config thinking provider override clearing', () => {
|
||||
it('is a no-op when provider override does not exist', () => {
|
||||
const result = clearProviderOverride(
|
||||
{
|
||||
codex: { opus: 'high' },
|
||||
},
|
||||
'gemini'
|
||||
);
|
||||
|
||||
expect(result.changed).toBe(false);
|
||||
expect(result.nextOverrides).toEqual({
|
||||
codex: { opus: 'high' },
|
||||
});
|
||||
});
|
||||
|
||||
it('is a no-op when provider exists but tier override does not', () => {
|
||||
const result = clearProviderOverride(
|
||||
{
|
||||
codex: { opus: 'high' },
|
||||
},
|
||||
'codex',
|
||||
'haiku'
|
||||
);
|
||||
|
||||
expect(result.changed).toBe(false);
|
||||
expect(result.nextOverrides).toEqual({
|
||||
codex: { opus: 'high' },
|
||||
});
|
||||
});
|
||||
|
||||
it('removes provider entry when last tier is cleared', () => {
|
||||
const result = clearProviderOverride(
|
||||
{
|
||||
codex: { opus: 'high' },
|
||||
},
|
||||
'codex',
|
||||
'opus'
|
||||
);
|
||||
|
||||
expect(result.changed).toBe(true);
|
||||
expect(result.nextOverrides).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
import { resolveThinkingProviderOverridesForSave } from '../../../src/web-server/routes/misc-routes';
|
||||
|
||||
describe('thinking routes logic', () => {
|
||||
it('clears provider overrides when clear flag is set', () => {
|
||||
const result = resolveThinkingProviderOverridesForSave(
|
||||
{
|
||||
codex: { opus: 'high' },
|
||||
},
|
||||
{
|
||||
gemini: { sonnet: 'medium' },
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('applies normalized updates when provided and clear flag is false', () => {
|
||||
const updates = {
|
||||
gemini: { sonnet: 'medium' },
|
||||
};
|
||||
const result = resolveThinkingProviderOverridesForSave(
|
||||
{
|
||||
codex: { opus: 'high' },
|
||||
},
|
||||
updates,
|
||||
false
|
||||
);
|
||||
|
||||
expect(result).toEqual(updates);
|
||||
});
|
||||
|
||||
it('preserves current overrides when no updates are provided', () => {
|
||||
const current = {
|
||||
codex: { opus: 'high' },
|
||||
};
|
||||
const result = resolveThinkingProviderOverridesForSave(current, undefined, false);
|
||||
|
||||
expect(result).toEqual(current);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user