Files
orca/src/main/codex/codex-structured-session-options.test.ts
T
Brennan BensonandMerge Sim 872bd51d47 fix(native-chat): reland large structured command results (#17720)
* fix(native-chat): preserve large structured command results (#17707)

* fix(native-chat): preserve large structured command results

* chore: place native chat validation artifacts under docs

* chore: drop stale root package config

* fix(native-chat): enforce rebuilt lifecycle append slots

---------

Co-authored-by: Merge Sim <sim@local>

* chore: omit native-chat reland planning docs

* fix(native-chat): remove journal store import cycle

* fix(native-chat): keep journal factory acyclic

---------

Co-authored-by: Merge Sim <sim@local>
2026-08-31 13:12:19 -07:00

175 lines
5.2 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import type { CodexAppServerConnection } from './codex-app-server-connection'
import { CodexAcquisitionWindow } from './codex-structured-acquisition-window'
import {
applyCodexStructuredSessionOption,
readCodexStructuredSessionOptions,
reportedCodexThreadOptions,
restoredCodexSessionOptions
} from './codex-structured-session-options'
import type { CodexSession } from './codex-structured-session-state'
function optionSession(request: CodexAppServerConnection['request']): CodexSession {
return {
connection: {
pid: 1,
closed: false,
request,
notify: () => {},
respond: () => {},
respondWithError: () => {},
close: async () => true
},
ended: false,
requestedClose: false,
fence: 1,
acquisitionGeneration: 'generation-1',
threadId: 'thread-1',
historyPath: null,
prompts: new CodexAcquisitionWindow().prompts,
options: new Map(),
reportedOptions: { model: 'gpt-live', effort: 'high' },
turnIdWaiters: [],
translator: null
}
}
describe('structured Codex session options', () => {
it('filters restored records to recognized turn options', () => {
expect(
Object.fromEntries(
restoredCodexSessionOptions({
model: 'gpt-live',
effort: 'high',
threadId: 'thread-injected',
input: 'input-injected'
})
)
).toEqual({ model: 'gpt-live', effort: 'high' })
})
it('hydrates paged provider models and their supported efforts', async () => {
const request = vi.fn(async (_method: string, params?: Record<string, unknown>) =>
params?.cursor
? {
data: [
{
model: 'gpt-second',
displayName: 'GPT Second',
description: 'Fast',
hidden: false,
supportedReasoningEfforts: [
{ reasoningEffort: 'low', description: 'Quick reasoning' }
],
defaultReasoningEffort: 'low',
isDefault: false
}
],
nextCursor: null
}
: {
data: [
{
model: 'gpt-live',
displayName: 'GPT Live',
hidden: false,
supportedReasoningEfforts: [
{ reasoningEffort: 'medium', description: 'Balanced' },
{ reasoningEffort: 'high', description: 'Deep reasoning' }
],
defaultReasoningEffort: 'medium',
isDefault: true
}
],
nextCursor: 'page-2'
}
)
await expect(
readCodexStructuredSessionOptions({
connection: { request } as never,
current: { model: 'gpt-live', effort: 'medium' }
})
).resolves.toEqual({
models: [
{
id: 'gpt-live',
label: 'GPT Live',
isDefault: true,
defaultEffort: 'medium',
efforts: [
{ value: 'medium', label: 'Medium', description: 'Balanced' },
{ value: 'high', label: 'High', description: 'Deep reasoning' }
]
},
{
id: 'gpt-second',
label: 'GPT Second',
description: 'Fast',
isDefault: false,
defaultEffort: 'low',
efforts: [{ value: 'low', label: 'Low', description: 'Quick reasoning' }]
}
],
current: { model: 'gpt-live', effort: 'medium' }
})
expect(request).toHaveBeenNthCalledWith(
2,
'model/list',
{ limit: 100, includeHidden: false, cursor: 'page-2' },
{ timeoutMs: undefined }
)
})
it('hydrates current values from thread start or resume', () => {
expect(
reportedCodexThreadOptions({
threadId: 'thread-1',
historyPath: null,
model: 'gpt-live',
effort: 'high'
})
).toEqual({ model: 'gpt-live', effort: 'high' })
})
it('reconciles an incompatible effort when only the model changes', async () => {
const session = optionSession(
vi.fn(async () => ({
data: [
{
model: 'gpt-live',
supportedReasoningEfforts: [{ reasoningEffort: 'high' }],
defaultReasoningEffort: 'high'
},
{
model: 'gpt-fast',
supportedReasoningEfforts: [{ reasoningEffort: 'low' }],
defaultReasoningEffort: 'low'
}
],
nextCursor: null
}))
)
await expect(
applyCodexStructuredSessionOption(session, 'model', 'gpt-fast', undefined)
).resolves.toEqual({ model: 'gpt-fast', effort: 'low' })
})
it('rejects values absent from the provider catalog', async () => {
const session = optionSession(
vi.fn(async () => ({
data: [{ model: 'gpt-live', supportedReasoningEfforts: [] }],
nextCursor: null
}))
)
await expect(
applyCodexStructuredSessionOption(session, 'model', 'not-entitled', undefined)
).rejects.toThrow('does not offer model not-entitled')
await expect(
applyCodexStructuredSessionOption(session, 'effort', 'high', undefined)
).rejects.toThrow('does not support high')
})
})