mono/packages/ui/docs/support-chat.md
2026-03-21 20:18:25 +01:00

4.3 KiB

Support Chat

Embeddable AI support chat built on ChatPanel with a fixed support preset (no header, no sidebar). System prompts are assembled from defaults.ts, injecting the user's UI language and named context blocks automatically.


Route

/support-chat — public, no auth required. Registered in App.tsx via the SupportChat page.


Architecture

SupportChat (page/embed)
  └── ChatPanel  preset="support"
        ├── useChatEngine('support')          ← isolated localStorage namespace
        ├── buildSupportPrompt(context)       ← from defaults.ts
        │     ├── BASE_SUPPORT_PROMPT
        │     ├── getCurrentLang()            ← from i18n.tsx
        │     └── SUPPORT_CONTEXTS[key...]    ← named blocks
        └── seed useEffect (once on mount)
              sets provider / model / tools / systemPrompt

localStorage isolation

Each ChatPanel preset gets its own storage namespace via useChatEngine(preset):

Preset Key prefix
developer / standard / simple developer-settings-* etc.
support support-settings-*

This prevents PlaygroundChat from polluting SupportChat settings (and vice versa).


System Prompt Assembly

File: src/modules/ai/defaults.ts

buildSupportPrompt(contexts?)
// → BASE_SUPPORT_PROMPT
// + "Always reply in Français (language code: fr)."   ← auto from getCurrentLang()
// + SUPPORT_CONTEXTS['shipping-rates']                 ← if in contexts

Default contexts

export const DEFAULT_CONTEXTS: SupportContextKey[] = ['shipping-rates'];

Applied when no context prop is passed.

Adding a new context block

// src/modules/ai/defaults.ts
export const SUPPORT_CONTEXTS: Record<string, string> = {
  'shipping-rates': `...`,
  'returns': `## Returns Policy\n...`,   // ← add here
};

The key becomes the SupportContextKey union type automatically.


Embedding

Standalone page (default)

<SupportChat />
// Uses: openrouter / gpt-4o, search tools ON, DEFAULT_CONTEXTS

With custom contexts

<SupportChat context={['shipping-rates', 'returns']} />

With different model / provider

<SupportChat
  provider="openai"
  model="gpt-4o-mini"
  context={['shipping-rates']}
/>

With live runtime context (e.g. current order)

Use ChatPanel directly with getContext — called before every send:

<ChatPanel
  preset="support"
  context={['shipping-rates']}
  getContext={() => `User is viewing order #${orderId}`}
/>

All props

SupportChat

Prop Type Default Description
context SupportContextKey[] DEFAULT_CONTEXTS Context blocks appended to base prompt
provider string 'openrouter' AI provider
model string 'openai/gpt-4o' AI model
searchTools boolean true Site search tools
pageTools boolean false Page/content tools
imageTools boolean false Image generation tool
vfsTools boolean false VFS file tools

ChatPanel (additional props relevant to support embeds)

Prop Type Description
context SupportContextKey[] Same as above, passed through
initialSystemPrompt string Overrides buildSupportPrompt entirely
getContext () => string | null Dynamic context injected before each send
extraTools () => any[] Additional tool definitions

Navigation

A MessageSquare icon button is always visible in TopNavigation (public, no auth guard), highlighting when the route is active.


Files

File Role
src/pages/SupportChat.tsx Page component + embed wrapper
src/modules/ai/defaults.ts Prompt registry (BASE_SUPPORT_PROMPT, SUPPORT_CONTEXTS, buildSupportPrompt)
src/modules/ai/ChatPanel.tsx Panel with support preset + initial* seed props + context prop
src/modules/ai/useChatEngine.ts Engine hook, namespaced via namespace param
src/App.tsx /support-chat route
src/components/TopNavigation.tsx Nav icon button