Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions e2e-chatbot-app-next/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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?
4 changes: 3 additions & 1 deletion e2e-chatbot-app-next/client/src/components/greeting.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { motion } from 'framer-motion';
import { useAppConfig } from '@/contexts/AppConfigContext';

export const Greeting = () => {
const { greeting } = useAppConfig();
return (
<div
key="overview"
Expand All @@ -12,7 +14,7 @@ export const Greeting = () => {
exit={{ opacity: 0, y: 10 }}
className="font-semibold text-lg md:text-xl text-center"
>
What would you like to know?
{greeting}
</motion.div>
</div>
);
Expand Down
5 changes: 5 additions & 0 deletions e2e-chatbot-app-next/client/src/contexts/AppConfigContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
};
Expand All @@ -18,6 +21,7 @@ interface AppConfigContextType {
error: Error | undefined;
chatHistoryEnabled: boolean;
feedbackEnabled: boolean;
greeting: string;
oboMissingScopes: string[];
}

Expand All @@ -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 ?? [],
};

Expand Down
5 changes: 4 additions & 1 deletion e2e-chatbot-app-next/server/src/routes/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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,
},
Expand Down
11 changes: 11 additions & 0 deletions e2e-chatbot-app-next/tests/routes/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}) => {
Expand Down