From e1150749372cb892885fb8c03310d0dacff5ec46 Mon Sep 17 00:00:00 2001 From: Will Chen Date: Mon, 12 May 2025 16:12:36 -0700 Subject: [PATCH] Fix DB schema (#135) --- ...mm.sql => 0005_superb_lady_mastermind.sql} | 5 +-- drizzle/meta/0005_snapshot.json | 15 +++++--- drizzle/meta/_journal.json | 4 +-- src/components/CreateCustomModelDialog.tsx | 25 +++++++------- src/components/settings/ModelsSection.tsx | 4 +-- src/db/schema.ts | 5 +-- src/ipc/handlers/language_model_handlers.ts | 27 +++++---------- src/ipc/ipc_types.ts | 34 ++++++++++++------- src/ipc/shared/language_model_helpers.ts | 6 ++-- 9 files changed, 67 insertions(+), 58 deletions(-) rename drizzle/{0005_hesitant_sister_grimm.sql => 0005_superb_lady_mastermind.sql} (85%) diff --git a/drizzle/0005_hesitant_sister_grimm.sql b/drizzle/0005_superb_lady_mastermind.sql similarity index 85% rename from drizzle/0005_hesitant_sister_grimm.sql rename to drizzle/0005_superb_lady_mastermind.sql index 057d38a..1d5dbd5 100644 --- a/drizzle/0005_hesitant_sister_grimm.sql +++ b/drizzle/0005_superb_lady_mastermind.sql @@ -8,8 +8,9 @@ CREATE TABLE `language_model_providers` ( ); --> statement-breakpoint CREATE TABLE `language_models` ( - `id` text PRIMARY KEY NOT NULL, - `name` text NOT NULL, + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `display_name` text NOT NULL, + `api_name` text NOT NULL, `provider_id` text NOT NULL, `description` text, `max_output_tokens` integer, diff --git a/drizzle/meta/0005_snapshot.json b/drizzle/meta/0005_snapshot.json index d24c56c..568b2aa 100644 --- a/drizzle/meta/0005_snapshot.json +++ b/drizzle/meta/0005_snapshot.json @@ -1,7 +1,7 @@ { "version": "6", "dialect": "sqlite", - "id": "f2ef6f83-09f5-4932-b7a0-4b205ba542ec", + "id": "424973e5-a102-4b71-8d5d-6160f1609b8c", "prevId": "ceedb797-6aa3-4a50-b42f-bc85ee08b3df", "tables": { "apps": { @@ -191,13 +191,20 @@ "columns": { "id": { "name": "id", - "type": "text", + "type": "integer", "primaryKey": true, "notNull": true, + "autoincrement": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true, "autoincrement": false }, - "name": { - "name": "name", + "api_name": { + "name": "api_name", "type": "text", "primaryKey": false, "notNull": true, diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index f470284..1d98390 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -40,8 +40,8 @@ { "idx": 5, "version": "6", - "when": 1747087890389, - "tag": "0005_hesitant_sister_grimm", + "when": 1747091036229, + "tag": "0005_superb_lady_mastermind", "breakpoints": true } ] diff --git a/src/components/CreateCustomModelDialog.tsx b/src/components/CreateCustomModelDialog.tsx index 2aa7332..e181f78 100644 --- a/src/components/CreateCustomModelDialog.tsx +++ b/src/components/CreateCustomModelDialog.tsx @@ -27,8 +27,8 @@ export function CreateCustomModelDialog({ onSuccess, providerId, }: CreateCustomModelDialogProps) { - const [id, setId] = useState(""); - const [name, setName] = useState(""); + const [apiName, setApiName] = useState(""); + const [displayName, setDisplayName] = useState(""); const [description, setDescription] = useState(""); const [maxOutputTokens, setMaxOutputTokens] = useState(""); const [contextWindow, setContextWindow] = useState(""); @@ -38,8 +38,8 @@ export function CreateCustomModelDialog({ const mutation = useMutation({ mutationFn: async () => { const params = { - id, - name, + apiName, + displayName, providerId, description: description || undefined, maxOutputTokens: maxOutputTokens @@ -48,8 +48,9 @@ export function CreateCustomModelDialog({ contextWindow: contextWindow ? parseInt(contextWindow, 10) : undefined, }; - if (!params.id) throw new Error("Model ID is required"); - if (!params.name) throw new Error("Model Name is required"); + if (!params.apiName) throw new Error("Model API name is required"); + if (!params.displayName) + throw new Error("Model display name is required"); if (maxOutputTokens && isNaN(params.maxOutputTokens ?? NaN)) throw new Error("Max Output Tokens must be a valid number"); if (contextWindow && isNaN(params.contextWindow ?? NaN)) @@ -69,8 +70,8 @@ export function CreateCustomModelDialog({ }); const resetForm = () => { - setId(""); - setName(""); + setApiName(""); + setDisplayName(""); setDescription(""); setMaxOutputTokens(""); setContextWindow(""); @@ -105,9 +106,9 @@ export function CreateCustomModelDialog({ ) => - setId(e.target.value) + setApiName(e.target.value) } className="col-span-3" placeholder="This must match the model expected by the API" @@ -121,9 +122,9 @@ export function CreateCustomModelDialog({ ) => - setName(e.target.value) + setDisplayName(e.target.value) } className="col-span-3" placeholder="Human-friendly name for the model" diff --git a/src/components/settings/ModelsSection.tsx b/src/components/settings/ModelsSection.tsx index e555f30..1bc43da 100644 --- a/src/components/settings/ModelsSection.tsx +++ b/src/components/settings/ModelsSection.tsx @@ -46,7 +46,7 @@ export function ModelsSection({ providerId }: ModelsSectionProps) {
{models.map((model) => (
@@ -56,7 +56,7 @@ export function ModelsSection({ providerId }: ModelsSectionProps) { {/* Optional: Add an edit/delete button here later */}

- {model.name} + {model.apiName}

{model.description && (

diff --git a/src/db/schema.ts b/src/db/schema.ts index 9e29fb4..ff9785c 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -82,8 +82,9 @@ export const language_model_providers = sqliteTable( ); export const language_models = sqliteTable("language_models", { - id: text("id").primaryKey(), - name: text("name").notNull(), + id: integer("id").primaryKey({ autoIncrement: true }), + displayName: text("display_name").notNull(), + apiName: text("api_name").notNull(), provider_id: text("provider_id") .notNull() .references(() => language_model_providers.id, { onDelete: "cascade" }), diff --git a/src/ipc/handlers/language_model_handlers.ts b/src/ipc/handlers/language_model_handlers.ts index 83b69d4..d81dee2 100644 --- a/src/ipc/handlers/language_model_handlers.ts +++ b/src/ipc/handlers/language_model_handlers.ts @@ -87,8 +87,8 @@ export function registerLanguageModelHandlers() { params: CreateCustomLanguageModelParams, ): Promise => { const { - id, - name, + apiName, + displayName, providerId, description, maxOutputTokens, @@ -96,11 +96,11 @@ export function registerLanguageModelHandlers() { } = params; // Validation - if (!id) { - throw new Error("Model ID is required"); + if (!apiName) { + throw new Error("Model API name is required"); } - if (!name) { - throw new Error("Model name is required"); + if (!displayName) { + throw new Error("Model display name is required"); } if (!providerId) { throw new Error("Provider ID is required"); @@ -117,21 +117,10 @@ export function registerLanguageModelHandlers() { throw new Error(`Provider with ID "${providerId}" not found`); } - // Check if model ID already exists - const existingModel = db - .select() - .from(languageModelsSchema) - .where(eq(languageModelsSchema.id, id)) - .get(); - - if (existingModel) { - throw new Error(`A model with ID "${id}" already exists`); - } - // Insert the new model await db.insert(languageModelsSchema).values({ - id, - name, + displayName, + apiName, provider_id: providerId, description: description || null, max_output_tokens: maxOutputTokens || null, diff --git a/src/ipc/ipc_types.ts b/src/ipc/ipc_types.ts index d7863c3..c7f5ef9 100644 --- a/src/ipc/ipc_types.ts +++ b/src/ipc/ipc_types.ts @@ -144,16 +144,26 @@ export interface LanguageModelProvider { type: "custom" | "local" | "cloud"; } -export interface LanguageModel { - id: string; - name: string; - displayName: string; - description: string; - tag?: string; - maxOutputTokens?: number; - contextWindow?: number; - type: "local" | "cloud" | "custom"; -} +export type LanguageModel = + | { + id: number; + apiName: string; + displayName: string; + description: string; + tag?: string; + maxOutputTokens?: number; + contextWindow?: number; + type: "custom"; + } + | { + apiName: string; + displayName: string; + description: string; + tag?: string; + maxOutputTokens?: number; + contextWindow?: number; + type: "local" | "cloud"; + }; export interface CreateCustomLanguageModelProviderParams { id: string; @@ -163,8 +173,8 @@ export interface CreateCustomLanguageModelProviderParams { } export interface CreateCustomLanguageModelParams { - id: string; - name: string; + apiName: string; + displayName: string; providerId: string; description?: string; maxOutputTokens?: number; diff --git a/src/ipc/shared/language_model_helpers.ts b/src/ipc/shared/language_model_helpers.ts index a9e78fe..f53b4fd 100644 --- a/src/ipc/shared/language_model_helpers.ts +++ b/src/ipc/shared/language_model_helpers.ts @@ -157,7 +157,7 @@ export async function getLanguageModels(obj: { const models = MODEL_OPTIONS[providerId as RegularModelProvider] || []; return models.map((model) => ({ ...model, - id: model.name, + apiName: model.name, type: "cloud", })); } else { @@ -174,7 +174,8 @@ export async function getLanguageModels(obj: { .select({ id: languageModelsSchema.id, // Map DB columns to LanguageModel fields - name: languageModelsSchema.name, + displayName: languageModelsSchema.displayName, + apiName: languageModelsSchema.apiName, // No display_name in DB, use name instead description: languageModelsSchema.description, // No tag in DB @@ -186,7 +187,6 @@ export async function getLanguageModels(obj: { return customModelsDb.map((model) => ({ ...model, - displayName: model.name, // Use name as displayName for custom models // Ensure possibly null fields are handled, provide defaults or undefined if needed description: model.description ?? "", tag: undefined, // No tag for custom models from DB