From c9a2f3631e7c98889cef469e5f16fdb33f4732d1 Mon Sep 17 00:00:00 2001 From: DEV_DSW <562304744@qq.com> Date: Mon, 20 Apr 2026 14:44:27 +0800 Subject: [PATCH] refactor: remove models snapshot feature and related code - Remove models snapshot UI section from Models page - Delete models API route handler and related logic - Remove models store implementation and exports - Clean up internationalization messages for removed feature - Update main entry point exports to exclude models store --- dist-electron/main/main.js | 2 +- electron/api/router.ts | 2 - electron/api/routes/models.ts | 92 ----------- src/pages/Models/components/ModelsSection.tsx | 86 ---------- src/pages/Models/index.tsx | 2 - src/pages/Models/messages.ts | 30 ---- src/stores/index.ts | 1 - src/stores/models.ts | 147 ------------------ 8 files changed, 1 insertion(+), 361 deletions(-) delete mode 100644 electron/api/routes/models.ts delete mode 100644 src/pages/Models/components/ModelsSection.tsx delete mode 100644 src/stores/models.ts diff --git a/dist-electron/main/main.js b/dist-electron/main/main.js index 7ce1092..29d57f0 100644 --- a/dist-electron/main/main.js +++ b/dist-electron/main/main.js @@ -1,6 +1,6 @@ "use strict"; require("electron"); -require("./main-XRVcGPgv.js"); +require("./main-Bc3HYL6W.js"); require("electron-squirrel-startup"); require("electron-log"); require("bytenode"); diff --git a/electron/api/router.ts b/electron/api/router.ts index 639b3a1..bc5556a 100644 --- a/electron/api/router.ts +++ b/electron/api/router.ts @@ -11,7 +11,6 @@ import { handleCronRoutes } from './routes/cron'; import { handleFileRoutes } from './routes/files'; import { handleGatewayRoutes } from './routes/gateway'; import { handleKnowledgeRoutes } from './routes/knowledge'; -import { handleModelRoutes } from './routes/models'; import { handleProviderRoutes } from './routes/providers'; import { handleSessionRoutes } from './routes/sessions'; import { handleSkillRoutes } from './routes/skills'; @@ -25,7 +24,6 @@ const routeHandlers: RouteHandler[] = [ handleProviderRoutes, handleChannelRoutes, handleAgentRoutes, - handleModelRoutes, handleCronRoutes, handleGatewayRoutes, handleKnowledgeRoutes, diff --git a/electron/api/routes/models.ts b/electron/api/routes/models.ts deleted file mode 100644 index 4134a97..0000000 --- a/electron/api/routes/models.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { ProviderAccount } from '@runtime/lib/providers'; -import { - DEFAULT_AGENT_ID, - DEFAULT_MAIN_SESSION_SUFFIX, - buildMainSessionKey, - normalizeAgentId, - type AgentSummary, -} from '@runtime/lib/models'; -import type { HostApiContext } from '../context'; -import type { NormalizedHostApiRequest } from '../route-utils'; -import { ok } from '../route-utils'; - -function formatModelDisplay(modelRef: string | null | undefined, fallbackLabel: string): string { - const trimmed = String(modelRef ?? '').trim(); - if (!trimmed) return fallbackLabel; - - const parts = trimmed.split('/'); - return parts[parts.length - 1] || trimmed; -} - -function buildMainModel(defaultAccount: ProviderAccount | null): AgentSummary { - return { - id: DEFAULT_AGENT_ID, - name: 'Main Model', - isDefault: true, - providerAccountId: defaultAccount?.id ?? null, - modelRef: defaultAccount?.model ?? null, - modelDisplay: formatModelDisplay(defaultAccount?.model, defaultAccount?.label || 'Unassigned'), - mainSessionKey: buildMainSessionKey(DEFAULT_AGENT_ID, DEFAULT_MAIN_SESSION_SUFFIX), - vendorId: defaultAccount?.vendorId ?? null, - source: 'synthetic-main', - }; -} - -function buildProviderBackedModels(accounts: ProviderAccount[]): AgentSummary[] { - const seen = new Set(); - const summaries: AgentSummary[] = []; - - for (const account of accounts) { - const agentId = normalizeAgentId(account.id); - if (seen.has(agentId) || agentId === DEFAULT_AGENT_ID) continue; - seen.add(agentId); - - summaries.push({ - id: agentId, - name: account.label || agentId, - isDefault: false, - providerAccountId: account.id, - modelRef: account.model ?? null, - modelDisplay: formatModelDisplay(account.model, account.label || agentId), - mainSessionKey: buildMainSessionKey(agentId, DEFAULT_MAIN_SESSION_SUFFIX), - vendorId: account.vendorId, - source: 'provider-account', - }); - } - - return summaries; -} - -export async function handleModelRoutes( - request: NormalizedHostApiRequest, - ctx: HostApiContext, -) { - const { pathname, method } = request; - if (pathname !== '/api/models' || method !== 'GET') { - return null; - } - - const accounts = ctx.providerApiService - .getAccounts() - .filter((account) => account.enabled !== false); - const defaultAccountId = ctx.providerApiService.getDefault().accountId; - const defaultAccount = accounts.find((account) => account.id === defaultAccountId) ?? accounts[0] ?? null; - - const models = [ - buildMainModel(defaultAccount), - ...buildProviderBackedModels(accounts), - ]; - - return ok({ - success: true, - models, - agents: models, - defaultAgentId: DEFAULT_AGENT_ID, - defaultProviderAccountId: defaultAccount?.id ?? null, - defaultModelRef: defaultAccount?.model ?? null, - mainSessionSuffix: DEFAULT_MAIN_SESSION_SUFFIX, - configuredChannelTypes: [], - channelOwners: {}, - channelAccountOwners: {}, - }); -} diff --git a/src/pages/Models/components/ModelsSection.tsx b/src/pages/Models/components/ModelsSection.tsx deleted file mode 100644 index ee9c063..0000000 --- a/src/pages/Models/components/ModelsSection.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useEffect } from 'react'; -import { modelsStore, useModelsStore } from '../../../stores'; -import { useModelsCopy } from '../copy'; - -const CHIP_CLASS_NAME = [ - 'rounded-full border px-2.5 py-1 text-[11px] leading-none', - 'border-[#E5E8EE] text-[#525866] dark:border-[#2a2a2d] dark:text-gray-300', -].join(' '); - -export default function ModelsSection() { - const modelsState = useModelsStore(); - const t = useModelsCopy(); - - useEffect(() => { - void modelsStore.init(); - }, []); - - return ( -
-
-
-

- {t('models.snapshot.title')} -

-

- {t('models.snapshot.subtitle')} -

-
- -
- - {modelsState.error ? ( -
- {modelsState.error} -
- ) : null} - -
- {modelsState.models.map((model) => ( -
-
-
-
- {model.name} -
-
{model.id}
-
- {model.isDefault ? ( - - {t('models.snapshot.defaultBadge')} - - ) : null} -
- -
- {t('models.snapshot.provider')}: {model.providerAccountId || '--'} - {t('models.snapshot.model')}: {model.modelDisplay || '--'} -
- -
-
{t('models.snapshot.mainSessionKey')}
-
{model.mainSessionKey}
-
-
- ))} - - {!modelsState.loading && modelsState.models.length === 0 ? ( -
- {t('models.snapshot.empty')} -
- ) : null} -
-
- ); -} diff --git a/src/pages/Models/index.tsx b/src/pages/Models/index.tsx index f8afe01..fb93024 100644 --- a/src/pages/Models/index.tsx +++ b/src/pages/Models/index.tsx @@ -1,4 +1,3 @@ -import ModelsSection from './components/ModelsSection'; import ProvidersSection from './components/ProvidersSection'; import UsageHistorySection from './components/UsageHistorySection'; import { useModelsCopy } from './copy'; @@ -21,7 +20,6 @@ export default function ModelsPage() {
-
diff --git a/src/pages/Models/messages.ts b/src/pages/Models/messages.ts index c8b4126..9d00b60 100644 --- a/src/pages/Models/messages.ts +++ b/src/pages/Models/messages.ts @@ -18,16 +18,6 @@ const EN_MODELS_MESSAGES: MessageTree = { loading: 'Loading...', ai: 'AI', }, - snapshot: { - title: 'Models Snapshot', - subtitle: 'Local `/api/models` snapshot and `mainSessionKey` mapping.', - refresh: 'Refresh Models', - defaultBadge: 'Default', - provider: 'Provider', - model: 'Model', - mainSessionKey: 'mainSessionKey', - empty: 'No models are available yet. Configure a provider account below and routable model snapshots will appear here automatically.', - }, providers: { title: 'AI Providers', subtitle: 'Manage your AI models and API keys.', @@ -128,16 +118,6 @@ const ZH_MODELS_MESSAGES: MessageTree = { loading: '加载中...', ai: 'AI', }, - snapshot: { - title: '模型快照', - subtitle: '本地 `/api/models` 快照与 `mainSessionKey` 映射。', - refresh: '刷新模型', - defaultBadge: '默认', - provider: '服务商', - model: '模型', - mainSessionKey: '主会话 Key', - empty: '当前还没有可用模型。先在下方配置服务商账号后,这里会自动生成可路由的模型快照。', - }, providers: { title: 'AI 服务商', subtitle: '管理你的 AI 模型与 API Key。', @@ -238,16 +218,6 @@ const JA_MODELS_MESSAGES: MessageTree = { loading: '読み込み中...', ai: 'AI', }, - snapshot: { - title: 'モデルスナップショット', - subtitle: 'ローカル `/api/models` スナップショットと `mainSessionKey` の対応です。', - refresh: 'モデルを更新', - defaultBadge: 'デフォルト', - provider: 'プロバイダー', - model: 'モデル', - mainSessionKey: 'メインセッションキー', - empty: '利用可能なモデルがまだありません。下でプロバイダーアカウントを設定すると、ルーティング可能なモデルスナップショットが自動生成されます。', - }, providers: { title: 'AI プロバイダー', subtitle: 'AI モデルと API キーを管理します。', diff --git a/src/stores/index.ts b/src/stores/index.ts index 890e975..32c1731 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -1,5 +1,4 @@ export * from './settings'; -export * from './models'; export * from './agents'; export * from './chat'; export * from './task'; diff --git a/src/stores/models.ts b/src/stores/models.ts deleted file mode 100644 index 297b1a1..0000000 --- a/src/stores/models.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { useSyncExternalStore } from 'react'; -import { - DEFAULT_AGENT_ID, - DEFAULT_MAIN_SESSION_SUFFIX, - buildMainSessionKey, - normalizeAgentId, - type AgentSummary, - type ModelsSnapshot, -} from '@runtime/lib/models'; -import { hostApiFetch } from '../lib/host-api'; - -export interface ModelsStoreState { - initialized: boolean; - loading: boolean; - error: string | null; - models: AgentSummary[]; - defaultAgentId: string; - defaultProviderAccountId: string | null; - defaultModelRef: string | null; - mainSessionSuffix: string; -} - -const listeners = new Set<() => void>(); - -let loadModelsInFlight: Promise | null = null; -let state: ModelsStoreState = { - initialized: false, - loading: false, - error: null, - models: [], - defaultAgentId: DEFAULT_AGENT_ID, - defaultProviderAccountId: null, - defaultModelRef: null, - mainSessionSuffix: DEFAULT_MAIN_SESSION_SUFFIX, -}; - -function emit(): void { - for (const listener of listeners) { - listener(); - } -} - -function patchState(patch: Partial): ModelsStoreState { - state = { ...state, ...patch }; - emit(); - return state; -} - -function sanitizeModel(model: AgentSummary): AgentSummary { - const normalizedId = normalizeAgentId(model.id); - const normalizedMainSessionKey = model.mainSessionKey || buildMainSessionKey(normalizedId); - - return { - id: normalizedId, - name: model.name || normalizedId, - isDefault: Boolean(model.isDefault), - providerAccountId: model.providerAccountId ?? null, - modelRef: model.modelRef ?? null, - modelDisplay: model.modelDisplay || model.modelRef || model.name || normalizedId, - mainSessionKey: normalizedMainSessionKey, - vendorId: model.vendorId ?? null, - source: model.source, - }; -} - -async function loadModels(): Promise { - if (loadModelsInFlight) { - await loadModelsInFlight; - return; - } - - loadModelsInFlight = (async () => { - patchState({ loading: true, error: null }); - - try { - const snapshot = await hostApiFetch('/api/models'); - const models = Array.isArray(snapshot?.models) - ? snapshot.models.map((model) => sanitizeModel(model)) - : Array.isArray(snapshot?.agents) - ? snapshot.agents.map((model) => sanitizeModel(model)) - : []; - - patchState({ - initialized: true, - loading: false, - error: null, - models, - defaultAgentId: snapshot?.defaultAgentId ? normalizeAgentId(snapshot.defaultAgentId) : DEFAULT_AGENT_ID, - defaultProviderAccountId: snapshot?.defaultProviderAccountId ?? null, - defaultModelRef: snapshot?.defaultModelRef ?? null, - mainSessionSuffix: snapshot?.mainSessionSuffix || DEFAULT_MAIN_SESSION_SUFFIX, - }); - } catch (error) { - patchState({ - initialized: true, - loading: false, - error: error instanceof Error ? error.message : String(error), - }); - } - })(); - - try { - await loadModelsInFlight; - } finally { - loadModelsInFlight = null; - } -} - -function subscribe(listener: () => void): () => void { - listeners.add(listener); - return () => listeners.delete(listener); -} - -function getSnapshot(): ModelsStoreState { - return state; -} - -function getModelById(modelId: string | null | undefined): AgentSummary | undefined { - const normalizedId = normalizeAgentId(modelId); - return state.models.find((model) => model.id === normalizedId); -} - -function resolveMainSessionKey(agentId: string | null | undefined): string { - const normalizedId = normalizeAgentId(agentId || state.defaultAgentId); - return getModelById(normalizedId)?.mainSessionKey || buildMainSessionKey(normalizedId, state.mainSessionSuffix); -} - -function resolveProviderAccountId(agentId: string | null | undefined): string | null { - const normalizedId = normalizeAgentId(agentId || state.defaultAgentId); - return getModelById(normalizedId)?.providerAccountId ?? state.defaultProviderAccountId; -} - -export const modelsStore = { - subscribe, - getSnapshot, - getState: () => state, - init: loadModels, - load: loadModels, - getModelById, - resolveMainSessionKey, - resolveProviderAccountId, -}; - -export function useModelsStore(selector?: (state: ModelsStoreState) => T): T { - const select = selector ?? ((current: ModelsStoreState) => current as unknown as T); - return useSyncExternalStore(subscribe, () => select(getSnapshot()), () => select(getSnapshot())); -}