feat: add new provider aionly (#10179)

* feat: add new provider aionly

* fix(store): update migration to properly add 'aionly' provider in v156

Move 'aionly' provider addition from v155 to v156 migration to ensure proper state initialization

---------

Co-authored-by: fengjunhao <765838796@qq.com>
Co-authored-by: Phantom <59059173+EurFelux@users.noreply.github.com>
Co-authored-by: icarus <eurfelux@gmail.com>
Co-authored-by: 亢奋猫 <kangfenmao@qq.com>
This commit is contained in:
jo1yne06 2025-09-23 19:49:24 +08:00 committed by GitHub
parent 25c5d671dc
commit a847b74c32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 112 additions and 6 deletions

View File

@ -275,7 +275,8 @@ export class WindowService {
'https://aihubmix.com/topup',
'https://aihubmix.com/statistics',
'https://dash.302.ai/sso/login',
'https://dash.302.ai/charge'
'https://dash.302.ai/charge',
'https://www.aiionly.com/login'
]
if (oauthProviderUrls.some((link) => url.startsWith(link))) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -3,6 +3,7 @@ import { Provider } from '@renderer/types'
import {
oauthWith302AI,
oauthWithAihubmix,
oauthWithAiOnly,
oauthWithPPIO,
oauthWithSiliconFlow,
oauthWithTokenFlux
@ -46,6 +47,10 @@ const OAuthButton: FC<Props> = ({ provider, onSuccess, ...buttonProps }) => {
if (provider.id === '302ai') {
oauthWith302AI(handleSuccess)
}
if (provider.id === 'aionly') {
oauthWithAiOnly(handleSuccess)
}
}
return (

View File

@ -1785,5 +1785,37 @@ export const SYSTEM_MODELS: Record<SystemProviderId | 'defaultModel', Model[]> =
provider: 'poe',
group: 'poe'
}
],
aionly: [
{
id: 'claude-opus-4.1',
name: 'claude-opus-4.1',
provider: 'aionly',
group: 'claude'
},
{
id: 'claude-sonnet4',
name: 'claude-sonnet4',
provider: 'aionly',
group: 'claude'
},
{
id: 'claude-3.5-sonnet-v2',
name: 'claude-3.5-sonnet-v2',
provider: 'aionly',
group: 'claude'
},
{
id: 'gpt-4.1',
name: 'gpt-4.1',
provider: 'aionly',
group: 'gpt'
},
{
id: 'gemini-2.5-flash',
name: 'gemini-2.5-flash',
provider: 'aionly',
group: 'gemini'
}
]
}

View File

@ -3,6 +3,7 @@ import HunyuanProviderLogo from '@renderer/assets/images/models/hunyuan.png'
import AzureProviderLogo from '@renderer/assets/images/models/microsoft.png'
import Ai302ProviderLogo from '@renderer/assets/images/providers/302ai.webp'
import AiHubMixProviderLogo from '@renderer/assets/images/providers/aihubmix.webp'
import AiOnlyProviderLogo from '@renderer/assets/images/providers/aiOnly.png'
import AlayaNewProviderLogo from '@renderer/assets/images/providers/alayanew.webp'
import AnthropicProviderLogo from '@renderer/assets/images/providers/anthropic.png'
import AwsProviderLogo from '@renderer/assets/images/providers/aws-bedrock.webp'
@ -600,6 +601,16 @@ export const SYSTEM_PROVIDERS_CONFIG: Record<SystemProviderId, SystemProvider> =
models: SYSTEM_MODELS['poe'],
isSystem: true,
enabled: false
},
aionly: {
id: 'aionly',
name: 'AIOnly',
type: 'openai',
apiKey: '',
apiHost: 'https://api.aiionly.com',
models: SYSTEM_MODELS.aionly,
isSystem: true,
enabled: false
}
} as const
@ -661,7 +672,8 @@ export const PROVIDER_LOGO_MAP: AtLeast<SystemProviderId, string> = {
vertexai: VertexAIProviderLogo,
'new-api': NewAPIProviderLogo,
'aws-bedrock': AwsProviderLogo,
poe: 'poe' // use svg icon component
poe: 'poe', // use svg icon component
aionly: AiOnlyProviderLogo
} as const
export function getProviderLogo(providerId: string) {
@ -1255,6 +1267,17 @@ export const PROVIDER_URLS: Record<SystemProviderId, ProviderUrls> = {
docs: 'https://creator.poe.com/docs/external-applications/openai-compatible-api',
models: 'https://poe.com/'
}
},
aionly: {
api: {
url: 'https://api.aiionly.com'
},
websites: {
official: 'https://www.aiionly.com',
apiKey: 'https://www.aiionly.com/keyApi',
docs: 'https://www.aiionly.com/document',
models: 'https://www.aiionly.com'
}
}
}

View File

