@agentup-inksen/web-chat-app
v0.0.7
Published
Embeddable full-screen chat app web component (<agentup-chat-app>) for AgentUp
Readme
@agentup-inksen/web-chat-app
Embeddable full-screen chat application for AgentUp, distributed as the <agentup-chat-app> web component (built on Lit). Designed for 3rd party host applications that already authenticate their users (Host SSO).
Layout
┌──────────────────────────────────────────────┐
│ Sidebar (agents + conversations) │ Chat │
│ │ pane │
│ │ │
└──────────────────────────────────────────────┘Below ~720px container width the sidebar collapses into a slide-over.
Quick start (npm)
npm install @agentup-inksen/web-chat-app litimport '@agentup-inksen/web-chat-app';<agentup-chat-app
api-url="https://api.agentup.example"
tenant-id="acme"
visitor-token="<JWT minted server-side>"
lang="en">
</agentup-chat-app>Drop-in (no bundler)
<script src="https://cdn.example.com/agentup-chat-app.iife.js"></script>
<agentup-chat-app
api-url="https://api.agentup.example"
tenant-id="acme"
visitor-token="..."></agentup-chat-app>Visitor token (Host SSO)
The visitor token is minted by your backend, never the browser. Your host server proves itself with the tenant's widget API key:
curl -X POST https://api.agentup.example/api/webchat/visitor-tokens \
-H 'X-Tenant-Id: acme' \
-H 'X-Widget-Api-Key: <secret-from-dashboard>' \
-H 'Content-Type: application/json' \
-d '{
"externalUserId": "host-user-123",
"name": "Demo User",
"email": "[email protected]"
}'Response:
{
"visitorToken": "eyJhbGciOi...",
"expiresAt": "2026-04-30T17:30:00Z",
"visitorId": "..."
}Ship visitorToken to the browser (cookie/inline <script>) and pass it to the component. When it expires, listen for agentup-auth-error, refresh from your backend, and assign the new value:
const el = document.querySelector('agentup-chat-app')!;
el.addEventListener('agentup-auth-error', async () => {
el.visitorToken = await fetch('/api/host/refresh-agentup-token').then(r => r.text());
});Theming
Set CSS custom properties on the host element:
agentup-chat-app {
--agentup-bg: #0f172a;
--agentup-surface: #1e293b;
--agentup-surface-2: #334155;
--agentup-border: #475569;
--agentup-text: #e2e8f0;
--agentup-muted: #94a3b8;
--agentup-primary: #6366f1;
--agentup-primary-contrast: #ffffff;
--agentup-radius: 16px;
--agentup-sidebar-width: 320px;
--agentup-font: 'Inter', sans-serif;
}Slots
| Slot | Purpose |
| --- | --- |
| header | Replaces the default header text (e.g. logo) |
| empty-state | Replaces the default empty state |
Events
| Event | Detail | Description |
| --- | --- | --- |
| agentup-auth-error | – | Visitor token expired/invalid. Refresh and re-assign visitorToken. |
| agentup-conversation-changed | { conversationId } | Active conversation changed. |
i18n
lang="tr" or lang="en" switches between bundled strings. The component also tries to load tenant-managed translations from GET /api/translations/language/{lang} (best-effort) and merges them on top. Or pass a static dictionary:
el.translations = { 'web_chat_app.title': 'Müşteri Destek' };Build
cd packages/app
npm run build # tsup (esm+cjs+dts) + vite (iife+css)
npm run dev # vite dev server pointing at demo/index.htmlRoadmap
- Search inside the conversations list.
- File upload (already exposed via
POST /api/webchat/upload). - Sub-elements (
<agentup-agent-list>,<agentup-chat-pane>) extracted for advanced custom layouts.
