diff --git a/e2e-chatbot-app-next/.env.example b/e2e-chatbot-app-next/.env.example index 7dad22c9..7d25e3f9 100644 --- a/e2e-chatbot-app-next/.env.example +++ b/e2e-chatbot-app-next/.env.example @@ -60,3 +60,10 @@ DATABRICKS_SERVING_ENDPOINT=your-serving-endpoint # In production (Databricks Apps), this is injected automatically when the # experiment resource is configured in databricks.yml + app.yaml. # MLFLOW_EXPERIMENT_ID=/Users/your-email@company.com/chatbot-feedback-dev + +# ============================================ +# UI Configuration (Optional) +# ============================================ +# Greeting / empty-state message shown in the chat UI before the first message. +# Defaults to "What would you like to know?" when unset. +# CHAT_GREETING=How can I help with your account today? diff --git a/e2e-chatbot-app-next/client/src/components/greeting.tsx b/e2e-chatbot-app-next/client/src/components/greeting.tsx index c1213bc0..d24f8c8a 100644 --- a/e2e-chatbot-app-next/client/src/components/greeting.tsx +++ b/e2e-chatbot-app-next/client/src/components/greeting.tsx @@ -1,6 +1,8 @@ import { motion } from 'framer-motion'; +import { useAppConfig } from '@/contexts/AppConfigContext'; export const Greeting = () => { + const { greeting } = useAppConfig(); return (
{ exit={{ opacity: 0, y: 10 }} className="font-semibold text-lg md:text-xl text-center" > - What would you like to know? + {greeting}
); diff --git a/e2e-chatbot-app-next/client/src/contexts/AppConfigContext.tsx b/e2e-chatbot-app-next/client/src/contexts/AppConfigContext.tsx index 00b818d4..a1a211df 100644 --- a/e2e-chatbot-app-next/client/src/contexts/AppConfigContext.tsx +++ b/e2e-chatbot-app-next/client/src/contexts/AppConfigContext.tsx @@ -2,11 +2,14 @@ import { createContext, useContext, type ReactNode } from 'react'; import useSWR from 'swr'; import { fetcher } from '@/lib/utils'; +export const DEFAULT_GREETING = 'What would you like to know?'; + interface ConfigResponse { features: { chatHistory: boolean; feedback: boolean; }; + greeting?: string; obo?: { missingScopes: string[]; }; @@ -18,6 +21,7 @@ interface AppConfigContextType { error: Error | undefined; chatHistoryEnabled: boolean; feedbackEnabled: boolean; + greeting: string; oboMissingScopes: string[]; } @@ -44,6 +48,7 @@ export function AppConfigProvider({ children }: { children: ReactNode }) { // Default to true until loaded to avoid breaking existing behavior chatHistoryEnabled: data?.features.chatHistory ?? true, feedbackEnabled: data?.features.feedback ?? false, + greeting: data?.greeting ?? DEFAULT_GREETING, oboMissingScopes: data?.obo?.missingScopes ?? [], }; diff --git a/e2e-chatbot-app-next/server/src/routes/config.ts b/e2e-chatbot-app-next/server/src/routes/config.ts index 02c2279a..4d439e03 100644 --- a/e2e-chatbot-app-next/server/src/routes/config.ts +++ b/e2e-chatbot-app-next/server/src/routes/config.ts @@ -28,7 +28,9 @@ function getScopesFromToken(token: string): string[] { /** * GET /api/config - Get application configuration - * Returns feature flags and OBO status based on environment configuration. + * Returns feature flags, the empty-state greeting, and OBO status based on + * environment configuration. The greeting comes from CHAT_GREETING (the client + * falls back to a default when unset). * If the user's OBO token is present, decodes it to check which required * scopes are missing — the banner only shows missing scopes. */ @@ -54,6 +56,7 @@ configRouter.get('/', async (req: Request, res: Response) => { chatHistory: isDatabaseAvailable(), feedback: !!process.env.MLFLOW_EXPERIMENT_ID, }, + greeting: process.env.CHAT_GREETING || undefined, obo: { missingScopes, }, diff --git a/e2e-chatbot-app-next/tests/routes/config.test.ts b/e2e-chatbot-app-next/tests/routes/config.test.ts index 9a354205..2cb2ea08 100644 --- a/e2e-chatbot-app-next/tests/routes/config.test.ts +++ b/e2e-chatbot-app-next/tests/routes/config.test.ts @@ -46,6 +46,17 @@ test.describe('/api/config', () => { expect(data1).toEqual(data2); }); + test('GET /api/config omits greeting when CHAT_GREETING is unset', async ({ + adaContext, + }) => { + // CHAT_GREETING is not set in the test environment, so the server omits the + // field and the client falls back to its default greeting. + const response = await adaContext.request.get('/api/config'); + const data = await response.json(); + + expect(data.greeting).toBeUndefined(); + }); + test('GET /api/config returns OBO info', async ({ adaContext, }) => {