Merge pull request #6628 from baryon/contrib/openai-gpt6-astra-capability-sync

fix(openai): persist GPT-6 Astra Codex capabilities from upstream sync
This commit is contained in:
Wesley Liddick
2026-09-05 16:07:50 +08:00
committed by GitHub
16 changed files with 545 additions and 120 deletions
@@ -5061,8 +5061,11 @@ const submitCreateAccount = async (payload: CreateAccountRequest) => {
if (upstreamModelsPreviewed.value || hasConcreteMappedTarget) {
try {
const result = await adminAPI.accounts.syncUpstreamModels(account.id)
if (result.warnings?.some(warning => warning.code === 'upstream_model_metadata_incomplete')) {
const warnings = result.warnings ?? []
if (warnings.some(warning => warning.code === 'upstream_model_metadata_incomplete')) {
appStore.showWarning(t('admin.accounts.syncUpstreamModelsMetadataIncomplete'))
} else if (warnings.some(warning => warning.code === 'upstream_model_metadata_partial')) {
appStore.showWarning(t('admin.accounts.syncUpstreamModelsMetadataPartial'))
}
} catch {
appStore.showWarning(t('admin.accounts.syncUpstreamModelsFailed'))
@@ -4194,7 +4194,14 @@ const syncAntigravityUpstreamModels = async () => {
}
}
if (result.warnings?.some((warning) => warning.code === 'upstream_model_metadata_incomplete')) {
const warnings = result.warnings ?? []
const hasPartialMetadata = warnings.some(
(warning) => warning.code === 'upstream_model_metadata_partial'
)
const hasIncompleteMetadata = warnings.some(
(warning) => warning.code === 'upstream_model_metadata_incomplete'
)
if (hasIncompleteMetadata) {
appStore.showWarning(t('admin.accounts.syncUpstreamModelsMetadataIncomplete'))
return
}
@@ -4203,6 +4210,9 @@ const syncAntigravityUpstreamModels = async () => {
} else {
appStore.showInfo(t('admin.accounts.syncUpstreamModelsNoChanges', { count: upstreamModels.length }))
}
if (hasPartialMetadata) {
appStore.showWarning(t('admin.accounts.syncUpstreamModelsMetadataPartial'))
}
} catch (error) {
const message = error instanceof Error ? error.message : t('admin.accounts.syncUpstreamModelsFailed')
appStore.showError(t('admin.accounts.syncUpstreamModelsError', { message }))
@@ -327,7 +327,14 @@ const syncUpstreamModels = async () => {
}
emit('update:modelValue', newModels)
if (result.warnings?.some(warning => warning.code === 'upstream_model_metadata_incomplete')) {
const warnings = result.warnings ?? []
const hasPartialMetadata = warnings.some(
warning => warning.code === 'upstream_model_metadata_partial'
)
const hasIncompleteMetadata = warnings.some(
warning => warning.code === 'upstream_model_metadata_incomplete'
)
if (hasIncompleteMetadata) {
appStore.showWarning(t('admin.accounts.syncUpstreamModelsMetadataIncomplete'))
return
}
@@ -336,6 +343,9 @@ const syncUpstreamModels = async () => {
} else {
appStore.showInfo(t('admin.accounts.syncUpstreamModelsNoChanges', { count: upstreamModels.length }))
}
if (hasPartialMetadata) {
appStore.showWarning(t('admin.accounts.syncUpstreamModelsMetadataPartial'))
}
} catch (error) {
const message = error instanceof Error ? error.message : t('admin.accounts.syncUpstreamModelsFailed')
appStore.showError(t('admin.accounts.syncUpstreamModelsError', { message }))
@@ -153,6 +153,41 @@ describe('ModelWhitelistSelector', () => {
expect(showSuccess).not.toHaveBeenCalled()
})
it('shows success and a partial warning when some capabilities were saved', async () => {
syncUpstreamModels.mockResolvedValue({
models: ['gpt-6-astra', 'gpt-image-2'],
warnings: [
{
code: 'upstream_model_metadata_partial',
message: 'Some model capabilities were saved; remaining models are still incomplete.'
}
]
})
const wrapper = mount(ModelWhitelistSelector, {
props: {
modelValue: [],
platform: 'openai',
accountId: 46
},
global: {
stubs: {
ModelIcon: true
}
}
})
const syncButton = wrapper
.findAll('button')
.find(button => button.text() === 'admin.accounts.syncUpstreamModels')
expect(syncButton).toBeDefined()
await syncButton!.trigger('click')
await flushPromises()
expect(wrapper.emitted('update:modelValue')).toEqual([[['gpt-6-astra', 'gpt-image-2']]])
expect(showSuccess).toHaveBeenCalledWith('admin.accounts.syncUpstreamModelsSuccess')
expect(showWarning).toHaveBeenCalledWith('admin.accounts.syncUpstreamModelsMetadataPartial')
})
it('reports a successful preview so account creation can persist metadata', async () => {
syncUpstreamModelsPreview.mockResolvedValue({
models: ['x-preview-f-free'],
@@ -15,6 +15,7 @@ describe('useModelWhitelist', () => {
expect(models).toContain('gpt-5.4-2026-03-05')
expect(models).toContain('codex-auto-review')
expect(models).toContain('gpt-5.6')
expect(models).toContain('gpt-6-astra')
})
it('openai 模型列表不再暴露已下线的 ChatGPT 登录 Codex 模型', () => {
@@ -7,8 +7,10 @@ const openaiModels = [
// GPT-5.2 系列
'gpt-5.2', 'gpt-5.2-2025-12-11', 'gpt-5.2-chat-latest',
'gpt-5.2-pro', 'gpt-5.2-pro-2025-12-11',
// GPT-5.6 系列
// GPT-5.6 系列
'gpt-5.6', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna',
// GPT-6 系列
'gpt-6-astra',
// GPT-5.5 系列
'gpt-5.5',
// GPT-5.4 系列
@@ -294,6 +296,7 @@ const openaiPresetMappings = [
{ label: 'GPT-5.6 Sol', from: 'gpt-5.6-sol', to: 'gpt-5.6-sol', color: 'bg-orange-100 text-orange-700 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-400' },
{ label: 'GPT-5.6 Terra', from: 'gpt-5.6-terra', to: 'gpt-5.6-terra', color: 'bg-lime-100 text-lime-700 hover:bg-lime-200 dark:bg-lime-900/30 dark:text-lime-400' },
{ label: 'GPT-5.6 Luna', from: 'gpt-5.6-luna', to: 'gpt-5.6-luna', color: 'bg-sky-100 text-sky-700 hover:bg-sky-200 dark:bg-sky-900/30 dark:text-sky-400' },
{ label: 'GPT-6 Astra', from: 'gpt-6-astra', to: 'gpt-6-astra', color: 'bg-fuchsia-100 text-fuchsia-700 hover:bg-fuchsia-200 dark:bg-fuchsia-900/30 dark:text-fuchsia-400' },
{ label: 'GPT-5.5', from: 'gpt-5.5', to: 'gpt-5.5', color: 'bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400' },
{ label: 'GPT-5.4', from: 'gpt-5.4', to: 'gpt-5.4', color: 'bg-rose-100 text-rose-700 hover:bg-rose-200 dark:bg-rose-900/30 dark:text-rose-400' },
{ label: 'Haiku→5.4', from: 'claude-haiku-4-5-20251001', to: 'gpt-5.4', color: 'bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400' },
@@ -767,7 +767,9 @@ export default {
syncUpstreamModelsFailed: 'Failed to sync upstream models',
syncUpstreamModelsError: 'Failed to sync upstream models: {message}',
syncUpstreamModelsMetadataIncomplete:
'Model IDs were synced, but capability metadata is incomplete and was not updated.',
'Model IDs were synced, but no capability metadata could be updated.',
syncUpstreamModelsMetadataPartial:
'Some model capabilities were updated; remaining models are still incomplete.',
clearAllModels: 'Clear all models',
customModelName: 'Custom model name',
enterCustomModelName: 'Enter custom model name',
@@ -842,7 +842,8 @@ export default {
syncUpstreamModelsEmpty: '上游没有返回可同步的模型',
syncUpstreamModelsFailed: '同步上游模型失败',
syncUpstreamModelsError: '同步上游模型失败:{message}',
syncUpstreamModelsMetadataIncomplete: '模型 ID 已同步,但能力元数据不完整,能力信息未更新。',
syncUpstreamModelsMetadataIncomplete: '模型 ID 已同步,但未能更新任何能力元数据。',
syncUpstreamModelsMetadataPartial: '已更新部分模型的能力元数据;其余模型能力仍不完整。',
clearAllModels: '清除所有模型',
customModelName: '自定义模型名称',
enterCustomModelName: '输入自定义模型名称',