From aa50176fe74106d274c53e71ac6b75cd7a471fd4 Mon Sep 17 00:00:00 2001 From: Justyn Shull Date: Sun, 28 Jul 2024 05:00:45 -0500 Subject: [PATCH] Catch errors when SECRETS is empty or doesnt have the right key --- src/init.test.ts | 194 +++++++++++++++++++++++++++++++++++++---------- src/init.ts | 15 +++- 2 files changed, 167 insertions(+), 42 deletions(-) diff --git a/src/init.test.ts b/src/init.test.ts index bfdbc96..b9b3c74 100644 --- a/src/init.test.ts +++ b/src/init.test.ts @@ -24,6 +24,10 @@ ai: provider: gemini baseUrl: https://api.gemini.ai/v1 secretName: GOOGLE_AI_STUDIO_KEY + imageModels: + - name: dall-e + provider: dalle + modelName: dall-e embeddingModels: - name: text-embedding-3-small provider: openai @@ -45,45 +49,159 @@ OPENAI_API_KEY: bar `; Deno.test("initializeOpenAI should set aiSettings correctly", async () => { - try { - await syscall("mock.setPage", "SETTINGS", settingsPageSample); - await syscall("mock.setPage", "SECRETS", secretsPageSample); - await initializeOpenAI(); - assertEquals( - aiSettings.textModels.length, - 2, - "initializeOpenAI did not set the correct number of text models", - ); - assertEquals( - aiSettings.textModels[0].name, - "gpt-4o", - "initializeOpenAI did not set the correct text model name", - ); - } catch (error) { - console.error( - "Error in test 'initializeOpenAI should set aiSettings correctly':", - error, - ); - throw error; - } + try { + await syscall("mock.setPage", "SETTINGS", settingsPageSample); + await syscall("mock.setPage", "SECRETS", secretsPageSample); + await initializeOpenAI(); + assertEquals( + aiSettings.textModels.length, + 2, + "initializeOpenAI did not set the correct number of text models", + ); + assertEquals( + aiSettings.textModels[0].name, + "gpt-4o", + "initializeOpenAI did not set the correct text model name", + ); + } catch (error) { + console.error( + "Error in test 'initializeOpenAI should set aiSettings correctly':", + error, + ); + throw error; + } }); Deno.test("initializeOpenAI should configure the selected model", async () => { - try { - await syscall("mock.setPage", "SETTINGS", settingsPageSample); - await syscall("mock.setPage", "SECRETS", secretsPageSample); - await initializeOpenAI(); - await getAndConfigureModel(); - assertEquals( - aiSettings.textModels[0].name, - "gpt-4o", - "getAndConfigureModel did not configure the correct text model", - ); - } catch (error) { - console.error( - "Error in test 'initializeOpenAI should configure the selected model':", - error, - ); - throw error; - } + try { + await syscall("mock.setPage", "SETTINGS", settingsPageSample); + await syscall("mock.setPage", "SECRETS", secretsPageSample); + await initializeOpenAI(); + await getAndConfigureModel(); + assertEquals( + aiSettings.textModels[0].name, + "gpt-4o", + "getAndConfigureModel did not configure the correct text model", + ); + } catch (error) { + console.error( + "Error in test 'initializeOpenAI should configure the selected model':", + error, + ); + throw error; + } }); + +Deno.test("initializeOpenAI should set image models correctly", async () => { + try { + await syscall("mock.setPage", "SETTINGS", settingsPageSample); + await syscall("mock.setPage", "SECRETS", secretsPageSample); + await initializeOpenAI(); + assertEquals( + aiSettings.imageModels.length, + 1, + "initializeOpenAI did not set the correct number of image models", + ); + assertEquals( + aiSettings.imageModels[0].name, + "dall-e", + "initializeOpenAI did not set the correct image model name", + ); + } catch (error) { + console.error( + "Error in test 'initializeOpenAI should set image models correctly':", + error, + ); + throw error; + } +}); + +Deno.test("initializeOpenAI should set embedding models correctly", async () => { + try { + await syscall("mock.setPage", "SETTINGS", settingsPageSample); + await syscall("mock.setPage", "SECRETS", secretsPageSample); + await initializeOpenAI(); + assertEquals( + aiSettings.embeddingModels.length, + 2, + "initializeOpenAI did not set the correct number of embedding models", + ); + assertEquals( + aiSettings.embeddingModels[0].name, + "text-embedding-3-small", + "initializeOpenAI did not set the correct embedding model name", + ); + } catch (error) { + console.error( + "Error in test 'initializeOpenAI should set embedding models correctly':", + error, + ); + throw error; + } +}); + +Deno.test("initializeOpenAI should handle missing settings gracefully", async () => { + try { + await syscall("mock.setPage", "SETTINGS", ""); + await syscall("mock.setPage", "SECRETS", secretsPageSample); + await initializeOpenAI(); + assertEquals( + aiSettings.textModels.length, + 0, + "initializeOpenAI did not handle missing settings correctly", + ); + } catch (error) { + console.error( + "Error in test 'initializeOpenAI should handle missing settings gracefully':", + error, + ); + throw error; + } +}); + +Deno.test("initializeOpenAI should throw an error if the API key is empty", async () => { + try { + const secretsPage = '```yaml\nOPENAI_API_KEY: ""\n```'; + await syscall("mock.setPage", "SETTINGS", settingsPageSample); + await syscall("mock.setPage", "SECRETS", secretsPage); + await initializeOpenAI(); + } catch (error) { + assertEquals( + error.message, + "AI API key is missing. Please set it in the secrets page.", + "initializeOpenAI did not handle empty secrets correctly", + ); + } +}); + +Deno.test("initializeOpenAI should throw an error if the API secret is missing", async () => { + try { + const secretsPage = "```yaml\n\n```"; + await syscall("mock.setPage", "SETTINGS", settingsPageSample); + await syscall("mock.setPage", "SECRETS", secretsPage); + await initializeOpenAI(); + } catch (error) { + assertEquals( + error.message, + "Failed to read the AI API key. Please check the SECRETS page.", + "initializeOpenAI did not handle missing secrets correctly", + ); + } +}); + +Deno.test( + "initializeOpenAI should throw an error if secrets page does not exist", + { sanitizeOps: false, sanitizeResources: false }, + async () => { + try { + await syscall("mock.setPage", "SETTINGS", settingsPageSample); + await initializeOpenAI(); + } catch (error) { + assertEquals( + error.message, + "Failed to read the AI API key. Please check the SECRETS page.", + "initializeOpenAI did not handle missing secrets correctly", + ); + } + }, +); diff --git a/src/init.ts b/src/init.ts index f0e8a58..915a7d9 100644 --- a/src/init.ts +++ b/src/init.ts @@ -214,10 +214,17 @@ export async function configureSelectedModel(model: ModelConfig) { } model.requireAuth = model.requireAuth ?? aiSettings.requireAuth; if (model.requireAuth) { - const newApiKey = await readSecret(model.secretName || "OPENAI_API_KEY"); - if (newApiKey !== apiKey) { - apiKey = newApiKey; - log("client", "API key updated"); + try { + const newApiKey = await readSecret(model.secretName || "OPENAI_API_KEY"); + if (newApiKey !== apiKey) { + apiKey = newApiKey; + log("client", "API key updated"); + } + } catch (error) { + console.error("Error reading secret:", error); + throw new Error( + "Failed to read the AI API key. Please check the SECRETS page.", + ); } } if (model.requireAuth && !apiKey) {