# LogicAppsAgentChat **Repository Path**: mirrors_Azure/LogicAppsAgentChat ## Basic Information - **Project Name**: LogicAppsAgentChat - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-25 - **Last Updated**: 2026-02-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # A2A Chat Monorepo [![CI](https://github.com/travisvu/a2achat/actions/workflows/ci.yml/badge.svg)](https://github.com/travisvu/a2achat/actions/workflows/ci.yml) [![PR Checks](https://github.com/travisvu/a2achat/actions/workflows/pr-checks.yml/badge.svg)](https://github.com/travisvu/a2achat/actions/workflows/pr-checks.yml) [![Security](https://github.com/travisvu/a2achat/actions/workflows/security.yml/badge.svg)](https://github.com/travisvu/a2achat/actions/workflows/security.yml) A TypeScript SDK for building chat interfaces that connect to A2A (Agent-to-Agent) protocol agents. Available as both a library and an embeddable iframe widget. ## ๐Ÿ“ฆ What's Inside This monorepo contains: - **[@microsoft/a2achat-core](./packages/a2a-core)** - Core TypeScript SDK with framework-agnostic APIs and React components - **[Iframe App](./apps/iframe-app)** - Embeddable iframe widget for easy integration - **[Documentation Site](./apps/docs-site)** - Comprehensive Docusaurus documentation ## Structure ``` โ”œโ”€โ”€ packages/ โ”‚ โ””โ”€โ”€ a2a-core/ # Core SDK with multiple entry points โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ”œโ”€โ”€ index.ts # Main entry (core APIs) โ”‚ โ”‚ โ”œโ”€โ”€ react/index.ts # React entry (components & hooks) โ”‚ โ”‚ โ””โ”€โ”€ chat/index.ts # Chat entry (event-driven interface) โ”‚ โ””โ”€โ”€ README.md โ”œโ”€โ”€ apps/ โ”‚ โ”œโ”€โ”€ iframe-app/ # Embeddable iframe widget โ”‚ โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ”œโ”€โ”€ docs/ # Iframe-specific documentation โ”‚ โ”‚ โ””โ”€โ”€ README.md โ”‚ โ””โ”€โ”€ docs-site/ # Documentation website โ””โ”€โ”€ docs/ # Architecture & design docs ``` ## Development ### Prerequisites - Node.js >= 18 - PNPM >= 10.12.4 ### Setup ```bash # Install dependencies pnpm install # Build all packages pnpm run build # Run development mode pnpm run dev # Run tests pnpm run test # Type checking pnpm run type-check # Linting pnpm run lint # Format code with Prettier pnpm run format # Format check (CI) pnpm run format:check ``` ### Working with Packages ```bash # Build a specific package pnpm --filter @a2achat/core build # Run tests for a specific package pnpm --filter @a2achat/react test # Add a dependency to a package pnpm --filter @a2achat/core add some-package ``` ## Deployment ### Publishing Packages ```bash # Create a changeset pnpm changeset # Version packages pnpm version-packages # Publish to npm pnpm release ``` ## ๐Ÿ“– Examples ### Server-Side History with Multi-Session ```tsx import { ChatWidget } from '@microsoft/a2achat-core/react'; getToken(), }} // Resume existing conversation initialContextId="conv-abc123" // Track context changes onContextIdChange={(contextId) => { console.log('Context changed:', contextId); // Optionally save to URL or localStorage history.pushState({}, '', `?contextId=${contextId}`); }} />; ``` ### Custom UI with useA2A Hook ```tsx import { useA2A } from '@microsoft/a2achat-core/react'; import { useState } from 'react'; function CustomChatUI() { const [input, setInput] = useState(''); const { messages, isLoading, isConnected, sendMessage, clearMessages, authState } = useA2A({ agentCard: 'https://api.example.com', auth: { type: 'bearer', token: 'token' }, storageConfig: { type: 'indexeddb' }, }); const handleSend = async () => { if (!input.trim()) return; await sendMessage(input); setInput(''); }; return (
{isConnected ? 'Connected' : 'Disconnected'}
{authState.isRequired &&
Authentication required...
}
{messages.map((msg) => (
{msg.sender}: {msg.content}
))}
{isLoading &&
Loading...
} setInput(e.target.value)} onKeyPress={(e) => e.key === 'Enter' && handleSend()} />
); } ``` ### Handling On-Behalf-Of (OBO) Authentication ```tsx import { ChatWidget } from '@microsoft/a2achat-core/react'; { console.log('Unauthorized:', event.url, event.statusText); // Refresh token try { const response = await fetch('/.auth/refresh', { credentials: 'same-origin', }); if (response.ok) { // Token refreshed, retry will happen automatically console.log('Token refreshed'); } else { // Redirect to login window.location.href = '/.auth/login/aad'; } } catch (error) { console.error('Failed to refresh token:', error); } }} />; ``` ### Low-Level Client with Streaming ```typescript import { A2AClient } from '@microsoft/a2achat-core'; const client = new A2AClient({ agentCard: 'https://api.example.com', auth: { type: 'bearer', token: 'token' }, onAuthRequired: (event) => { console.log('Auth required:', event.authParts); // Open consent URLs in popup event.authParts.forEach((part) => { if (part.url) { window.open(part.url, '_blank', 'width=600,height=700'); } }); }, }); // Stream messages const stream = await client.message.stream({ message: { role: 'user', parts: [{ kind: 'text', text: 'Hello, how are you?' }], }, }); for await (const chunk of stream) { if (chunk.kind === 'text') { console.log('Text:', chunk.text); } else if (chunk.kind === 'data') { console.log('Data:', chunk.data); } } ``` ## โœจ Features ### Core Features - ๐Ÿš€ **Small bundle size**: ~45KB with React as peer dependency - ๐Ÿ“ฆ **Dual distribution**: NPM package + iframe embed - ๐ŸŽจ **Fully customizable**: CSS variables for runtime theming - โš›๏ธ **React 19+ compatible**: Modern React applications - โœ… **TypeScript**: Full type safety and IntelliSense - ๐Ÿงช **Well tested**: Comprehensive test suite with Vitest ### Chat Features - ๐Ÿ“ **Markdown support**: Rich text formatting with syntax highlighting - ๐Ÿ“Ž **File uploads**: Built-in file attachment support with progress tracking - ๐Ÿข **Company branding**: Add your logo to the chat interface - ๐Ÿ’ฌ **Multi-session**: Multiple concurrent conversations with sidebar UI - ๐Ÿ” **Authentication**: Bearer, API Key, OAuth2, Cookie, and custom handlers - ๐ŸŒŠ **Real-time streaming**: Server-Sent Events (SSE) for real-time agent responses - ๐Ÿ’พ **Chat history**: Client-side (IndexedDB) or server-side storage - ๐Ÿ” **Agent discovery**: Automatic agent card resolution ### Integration - ๐Ÿ–ผ๏ธ **Iframe embeddable**: Easy no-code integration - ๐Ÿ“จ **PostMessage API**: Cross-origin communication - ๐ŸชŸ **Azure Portal**: Frame Blade protocol support - ๐Ÿ”Œ **Plugin system**: Extensible with custom analytics, logging, and more ## ๐Ÿš€ Quick Start ### Installation ```bash npm install @microsoft/a2achat-core # or pnpm add @microsoft/a2achat-core # or yarn add @microsoft/a2achat-core ``` ### Library Usage (React) ```tsx import { ChatWidget } from '@microsoft/a2achat-core/react'; import '@microsoft/a2achat-core/react/styles.css'; function App() { return ( console.log('New message:', message)} onConnectionChange={(connected) => console.log('Connected:', connected)} /> ); } ``` ### Iframe Usage ```html ``` ## ๐Ÿ“š Documentation ### Library Usage The `@microsoft/a2achat-core` package provides three entry points for different use cases: #### 1. React Components (`/react`) Full-featured React components with built-in UI and state management: ```tsx import { ChatWidget, ChatWindow } from '@microsoft/a2achat-core/react'; import '@microsoft/a2achat-core/react/styles.css'; // Single-session chat // Multi-session chat with server-side history ``` #### 2. React Hooks (`/react`) For custom UI implementations: ```tsx import { useA2A } from '@microsoft/a2achat-core/react'; function CustomChat() { const { messages, isLoading, isConnected, sendMessage, authState } = useA2A({ agentCard: 'https://api.example.com', auth: { type: 'bearer', token: 'token' }, }); return (
{messages.map((msg) => (
{msg.content}
))} { if (e.key === 'Enter') sendMessage(e.target.value); }} />
); } ``` #### 3. Core Client API (main entry) Framework-agnostic for any JavaScript environment: ```typescript import { A2AClient } from '@microsoft/a2achat-core'; const client = new A2AClient({ agentCard: 'https://api.example.com', auth: { type: 'bearer', token: 'token' }, }); // Send a message const task = await client.message.send({ message: { role: 'user', parts: [{ kind: 'text', text: 'Hello' }], }, }); // Stream responses for await (const chunk of await client.message.stream({ message: { role: 'user', parts: [{ kind: 'text', text: 'Hello' }], }, })) { console.log(chunk); } ``` #### 4. Event-Driven Chat Interface (`/chat`) For event-based architectures: ```typescript import { ChatInterface } from '@microsoft/a2achat-core/chat'; const chat = new ChatInterface({ agentCard: 'https://api.example.com', auth: { type: 'bearer', token: 'token' }, }); chat.on('message-sent', (msg) => console.log('Sent:', msg)); chat.on('message-received', (msg) => console.log('Received:', msg)); chat.on('error', (err) => console.error('Error:', err)); await chat.sendMessage('Hello, agent!'); ``` ### Authentication Methods ```tsx import { AuthConfig } from '@microsoft/a2achat-core'; // Bearer token const bearerAuth: AuthConfig = { type: 'bearer', token: 'your-bearer-token', }; // API Key const apiKeyAuth: AuthConfig = { type: 'api-key', key: 'your-api-key', header: 'X-API-Key', }; // OAuth2 const oauth2Auth: AuthConfig = { type: 'oauth2', accessToken: 'your-access-token', tokenType: 'Bearer', }; // Cookie-based (for same-origin) const cookieAuth: AuthConfig = { type: 'cookie', }; // Custom handler const customAuth: AuthConfig = { type: 'custom', handler: async (request) => { const token = await getTokenFromYourAuthService(); request.headers.set('Authorization', `Custom ${token}`); return request; }, }; // No authentication const noAuth: AuthConfig = { type: 'none', }; ``` ### Iframe Widget Usage The iframe app provides an easy way to embed chat without npm dependencies. See [apps/iframe-app](./apps/iframe-app) for full documentation. #### Basic Embedding ```html ``` #### Configuration Options (URL Parameters or Data Attributes) | Parameter/Attribute | Type | Description | Default | | ------------------- | ------- | --------------------------------------------- | --------- | | `agentCard` | string | Agent card URL (required) | - | | `userId` | string | User identifier | - | | `userName` | string | Display name | - | | `theme` | string | Preset theme (blue, green, red, purple, etc.) | 'default' | | `mode` | string | Light or dark mode | 'light' | | `multiSession` | boolean | Enable multi-session mode | false | | `singleSession` | boolean | Force single-session mode | true | | `contextId` | string | Pre-populate session context ID | - | | `allowFileUpload` | boolean | Enable file uploads | true | | `maxFileSize` | number | Max file size in bytes | 10MB | | `allowedFileTypes` | string | Comma-separated MIME types | - | | `placeholder` | string | Input placeholder text | - | | `welcomeMessage` | string | Initial bot message | - | | `apiKey` | string | API key for authentication | - | | `oboUserToken` | string | On-behalf-of user token | - | | `logoUrl` | string | Branding logo URL | - | | `logoSize` | string | Logo size (small, medium, large) | 'medium' | | `logoPosition` | string | Logo position (header, footer) | 'header' | | `expectPostMessage` | boolean | Wait for postMessage configuration | false | | `inPortal` | boolean | Azure Portal context mode | false | | `trustedAuthority` | string | Portal's origin for auth | - | | `allowedOrigins` | string | Comma-separated allowed postMessage origins | - | #### Multi-Session Mode Enable multiple concurrent conversations with a sidebar UI: ```html ``` Features: - Multiple concurrent conversations - Session persistence in localStorage - Session renaming and deletion - Last message preview - Activity timestamps #### PostMessage Protocol For dynamic configuration or parent-iframe communication: ```html ``` #### Azure Portal Integration (Frame Blade) For Azure Portal blade integration: ```html ``` The iframe supports the Frame Blade protocol: - `ready` - Iframe initialization - `initializationcomplete` - Full setup done - `revealcontent` - Ready to display - `themeChanged` - Handle portal theme changes - `authToken` - Receive authentication tokens - `chatHistory` - Import chat history #### Security The iframe validates postMessage origins against: 1. Explicitly configured `allowedOrigins` 2. Document referrer origin 3. Current iframe origin 4. Development origins (localhost) Wildcard subdomain matching supported: `*.example.com` ```html ``` ## ๐Ÿ› ๏ธ Development ### Prerequisites - Node.js >= 18 - pnpm >= 10.12.4 ### Getting Started ```bash # Clone the repository git clone https://github.com/your-org/a2achat.git cd a2achat # Install dependencies pnpm install # Build all packages pnpm build # Start development mode for all packages pnpm dev ``` ### Monorepo Commands ```bash # Run commands for all packages pnpm test # Run all tests pnpm typecheck # Type check all packages pnpm lint # Lint all packages pnpm format # Format all files pnpm build # Build all packages # Run commands for specific package pnpm --filter @microsoft/a2achat-core test pnpm --filter @microsoft/a2achat-core build pnpm --filter @a2achat/iframe-app dev # Add dependencies to specific package pnpm --filter @microsoft/a2achat-core add lodash pnpm --filter @microsoft/a2achat-core add -D @types/lodash ``` ### Testing ```bash # Run all tests pnpm test # Run tests for specific package pnpm --filter @microsoft/a2achat-core test # Run tests in watch mode pnpm --filter @microsoft/a2achat-core test:watch # Run tests with UI pnpm --filter @microsoft/a2achat-core test:ui # Run tests with coverage pnpm test:coverage ``` ### Publishing ```bash # Create a changeset (document changes) pnpm changeset # Version packages based on changesets pnpm version-packages # Build and publish to npm pnpm release ``` See [DEVELOPMENT.md](./DEVELOPMENT.md) for detailed development guidelines. ## โš™๏ธ Configuration ### ChatWidget / ChatWindow Props | Prop | Type | Description | Default | | -------------------- | ------------------------------------ | --------------------------------------------- | ------- | | `agentCard` | `string \| AgentCard` | Agent URL or agent card object (required) | - | | `auth` | `AuthConfig` | Authentication configuration | - | | `theme` | `Partial` | Custom theme configuration | - | | `userId` | `string` | User identifier | - | | `userName` | `string` | Display name | - | | `metadata` | `Record` | Additional metadata | - | | `placeholder` | `string` | Input placeholder text | - | | `welcomeMessage` | `string` | Initial welcome message | - | | `allowFileUpload` | `boolean` | Enable file uploads | true | | `maxFileSize` | `number` | Max file size in bytes | 10MB | | `allowedFileTypes` | `string[]` | Allowed file types (MIME types or extensions) | - | | `sessionKey` | `string` | Unique key for session storage | - | | `sessionId` | `string` | Explicit session identifier | - | | `sessionName` | `string` | Display name for session | - | | `agentUrl` | `string` | Override agent endpoint URL | - | | `storageConfig` | `StorageConfig` | Chat history storage configuration | - | | `initialContextId` | `string` | Resume existing conversation context | - | | `onMessage` | `(message: Message) => void` | Message event callback | - | | `onConnectionChange` | `(connected: boolean) => void` | Connection status callback | - | | `onToggleSidebar` | `() => void` | Sidebar toggle callback (multi-session) | - | | `onContextIdChange` | `(contextId: string) => void` | Context ID change callback | - | | `onRenameSession` | `(newName: string) => Promise` | Session rename callback | - | | `onUnauthorized` | `(event: UnauthorizedEvent) => void` | 401 error handler for re-authentication | - | ### Theme Configuration ```typescript interface ChatTheme { colors: { primary: string; // Primary accent color primaryText: string; // Text on primary color background: string; // Main background surface: string; // Card/container background text: string; // Primary text textSecondary: string; // Secondary text border: string; // Border color error: string; // Error states success: string; // Success states backgroundDark?: string; // Dark mode background surfaceDark?: string; // Dark mode surface textDark?: string; // Dark mode text textSecondaryDark?: string; // Dark mode secondary text borderDark?: string; // Dark mode border }; typography: { fontFamily: string; fontSize: { small: string; base: string; large: string; }; }; spacing: { unit: number; // Base spacing unit (in pixels) }; borderRadius: { small: string; medium: string; large: string; }; branding?: { logoUrl?: string; logoSize?: 'small' | 'medium' | 'large'; logoPosition?: 'header' | 'footer'; name?: string; }; } // Usage import { createCustomTheme, defaultLightTheme } from '@microsoft/a2achat-core/react'; const myTheme = createCustomTheme({ primaryColor: '#0066cc', backgroundColor: '#ffffff', }); ``` ### Storage Configuration ```typescript type StorageConfig = | { type: 'indexeddb' } // Client-side IndexedDB storage | { type: 'server'; // Server-side storage agentUrl: string; getAuthToken?: () => string | Promise; }; // Usage localStorage.getItem('token') || '', }} initialContextId="existing-conversation-123" /> ``` ## ๐Ÿ”Œ Plugin System Extend functionality with custom plugins: ```typescript import { A2AClient, Plugin, PluginManager } from '@microsoft/a2achat-core'; // Define a custom plugin const analyticsPlugin: Plugin = { name: 'analytics', version: '1.0.0', description: 'Track chat events', install: (context) => { console.log('Analytics plugin installed'); }, hooks: { beforeMessageSend: async (message) => { console.log('Sending message:', message); return message; }, afterMessageReceive: async (message) => { console.log('Received message:', message); // Send to analytics service await trackEvent('message_received', { message }); return message; }, onError: async (error) => { console.error('Chat error:', error); // Send to error tracking service await trackError(error); }, }, }; // Use with A2AClient const client = new A2AClient({ agentCard: 'https://api.example.com', auth: { type: 'bearer', token: 'token' }, }); const pluginManager = new PluginManager(client); pluginManager.register(analyticsPlugin); ``` ### Built-in Plugins #### Analytics Plugin ```typescript import { AnalyticsPlugin } from '@microsoft/a2achat-core'; const analyticsPlugin = new AnalyticsPlugin({ trackEvent: (name, data) => { // Send to your analytics service analytics.track(name, data); }, }); ``` #### Logger Plugin ```typescript import { LoggerPlugin } from '@microsoft/a2achat-core'; const loggerPlugin = new LoggerPlugin({ level: 'info', // 'debug' | 'info' | 'warn' | 'error' logger: console, // or custom logger }); ``` ### Plugin Hooks Available lifecycle hooks: - `beforeRequest` - Modify requests before sending - `afterResponse` - Process responses after receiving - `beforeMessageSend` - Transform messages before sending - `afterMessageReceive` - Process messages after receiving - `onTaskCreated` - Handle task creation events - `onTaskCompleted` - Handle task completion events - `onTaskFailed` - Handle task failure events - `onError` - Handle error events - `onStart` - Handle connection start events - `onStop` - Handle connection stop events ## ๐Ÿ“Š Bundle Size The library is optimized for small bundle size: - **Core Library**: ~45KB (gzipped, excluding React) - **React Components**: ~5KB additional (gzipped) - **Styles**: ~5KB (gzipped) - **Total**: ~50-55KB with all features enabled React is a peer dependency and not included in the bundle. ## ๐ŸŒ Browser Support - Chrome/Edge 90+ - Firefox 88+ - Safari 14+ - Mobile browsers (iOS Safari 14+, Chrome Android 90+) Requires support for: - ES2020+ - Server-Sent Events (SSE) - IndexedDB (for client-side storage) - Web Workers (optional, for background tasks) ## ๐Ÿค Contributing Contributions are welcome! Please read our contributing guidelines before submitting PRs. ### Code Quality Standards - **TypeScript**: Strict mode enabled, no `any` types - **Testing**: Comprehensive test coverage with behavior-driven tests - Lines: 70% - Functions: 85% - Branches: 70% - Statements: 70% - **Formatting**: Prettier enforced via pre-commit hooks - **Linting**: ESLint rules must pass - **Type Safety**: No `@ts-ignore` without justification ### Development Workflow 1. Fork the repository 2. Create a feature branch: `git checkout -b feature/my-feature` 3. Make your changes with tests 4. Run quality checks: `pnpm typecheck && pnpm lint && pnpm test` 5. Commit your changes: `git commit -m "feat: add my feature"` 6. Push to your fork: `git push origin feature/my-feature` 7. Create a Pull Request ### CI/CD All PRs are automatically checked for: - TypeScript type errors - Prettier formatting - ESLint violations - Test failures - Build errors - Bundle size regression ## ๐Ÿ“š Additional Resources - [Core Package Documentation](./packages/a2a-core/README.md) - [Iframe App Documentation](./apps/iframe-app/README.md) - [Development Guide](./DEVELOPMENT.md) - [Architecture Documentation](./docs/) - [API Testing Findings](./docs/api-testing-findings.md) - [OBO Authentication Guide](./docs/OBO_AUTHENTICATION.md) ## ๐Ÿ”’ Security For security issues, please see [SECURITY.md](./SECURITY.md) for reporting guidelines. ## ๐Ÿ“ License MIT License - see [LICENSE.md](./LICENSE.md) for details --- Built with โค๏ธ by the A2A Chat team