diff --git a/frontend/src/api/models.ts b/frontend/src/api/models.ts new file mode 100644 index 00000000000..971c1bd883f --- /dev/null +++ b/frontend/src/api/models.ts @@ -0,0 +1,38 @@ +/** + * Models API endpoints + * Handles fetching available models for the user + */ + +import { apiClient } from './client' + +export interface Model { + id: string + type: string + display_name: string + created_at: string +} + +export interface ModelsResponse { + object: string + data: Model[] +} + +/** + * Get available models using an API key + * @param apiKey - The API key to use for authentication + * @returns List of available models + */ +export async function getAvailableModels(apiKey: string): Promise { + const { data } = await apiClient.get('/v1/models', { + headers: { + 'x-api-key': apiKey + } + }) + return data +} + +export const modelsAPI = { + getAvailableModels +} + +export default modelsAPI diff --git a/frontend/src/components/layout/AppSidebar.vue b/frontend/src/components/layout/AppSidebar.vue index 92dcc519015..7efe05263e8 100644 --- a/frontend/src/components/layout/AppSidebar.vue +++ b/frontend/src/components/layout/AppSidebar.vue @@ -264,6 +264,21 @@ const ChartIcon = { ) } +const CubeIcon = { + render: () => + h( + 'svg', + { fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor', 'stroke-width': '1.5' }, + [ + h('path', { + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round', + d: 'M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9' + }) + ] + ) +} + const GiftIcon = { render: () => h( @@ -569,6 +584,7 @@ const userNavItems = computed((): NavItem[] => { const items: NavItem[] = [ { path: '/dashboard', label: t('nav.dashboard'), icon: DashboardIcon }, { path: '/keys', label: t('nav.apiKeys'), icon: KeyIcon }, + { path: '/models', label: t('nav.models'), icon: CubeIcon }, { path: '/usage', label: t('nav.usage'), icon: ChartIcon, hideInSimpleMode: true }, { path: '/subscriptions', label: t('nav.mySubscriptions'), icon: CreditCardIcon, hideInSimpleMode: true }, ...(appStore.cachedPublicSettings?.payment_enabled diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index 8213cb0fd97..2c10ad41656 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -335,6 +335,7 @@ export default { dashboard: 'Dashboard', announcements: 'Announcements', apiKeys: 'API Keys', + models: 'Models', usage: 'Usage', redeem: 'Redeem', profile: 'Profile', @@ -5625,4 +5626,28 @@ export default { }, }, + // Models + models: { + title: 'Available Models', + description: 'View the list of AI models you can use and usage instructions', + selectApiKey: 'Select API Key', + selectApiKeyHint: 'Select an API key to view available models', + selectApiKeyPlaceholder: 'Please select an API key', + noApiKeys: 'No API Keys', + noApiKeysDesc: 'You have not created any API keys yet. Please create one to view available models', + createApiKey: 'Create API Key', + usageGuide: 'Usage Guide', + apiEndpoint: 'API Endpoint', + yourApiKey: 'Your API Key', + exampleRequest: 'Example Request', + availableModels: 'Available Models', + modelCount: '{count} models available', + modelId: 'Model ID', + displayName: 'Display Name', + actions: 'Actions', + noModels: 'No Models Available', + noModelsDesc: 'No models are available for the selected API key', + loadFailed: 'Failed to load models', + }, + } diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts index 5f936965801..8998af1720b 100644 --- a/frontend/src/i18n/locales/zh.ts +++ b/frontend/src/i18n/locales/zh.ts @@ -335,6 +335,7 @@ export default { dashboard: '仪表盘', announcements: '公告', apiKeys: 'API 密钥', + models: '可用模型', usage: '使用记录', redeem: '兑换', profile: '个人资料', @@ -5812,4 +5813,28 @@ export default { }, }, + // Models + models: { + title: '可用模型', + description: '查看您可以使用的 AI 模型列表和使用说明', + selectApiKey: '选择 API 密钥', + selectApiKeyHint: '选择一个 API 密钥来查看可用的模型列表', + selectApiKeyPlaceholder: '请选择 API 密钥', + noApiKeys: '暂无 API 密钥', + noApiKeysDesc: '您还没有创建任何 API 密钥,请先创建一个密钥来查看可用模型', + createApiKey: '创建 API 密钥', + usageGuide: '使用指南', + apiEndpoint: 'API 端点', + yourApiKey: '您的 API 密钥', + exampleRequest: '请求示例', + availableModels: '可用模型', + modelCount: '共 {count} 个模型', + modelId: '模型 ID', + displayName: '显示名称', + actions: '操作', + noModels: '暂无可用模型', + noModelsDesc: '当前 API 密钥没有可用的模型', + loadFailed: '加载模型列表失败', + }, + } diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index ad6e71c448a..67178653cdb 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -174,6 +174,18 @@ const routes: RouteRecordRaw[] = [ descriptionKey: 'redeem.description' } }, + { + path: '/models', + name: 'Models', + component: () => import('@/views/user/ModelsView.vue'), + meta: { + requiresAuth: true, + requiresAdmin: false, + title: 'Available Models', + titleKey: 'models.title', + descriptionKey: 'models.description' + } + }, { path: '/profile', name: 'Profile', diff --git a/frontend/src/views/user/ModelsView.vue b/frontend/src/views/user/ModelsView.vue new file mode 100644 index 00000000000..b020b278048 --- /dev/null +++ b/frontend/src/views/user/ModelsView.vue @@ -0,0 +1,302 @@ + + +