@ -80,7 +80,8 @@ const providerKeyMap = {
yi: 'provider.yi',
zhinao: 'provider.zhinao',
zhipu: 'provider.zhipu',
poe: 'provider.poe'
poe: 'provider.poe',
aionly: 'provider.aionly'
} as const
/**

View File

@ -2018,6 +2018,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "AiOnly",
"alayanew": "Alaya NeW",
"anthropic": "Anthropic",
"aws-bedrock": "AWS Bedrock",

View File

@ -2018,6 +2018,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "唯一AI(AiOnly)",
"alayanew": "Alaya NeW",
"anthropic": "Anthropic",
"aws-bedrock": "AWS Bedrock",

View File

@ -2018,6 +2018,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "唯一AI(AiOnly)",
"alayanew": "Alaya NeW",
"anthropic": "Anthropic",
"aws-bedrock": "AWS Bedrock",

View File

@ -2017,6 +2017,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "AiOnly",
"alayanew": "Alaya NeW",
"anthropic": "Anthropic",
"aws-bedrock": "AWS Bedrock",

View File

@ -2017,6 +2017,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "AiOnly",
"alayanew": "Alaya NeW",
"anthropic": "Antropológico",
"aws-bedrock": "AWS Bedrock",

View File

@ -2017,6 +2017,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "AiOnly",
"alayanew": "Alaya NeW",
"anthropic": "Anthropic",
"aws-bedrock": "AWS Bedrock",

View File

@ -2017,6 +2017,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "AiOnly",
"alayanew": "Alaya NeW",
"anthropic": "Anthropic",
"aws-bedrock": "AWS Bedrock",

View File

@ -2017,6 +2017,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "AiOnly",
"alayanew": "Alaya NeW",
"anthropic": "Antropológico",
"aws-bedrock": "AWS Bedrock",

View File

@ -2017,6 +2017,7 @@
"provider": {
"302ai": "302.AI",
"aihubmix": "AiHubMix",
"aionly": "AiOnly",
"alayanew": "Alaya NeW",
"anthropic": "Anthropic",
"aws-bedrock": "AWS Bedrock",

View File

@ -1,5 +1,6 @@
import AI302ProviderLogo from '@renderer/assets/images/providers/302ai.webp'
import AiHubMixProviderLogo from '@renderer/assets/images/providers/aihubmix.webp'
import AiOnlyProviderLogo from '@renderer/assets/images/providers/aiOnly.png'
import PPIOProviderLogo from '@renderer/assets/images/providers/ppio.png'
import SiliconFlowProviderLogo from '@renderer/assets/images/providers/silicon.png'
import TokenFluxProviderLogo from '@renderer/assets/images/providers/tokenflux.png'
@ -25,7 +26,8 @@ const PROVIDER_LOGO_MAP = {
silicon: SiliconFlowProviderLogo,
aihubmix: AiHubMixProviderLogo,
ppio: PPIOProviderLogo,
tokenflux: TokenFluxProviderLogo
tokenflux: TokenFluxProviderLogo,
aionly: AiOnlyProviderLogo
}
const ProviderOAuth: FC<Props> = ({ providerId }) => {

View File

@ -33,7 +33,7 @@ export function getProviderByModel(model?: Model) {
}
export function isProviderSupportAuth(provider: Provider) {
const supportProviders = ['302ai', 'silicon', 'aihubmix', 'ppio', 'tokenflux']
const supportProviders = ['302ai', 'silicon', 'aihubmix', 'ppio', 'tokenflux', 'aionly']
return supportProviders.includes(provider.id)
}

View File

@ -2479,6 +2479,7 @@ const migrateConfig = {
},
'156': (state: RootState) => {
try {
addProvider(state, 'aionly')
state.llm.providers.forEach((provider) => {
if (provider.id === SystemProviderIds.anthropic) {
if (provider.apiHost.endsWith('/')) {

View File

@ -321,7 +321,8 @@ export const SystemProviderIds = {
gpustack: 'gpustack',
voyageai: 'voyageai',
'aws-bedrock': 'aws-bedrock',
poe: 'poe'
poe: 'poe',
aionly: 'aionly'
} as const
export type SystemProviderId = keyof typeof SystemProviderIds

View File

@ -172,6 +172,27 @@ export const oauthWith302AI = async (setKey) => {
window.addEventListener('message', messageHandler)
}
export const oauthWithAiOnly = async (setKey) => {
const authUrl = `https://www.aiionly.com/login?inviteCode=1755481173663DrZBBOC0&cherryCode=01`
const popup = window.open(
authUrl,
'login',
'width=720,height=720,toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,alwaysOnTop=yes,alwaysRaised=yes'
)
const messageHandler = (event) => {
if (event.data.length > 0 && event.data[0]['secretKey'] !== undefined) {
setKey(event.data[0]['secretKey'])
popup?.close()
window.removeEventListener('message', messageHandler)
}
}
window.removeEventListener('message', messageHandler)
window.addEventListener('message', messageHandler)
}
export const providerCharge = async (provider: string) => {
const chargeUrlMap = {
silicon: {
@ -198,6 +219,11 @@ export const providerCharge = async (provider: string) => {
url: 'https://dash.302.ai/charge',
width: 900,
height: 700
},
aionly: {
url: `https://www.aiionly.com/recharge`,
width: 900,
height: 700
}
}
@ -236,6 +262,11 @@ export const providerBills = async (provider: string) => {
url: 'https://dash.302.ai/charge',
width: 900,
height: 700
},
aionly: {
url: `https://www.aiionly.com/billManagement`,
width: 900,
height: 700
}
}