refactor(types): consolidate OpenAI types and improve type safety

- Move OpenAI-related types to aiCoreTypes.ts
- Rename FetchChatCompletionOptions to FetchChatCompletionRequestOptions
- Add proper type definitions for service tiers and verbosity
- Improve type guards for service tier checks
This commit is contained in:
icarus 2025-10-26 01:19:16 +08:00
parent e69fd7f22b
commit a7cb663421
3 changed files with 105 additions and 26 deletions

View File

@ -1,3 +1,4 @@
import type OpenAI from '@cherrystudio/openai'
import type { ImageModel, LanguageModel } from 'ai'
import { generateObject, generateText, ModelMessage, streamObject, streamText } from 'ai'
@ -27,3 +28,7 @@ export type StreamObjectParams = Omit<Parameters<typeof streamObject>[0], 'model
export type GenerateObjectParams = Omit<Parameters<typeof generateObject>[0], 'model'>
export type AiSdkModel = LanguageModel | ImageModel
export type OpenAIVerbosity = OpenAI.Responses.ResponseTextConfig['verbosity']
export type OpenAIReasoningEffort = OpenAI.ReasoningEffort
export type OpenAISummaryText = OpenAI.Reasoning['summary'] | 'off'

View File

@ -857,10 +857,6 @@ export interface StoreSyncAction {
}
}
export type OpenAIVerbosity = 'high' | 'medium' | 'low'
export type OpenAISummaryText = 'auto' | 'concise' | 'detailed' | 'off'
export type S3Config = {
endpoint: string
region: string
@ -1077,7 +1073,7 @@ export const isHexColor = (value: string): value is HexColor => {
return /^#([0-9A-F]{3}){1,2}$/i.test(value)
}
export type FetchChatCompletionOptions = {
export type FetchChatCompletionRequestOptions = {
signal?: AbortSignal
timeout?: number
headers?: Record<string, string>
@ -1085,7 +1081,7 @@ export type FetchChatCompletionOptions = {
type BaseParams = {
assistant: Assistant
options?: FetchChatCompletionOptions
requestOptions?: FetchChatCompletionRequestOptions
onChunkReceived: (chunk: Chunk) => void
topicId?: string // 添加 topicId 参数
uiMessages?: Message[]

View File

@ -1,6 +1,9 @@
import OpenAI from '@cherrystudio/openai'
import { Model } from '@types'
import * as z from 'zod'
import { OpenAIVerbosity } from './aiCoreTypes'
export const ProviderTypeSchema = z.enum([
'openai',
'openai-response',
@ -39,36 +42,36 @@ export type ProviderApiOptions = {
isNotSupportEnableThinking?: boolean
}
// scale is not well supported now. It event lacks of docs
export type OpenAIServiceTier = Exclude<OpenAI.Responses.ResponseCreateParams['service_tier'], 'scale'>
export const OpenAIServiceTiers = {
auto: 'auto',
default: 'default',
flex: 'flex',
priority: 'priority'
} as const
} as const satisfies Record<string, OpenAIServiceTier>
export type OpenAIServiceTier = keyof typeof OpenAIServiceTiers
export function isOpenAIServiceTier(tier: string): tier is OpenAIServiceTier {
return Object.hasOwn(OpenAIServiceTiers, tier)
export function isOpenAIServiceTier(tier: string | null | undefined): tier is OpenAIServiceTier {
return tier === null || tier === undefined || Object.hasOwn(OpenAIServiceTiers, tier)
}
// https://console.groq.com/docs/api-reference#responses
export type GroqServiceTier = 'auto' | 'on_demand' | 'flex' | undefined | null
export const GroqServiceTiers = {
auto: 'auto',
on_demand: 'on_demand',
flex: 'flex',
performance: 'performance'
} as const
flex: 'flex'
} as const satisfies Record<string, GroqServiceTier>
// 从 GroqServiceTiers 对象中提取类型
export type GroqServiceTier = keyof typeof GroqServiceTiers
export function isGroqServiceTier(tier: string): tier is GroqServiceTier {
return Object.hasOwn(GroqServiceTiers, tier)
export function isGroqServiceTier(tier: string | undefined | null): tier is GroqServiceTier {
return tier === null || tier === undefined || Object.hasOwn(GroqServiceTiers, tier)
}
export type ServiceTier = OpenAIServiceTier | GroqServiceTier
export function isServiceTier(tier: string): tier is ServiceTier {
export function isServiceTier(tier: string | null | undefined): tier is ServiceTier {
return isGroqServiceTier(tier) || isOpenAIServiceTier(tier)
}
@ -90,6 +93,7 @@ export type Provider = {
// API options
apiOptions?: ProviderApiOptions
serviceTier?: ServiceTier
verbosity?: OpenAIVerbosity
/** @deprecated */
isNotSupportArrayContent?: boolean
@ -106,6 +110,71 @@ export type Provider = {
extra_headers?: Record<string, string>
}
export const SystemProviderIdSchema = z.enum([
'cherryin',
'silicon',
'aihubmix',
'ocoolai',
'deepseek',
'ppio',
'alayanew',
'qiniu',
'dmxapi',
'burncloud',
'tokenflux',
'302ai',
'cephalon',
'lanyun',
'ph8',
'openrouter',
'ollama',
'ovms',
'new-api',
'lmstudio',
'anthropic',
'openai',
'azure-openai',
'gemini',
'vertexai',
'github',
'copilot',
'zhipu',
'yi',
'moonshot',
'baichuan',
'dashscope',
'stepfun',
'doubao',
'infini',
'minimax',
'groq',
'together',
'fireworks',
'nvidia',
'grok',
'hyperbolic',
'mistral',
'jina',
'perplexity',
'modelscope',
'xirang',
'hunyuan',
'tencent-cloud-ti',
'baidu-cloud',
'gpustack',
'voyageai',
'aws-bedrock',
'poe',
'aionly',
'longcat'
])
export type SystemProviderId = z.infer<typeof SystemProviderIdSchema>
export const isSystemProviderId = (id: string): id is SystemProviderId => {
return SystemProviderIdSchema.safeParse(id).success
}
export const SystemProviderIds = {
cherryin: 'cherryin',
silicon: 'silicon',
@ -163,13 +232,9 @@ export const SystemProviderIds = {
poe: 'poe',
aionly: 'aionly',
longcat: 'longcat'
} as const
} as const satisfies Record<SystemProviderId, SystemProviderId>
export type SystemProviderId = keyof typeof SystemProviderIds
export const isSystemProviderId = (id: string): id is SystemProviderId => {
return Object.hasOwn(SystemProviderIds, id)
}
export type SystemProviderIdTypeMap = typeof SystemProviderIds
export type SystemProvider = Provider & {
id: SystemProviderId
@ -194,3 +259,16 @@ export type VertexProvider = Provider & {
export const isSystemProvider = (provider: Provider): provider is SystemProvider => {
return isSystemProviderId(provider.id) && !!provider.isSystem
}
export type GroqSystemProvider = Provider & {
id: SystemProviderIdTypeMap['groq']
isSystem: true
}
export type NotGroqProvider = Provider & {
id: Exclude<string, SystemProviderIdTypeMap['groq']>
}
export const isGroqSystemProvider = (provider: Provider): provider is GroqSystemProvider => {
return provider.id === SystemProviderIds.groq
}