返回 oh-my-ppt
model-config.ts
根目录 / src / main / image-generation / model-config.ts
1 import type { ImageModelProvider } from '@shared/image-generation'
2 import type { ResolvedImageModelConfig } from '../agent-runtime/provider/image'
3 import type { PPTDatabase } from '../db/database'
4 import type { IpcContext } from '../ipc/context'
5
6 type ImageModelConfigContext = Pick<IpcContext, 'decryptApiKey'> & {
7 db: Pick<PPTDatabase, 'getImageModelConfig'>
8 }
9
10 type ActiveImageModelConfigContext = ImageModelConfigContext & {
11 db: Pick<PPTDatabase, 'getImageModelConfig' | 'getActiveImageModelConfig'>
12 }
13
14 export const IMAGE_MODEL_PROVIDERS = [
15 'jimeng',
16 'jimeng4',
17 'agnes',
18 'siliconflow',
19 'openaiCompatible',
20 'gemini',
21 'seedream'
22 ] as const
23
24 export const resolveImageModelProvider = (provider: unknown): ImageModelProvider => {
25 if (IMAGE_MODEL_PROVIDERS.includes(provider as ImageModelProvider)) {
26 return provider as ImageModelProvider
27 }
28 throw new Error('Unsupported image provider')
29 }
30
31 export const parseImageModelConfig = (value: unknown): Record<string, unknown> | null => {
32 const text = typeof value === 'string' ? value.trim() : ''
33 if (!text) return null
34 try {
35 const parsed = JSON.parse(text)
36 if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null
37 return Object.keys(parsed).length > 0 ? (parsed as Record<string, unknown>) : null
38 } catch {
39 return null
40 }
41 }
42
43 export const getImageModelConfigString = (config: ResolvedImageModelConfig, key: string): string => {
44 const value = config.modelConfig[key]
45 return typeof value === 'string' ? value.trim() : ''
46 }
47
48 export const getImageModelDisplayName = (config: ResolvedImageModelConfig): string =>
49 getImageModelConfigString(config, 'model') ||
50 getImageModelConfigString(config, 'reqKey') ||
51 config.provider
52
53 const resolveRawImageModelConfig = (
54 ctx: Pick<IpcContext, 'decryptApiKey'>,
55 raw: {
56 id: string
57 name: string
58 provider: string
59 active: number
60 modelConfig: string
61 }
62 ): ResolvedImageModelConfig => {
63 const modelConfig = parseImageModelConfig(ctx.decryptApiKey(raw.modelConfig || '{}'))
64 if (!modelConfig) throw new Error('Image model config is empty or invalid')
65 return {
66 id: raw.id,
67 name: raw.name,
68 provider: resolveImageModelProvider(raw.provider),
69 active: raw.active === 1,
70 modelConfig
71 }
72 }
73
74 export const resolveConfiguredImageModel = async (
75 ctx: ImageModelConfigContext,
76 modelConfigId: string
77 ): Promise<ResolvedImageModelConfig> => {
78 const id = modelConfigId.trim()
79 if (!id) throw new Error('Image model config ID is required')
80 const raw = await ctx.db.getImageModelConfig(id)
81 if (!raw) throw new Error('Image model config does not exist')
82 return resolveRawImageModelConfig(ctx, raw)
83 }
84
85 export const resolveActiveOrSelectedImageModel = async (
86 ctx: ActiveImageModelConfigContext,
87 modelConfigId?: string
88 ): Promise<ResolvedImageModelConfig> => {
89 const id = modelConfigId?.trim()
90 if (id) return resolveConfiguredImageModel(ctx, id)
91 const active = await ctx.db.getActiveImageModelConfig()
92 if (!active) throw new Error('请先在设置中配置并启用生图模型。')
93 return resolveRawImageModelConfig(ctx, active)
94 }
95
95 lines TYPESCRIPT