@illuma-ai/agentviz
v1.0.1
Published
Embeddable agent chat widget — stream LLM responses with DOM extraction, theming, and markdown rendering
Maintainers
Readme
@illuma-ai/agentviz
Embeddable, framework-agnostic agent chat widget. Stream LLM responses with markdown rendering, file attachments, text selection summaries, and complete style isolation via Shadow DOM.
- Two widget types: Inline Summary (icon → summary/analysis) and Agent Chat (full conversation)
- Multiple display modes: Popover, drawer, FAB (floating action button), DOM injection
- Text selection summary: Highlight any text → floating "Summarize" / "Ask" toolbar
- Zero framework dependencies — works with React, Vue, Angular, or plain HTML
- Full style isolation — Shadow DOM +
all: initialCSS reset, no parent style leakage - Dark & light themes with full color token customization
Installation
npm install @illuma-ai/agentvizOr via CDN (IIFE bundle — exposes AgentViz and SelectionSummary globals):
<script src="https://unpkg.com/@illuma-ai/agentviz/dist/agentviz.iife.js"></script>Quick Start
Agent Chat — FAB (Floating Action Button)
A circular chat icon pinned to the bottom-right of the viewport. Clicking opens a drawer.
import { AgentViz } from '@illuma-ai/agentviz';
const widget = new AgentViz({
type: 'agent-chat',
displayMode: 'fab',
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
icon: '<svg>...</svg>', // or image URL
brandName: 'Illuma',
theme: 'dark',
});
widget.mount();Inline Summary — Icon in Header
Place a summary icon next to any section. Clicking extracts the content and sends it to the agent.
import { AgentViz } from '@illuma-ai/agentviz';
const widget = new AgentViz({
type: 'inline',
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
icon: '<svg>...</svg>',
contentMode: 'dom',
data: document.querySelector('#my-section'),
displayMode: 'popover',
parentElement: document.querySelector('#icon-container'),
brandName: 'Illuma',
});
widget.mount();Widget Types
type: "inline" — Inline Summary
An icon placed in the page DOM (header, toolbar, sidebar). When clicked, it extracts content based on contentMode and sends it to the agent for summary/analysis.
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| type | "inline" | Yes | Widget type discriminator |
| agentId | string | Yes | Agent ID for API calls |
| url | string | Yes | API base URL |
| token | string | Yes | API token (rat_...) |
| icon | string | Yes | Icon SVG markup or image URL |
| contentMode | "dom" \| "text" \| "json" | Yes | How content is delivered to the agent |
| data | HTMLElement \| string \| object | Yes | Content payload (type depends on contentMode) |
| displayMode | "popover" \| "drawer" | Yes | How the summary UI is displayed |
| parentElement | HTMLElement | Yes | DOM element to mount the icon into |
| chatEnabled | boolean | No | Show chat input for follow-up questions (default: false) |
| attachAsContext | boolean | No | JSON mode only — how JSON data is sent (default: true) |
| theme | "dark" \| "light" \| ThemeColors | No | Theme preset or custom colors (default: "dark") |
| brandName | string | No | Brand name in header (default: "Agent") |
| updateMemory | boolean | No | Pass updateMemory flag to API (default: false) |
Content Modes
// DOM — extract text/HTML from DOM elements
{ contentMode: 'dom', data: document.querySelector('#article') }
{ contentMode: 'dom', data: [el1, el2, el3] } // multiple elements
// Text — send plain text directly
{ contentMode: 'text', data: 'Your text content to summarize...' }
// JSON — send structured data
{ contentMode: 'json', data: { revenue: 12500000, growth: 0.18 } }Display Modes
// Popover — floating panel anchored to the icon
{ displayMode: 'popover' }
// Drawer — slide-in panel from the right
{ displayMode: 'drawer' }type: "agent-chat" — Agent Chat
Full conversational chat with the agent. Three display modes with different UX patterns.
FAB (Floating Action Button)
Circular button pinned to bottom-right of viewport. Always opens a drawer.
new AgentViz({
type: 'agent-chat',
displayMode: 'fab',
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
icon: '<svg>...</svg>',
fileAttach: true, // enable file uploads
theme: 'dark',
}).mount();| Property | Type | Required | Description |
|----------|------|----------|-------------|
| displayMode | "fab" | Yes | FAB mode |
| icon | string | Yes | Icon SVG or image URL for the FAB button |
| fileAttach | boolean | No | Enable file attachment (default: false) |
Icon Inline
Icon embedded in your page DOM (header, toolbar, etc). Opens chat via popover or drawer.
new AgentViz({
type: 'agent-chat',
displayMode: 'icon-inline',
parentElement: document.querySelector('#header-actions'),
subDisplayMode: 'popover', // or 'drawer'
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
icon: '<svg>...</svg>',
}).mount();| Property | Type | Required | Description |
|----------|------|----------|-------------|
| displayMode | "icon-inline" | Yes | Icon inline mode |
| parentElement | HTMLElement | Yes | DOM element to mount the icon into |
| subDisplayMode | "popover" \| "drawer" | Yes | How the chat panel opens |
| icon | string | Yes | Icon SVG or image URL |
DOM Inject
Chat injected directly into a container element. No icon, no overlay — the chat is part of your page layout.
new AgentViz({
type: 'agent-chat',
displayMode: 'dom-inject',
parentElement: document.querySelector('#chat-container'),
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
}).mount();| Property | Type | Required | Description |
|----------|------|----------|-------------|
| displayMode | "dom-inject" | Yes | DOM inject mode |
| parentElement | HTMLElement | Yes | Container to inject chat into |
| icon | string | No | Not typically needed |
Selection Summary
Global text-selection feature. Users highlight text anywhere on the page and get a floating toolbar with "Summarize" and "Ask" actions.
import { SelectionSummary } from '@illuma-ai/agentviz';
// Enable once at app level — works across all pages
SelectionSummary.enable({
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
brandName: 'Illuma',
theme: 'dark',
chatEnabled: true, // allow follow-up questions after summary
});
// Disable when no longer needed
SelectionSummary.disable();| Property | Type | Required | Description |
|----------|------|----------|-------------|
| agentId | string | Yes | Agent ID |
| url | string | Yes | API base URL |
| token | string | Yes | API token |
| brandName | string | No | Shown in toolbar and popover header |
| theme | "dark" \| "light" \| ThemeColors | No | Theme (default: "dark") |
| chatEnabled | boolean | No | Show chat input for follow-up (default: false) |
| icon | string | No | Custom icon for the toolbar button |
| minSelectionLength | number | No | Minimum chars to trigger toolbar (default: 10) |
API Reference
AgentViz
class AgentViz {
constructor(config: AgentVizConfig);
/** Mount the widget into the DOM */
mount(): void;
/** Remove from DOM but preserve conversation state */
unmount(): void;
/** Full cleanup — remove from DOM, abort streams, reset state */
destroy(): void;
/** Send a message to the agent programmatically */
sendMessage(text: string, files?: File[]): Promise<void>;
/** Send content for inline widgets (extracts based on contentMode) */
sendContent(): Promise<void>;
/** Update theme at runtime */
setTheme(theme: 'dark' | 'light' | Partial<ThemeColors>): void;
/** Open the widget panel */
open(): void;
/** Close the widget panel (preserves conversation) */
close(): void;
}SelectionSummary
class SelectionSummary {
/** Enable text-selection summary globally (singleton) */
static enable(config: SelectionSummaryConfig): SelectionSummary;
/** Disable and clean up */
static disable(): void;
/** Check if currently enabled */
static isEnabled(): boolean;
}Callbacks
new AgentViz({
// ...
onMessage: (msg) => console.log(`${msg.role}: ${msg.content}`),
onError: (err) => console.error('Widget error:', err),
onReady: () => console.log('Widget mounted'),
});Theming
Built-in Themes
// Dark theme (default)
{ theme: 'dark' }
// Light theme
{ theme: 'light' }Custom Colors
Override any color token from the base theme:
new AgentViz({
// ...
theme: {
background: '#0f0f23',
accent: '#8b5cf6',
userBubble: '#7c3aed',
userBubbleText: '#ffffff',
},
});Runtime Theme Switching
widget.setTheme('light');
widget.setTheme({ accent: '#e94560', background: '#1a1a2e' });Color Tokens
| Token | Description |
|-------|-------------|
| background | Main widget background |
| surface | Message bubble / card background |
| surfaceHover | Hover state for interactive surfaces |
| text | Primary text color |
| textSecondary | Secondary / muted text |
| primary | Primary brand color |
| accent | Accent color for links, highlights |
| border | Border color |
| inputBackground | Chat input background |
| inputText | Chat input text color |
| inputBorder | Chat input border |
| userBubble | User message bubble background |
| userBubbleText | User message text color |
| agentBubble | Agent message bubble background |
| agentBubbleText | Agent message text color |
| skeleton | Loading skeleton base color |
| skeletonShimmer | Loading skeleton shimmer highlight |
| error | Error text color |
| scrollbarThumb | Scrollbar thumb color |
| codeBackground | Code block background |
Framework Integration
React
import { useRef, useEffect } from 'react';
import { AgentViz } from '@illuma-ai/agentviz';
function ChatWidget() {
const containerRef = useRef<HTMLDivElement>(null);
const widgetRef = useRef<AgentViz | null>(null);
useEffect(() => {
if (!containerRef.current) return;
const widget = new AgentViz({
type: 'agent-chat',
displayMode: 'dom-inject',
parentElement: containerRef.current,
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
theme: 'dark',
});
widget.mount();
widgetRef.current = widget;
return () => widget.destroy();
}, []);
return <div ref={containerRef} style={{ height: 500 }} />;
}React — Inline Summary Icon
function SectionWithSummary({ children }) {
const iconRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!iconRef.current || !contentRef.current) return;
const widget = new AgentViz({
type: 'inline',
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
icon: '<svg>...</svg>',
contentMode: 'dom',
data: contentRef.current,
displayMode: 'popover',
parentElement: iconRef.current,
});
widget.mount();
return () => widget.destroy();
}, []);
return (
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<h2>Section Title</h2>
<div ref={iconRef} />
</div>
<div ref={contentRef}>{children}</div>
</div>
);
}Vue
<template>
<div ref="container" style="height: 500px" />
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { AgentViz } from '@illuma-ai/agentviz';
const container = ref(null);
let widget = null;
onMounted(() => {
widget = new AgentViz({
type: 'agent-chat',
displayMode: 'dom-inject',
parentElement: container.value,
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
});
widget.mount();
});
onUnmounted(() => widget?.destroy());
</script>Plain HTML (IIFE)
<script src="https://unpkg.com/@illuma-ai/agentviz/dist/agentviz.iife.js"></script>
<script>
// FAB — no container needed, auto-injects bottom-right
new AgentViz({
type: 'agent-chat',
displayMode: 'fab',
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',
}).mount();
// Selection Summary — global text highlight feature
SelectionSummary.enable({
agentId: 'agent_xxx',
url: 'https://app.illuma.ai',
token: 'rat_xxx',
brandName: 'Illuma',
});
</script>Exports
// Main class (facade)
export { AgentViz } from './widget';
// Widget implementations (advanced use)
export { InlineWidget } from './widget-inline';
export { AgentChatWidget } from './widget-agent-chat';
// Selection Summary
export { SelectionSummary } from './selection-summary';
export type { SelectionSummaryConfig } from './selection-summary';
// Types
export type {
AgentVizConfig,
InlineWidgetConfig,
AgentChatWidgetConfig,
AgentChatFabConfig,
AgentChatIconInlineConfig,
AgentChatDomInjectConfig,
AgentVizInstance,
WidgetType,
ContentMode,
InlineDisplayMode,
AgentChatDisplayMode,
SubDisplayMode,
ThemeColors,
ThemeInput,
Message,
FileAttachment,
StreamEvent,
} from './types';
// Theme presets
export { DARK_THEME, LIGHT_THEME } from './themes';
// Constants
export { ICONS, DEFAULTS, Z_INDEX } from './constants';License
MIT — see LICENSE
