Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions src/_locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@
"OpenAI (GPT-5.6 Terra)": "OpenAI (GPT-5.6 Terra)",
"OpenAI (GPT-5.6 Luna)": "OpenAI (GPT-5.6 Luna)",
"OpenAI (GPT-6 Astra)": "OpenAI (GPT-6 Astra)",
"OpenAI (GPT-6 Sol)": "OpenAI (GPT-6 Sol)",
"OpenAI (GPT-6 Luna)": "OpenAI (GPT-6 Luna)",
Comment thread
PeterDaveHello marked this conversation as resolved.
"Anthropic (Claude Sonnet 4.6)": "Anthropic (Claude Sonnet 4.6)",
"This provider is still used by other API modes or saved conversations": "This provider is still used by other API modes or saved conversations",
"This API key is set on the selected custom mode. Editing it here will create a dedicated provider for that mode.": "This API key is set on the selected custom mode. Editing it here will create a dedicated provider for that mode.",
Expand Down
8 changes: 6 additions & 2 deletions src/config/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ export const chatgptApiModelKeys = [
'chatgptApi5_6Terra',
'chatgptApi5_6Luna',
'chatgptApi6Astra',
'chatgptApi6Sol',
'chatgptApi6Luna',
'chatgptApi4oMini',
'chatgptApi4_1',
'chatgptApi4_1_mini',
Expand Down Expand Up @@ -335,6 +337,8 @@ export const Models = {
chatgptApi5_6Terra: { value: 'gpt-5.6-terra', desc: 'OpenAI (GPT-5.6 Terra)' },
chatgptApi5_6Luna: { value: 'gpt-5.6-luna', desc: 'OpenAI (GPT-5.6 Luna)' },
chatgptApi6Astra: { value: 'gpt-6-astra', desc: 'OpenAI (GPT-6 Astra)' },
chatgptApi6Sol: { value: 'gpt-6-sol', desc: 'OpenAI (GPT-6 Sol)' },
chatgptApi6Luna: { value: 'gpt-6-luna', desc: 'OpenAI (GPT-6 Luna)' },

chatgptApi4_1: { value: 'gpt-4.1', desc: 'OpenAI (GPT-4.1)' },
chatgptApi4_1_mini: { value: 'gpt-4.1-mini', desc: 'OpenAI (GPT-4.1 mini)' },
Expand Down Expand Up @@ -765,9 +769,9 @@ export const defaultApiModeIds = [
'ollamaModel',
'customModel',
'azureOpenAi',
'chatgptApi5_6Sol',
'chatgptApi6Sol',
'chatgptApi5_6Terra',
'chatgptApi5_6Luna',
'chatgptApi6Luna',
Comment thread
PeterDaveHello marked this conversation as resolved.
'chatgptApi6Astra',
'xaiGrok4_6',
'xaiGrok4_5',
Expand Down
2 changes: 1 addition & 1 deletion src/services/apis/openai-token-params.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const OPENAI_MAX_COMPLETION_TOKENS_MODEL_PATTERN =
/^(?:gpt-5(?:[.-]|$)|gpt-6-astra(?:-|$)|chat-latest$)/
/^(?:gpt-5(?:[.-]|$)|gpt-6-(?:astra|sol|luna)(?:-|$)|chat-latest$)/

function shouldUseMaxCompletionTokens(provider, model) {
const normalizedProvider = String(provider || '').toLowerCase()
Expand Down
2 changes: 2 additions & 0 deletions src/services/apis/temperature-params.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const MODELS_WITHOUT_CUSTOM_TEMPERATURE = new Set([
'claude-fable-5',
'claude-fable-5-1',
'gpt-6-astra',
'gpt-6-sol',
'gpt-6-luna',
])

function normalizeModelId(model) {
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/config/config-predicates.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getNavigatorLanguage,
getPreferredLanguageKey,
Models,
defaultApiModeIds,
chatgptApiModelKeys,
gptApiModelKeys,
claudeApiModelKeys,
Expand Down Expand Up @@ -52,6 +53,8 @@ const representativeChatgptApiModelNames = [
'chatgptApi5_6Sol',
'chatgptApi5_6Terra',
'chatgptApi5_6Luna',
'chatgptApi6Sol',
'chatgptApi6Luna',
]
const representativeGptCompletionApiModelNames = ['gptApiInstruct']
const representativeClaudeApiModelNames = ['claudeOpus48Api', 'claudeSonnet46Api']
Expand Down Expand Up @@ -82,6 +85,13 @@ afterEach(() => {
restoreNavigator()
})

test('GPT-6 Sol and Luna replace their GPT-5.6 counterparts in the default presets', () => {
assert.equal(defaultApiModeIds.includes('chatgptApi6Sol'), true)
assert.equal(defaultApiModeIds.includes('chatgptApi6Luna'), true)
assert.equal(defaultApiModeIds.includes('chatgptApi5_6Sol'), false)
assert.equal(defaultApiModeIds.includes('chatgptApi5_6Luna'), false)
})

test('getNavigatorLanguage returns zh-Hant for zh-TW style locales', () => {
setNavigatorLanguage('zh-TW')
assert.equal(getNavigatorLanguage(), 'zh-Hant')
Expand Down
25 changes: 23 additions & 2 deletions tests/unit/services/apis/openai-api-compat.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ test('generateAnswersWithOpenAiApi uses max_completion_tokens for GPT-5.4 mini',
assert.equal(Object.hasOwn(body, 'max_tokens'), false)
})

test('generateAnswersWithOpenAiApi uses max_completion_tokens for GPT-6 Astra and omits unsupported temperature', async (t) => {
test('generateAnswersWithOpenAiApi uses max_completion_tokens for GPT-6 and omits unsupported temperature', async (t) => {
t.mock.method(console, 'debug', () => {})
setStorage({
customOpenAiApiUrl: 'https://api.openai.example.com',
Expand Down Expand Up @@ -780,13 +780,34 @@ test('generateAnswersWithOpenAiApi uses max_completion_tokens for GPT-6 Astra an

await generateAnswersWithOpenAiApi(port, 'CurrentQ', session, 'sk-test')

const body = JSON.parse(capturedInit.body)
let body = JSON.parse(capturedInit.body)
assert.equal(capturedInput, 'https://api.openai.example.com/v1/chat/completions')
assert.equal(body.model, 'gpt-6-astra')
assert.equal(body.max_completion_tokens, 444)
assert.equal(Object.hasOwn(body, 'max_tokens'), false)
assert.equal(Object.hasOwn(body, 'temperature'), false)
assert.equal(session.conversationRecords.at(-1).answer, 'OK')

for (const [modelName, model] of [
['chatgptApi6Sol', 'gpt-6-sol'],
['chatgptApi6Luna', 'gpt-6-luna'],
]) {
const newSession = {
modelName,
conversationRecords: [],
isRetry: false,
}
const newPort = createFakePort()

await generateAnswersWithOpenAiApi(newPort, 'CurrentQ', newSession, 'sk-test')

body = JSON.parse(capturedInit.body)
assert.equal(body.model, model)
assert.equal(body.max_completion_tokens, 444)
assert.equal(Object.hasOwn(body, 'max_tokens'), false)
assert.equal(Object.hasOwn(body, 'temperature'), false)
assert.equal(newSession.conversationRecords.at(-1).answer, 'OK')
}
})

test('generateAnswersWithOpenAiApi uses max_completion_tokens for GPT-5.4 nano', async (t) => {
Expand Down
18 changes: 15 additions & 3 deletions tests/unit/services/apis/openai-token-params.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,28 @@ test('uses max_tokens when provider is undefined', () => {
})
})

test('uses completion token limits only for OpenAI GPT-6 Astra models', () => {
for (const model of ['gpt-6-astra', 'gpt-6-astra-20260901', 'GPT-6-ASTRA']) {
test('uses completion token limits only for supported OpenAI GPT-6 models', () => {
for (const model of [
'gpt-6-astra',
'gpt-6-astra-20260901',
'GPT-6-ASTRA',
'gpt-6-sol',
'gpt-6-luna',
]) {
assert.deepEqual(getChatCompletionsTokenParams('openai', model, 1024), {
max_completion_tokens: 1024,
})
assert.deepEqual(getChatCompletionsTokenParams('some-proxy-provider', model, 1024), {
max_tokens: 1024,
})
}
for (const model of ['gpt-6-astral', 'my-gpt-6-astra', 'gpt-60', 'openai/gpt-6-astra']) {
for (const model of [
'gpt-6-astral',
'gpt-6-solar',
'my-gpt-6-astra',
'gpt-60',
'openai/gpt-6-astra',
]) {
assert.deepEqual(getChatCompletionsTokenParams('openai', model, 1024), {
max_tokens: 1024,
})
Expand Down
8 changes: 6 additions & 2 deletions tests/unit/services/apis/temperature-params.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,16 @@ test('temperature overrides remain available for earlier Gemini models', () => {
}
})

test('temperature overrides omit GPT-6 Astra across provider ID formats', () => {
test('temperature overrides omit GPT-6 models across provider ID formats', () => {
for (const model of [
'gpt-6-astra',
'openai/gpt-6-astra',
'GPT-6-ASTRA',
'gpt-6-astra-20260901',
'gpt-6-sol',
'openai/gpt-6-sol',
'gpt-6-luna',
'openai/gpt-6-luna',
]) {
assert.equal(canApplyTemperatureOverride(model), false, model)
assert.deepEqual(
Expand All @@ -117,7 +121,7 @@ test('temperature overrides omit GPT-6 Astra across provider ID formats', () =>
model,
)
}
for (const model of ['gpt-6-astral', 'my-gpt-6-astra', 'gpt-4.1']) {
for (const model of ['gpt-6-astral', 'gpt-6-solar', 'my-gpt-6-astra', 'gpt-4.1']) {
assert.equal(canApplyTemperatureOverride(model), true, model)
}
})
4 changes: 3 additions & 1 deletion tests/unit/utils/model-name-convert.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ test('modelNameToDesc returns desc for a known model name without t function', (
assert.equal(desc, 'ChatGPT (Web)')
})

test('modelNameToDesc returns desc for GPT-5 stable presets', () => {
test('modelNameToDesc returns desc for stable GPT API presets', () => {
assert.equal(modelNameToDesc('chatgptApi5'), 'OpenAI (GPT-5)')
assert.equal(modelNameToDesc('chatgptApi5_1'), 'OpenAI (GPT-5.1)')
assert.equal(modelNameToDesc('chatgptApi5_2'), 'OpenAI (GPT-5.2)')
Expand All @@ -790,6 +790,8 @@ test('modelNameToDesc returns desc for GPT-5 stable presets', () => {
assert.equal(modelNameToDesc('chatgptApi5_6Sol'), 'OpenAI (GPT-5.6 Sol)')
assert.equal(modelNameToDesc('chatgptApi5_6Terra'), 'OpenAI (GPT-5.6 Terra)')
assert.equal(modelNameToDesc('chatgptApi5_6Luna'), 'OpenAI (GPT-5.6 Luna)')
assert.equal(modelNameToDesc('chatgptApi6Sol'), 'OpenAI (GPT-6 Sol)')
assert.equal(modelNameToDesc('chatgptApi6Luna'), 'OpenAI (GPT-6 Luna)')
})

test('modelNameToDesc appends extraCustomModelName for customModel', () => {
Expand Down