@wavespec/adapter-openai-chatkit
v0.1.0
Published
OpenAI ChatKit adapter for WaveSpec
Maintainers
Readme
@wavespec/adapter-openai-chatkit
OpenAI ChatKit Web Component adapter for WaveSpec testing framework.
Overview
This adapter integrates OpenAI's @openai/chatkit-react Web Component into WaveSpec's testing framework. Unlike other OpenAI adapters that wrap API clients, ChatKit is a UI component that requires DOM instantiation and communicates via CustomEvents.
Architecture
Core Components
- WebComponentLifecycleManager: Manages
<openai-chatkit>element lifecycle - EventBridge: Translates DOM CustomEvents to WaveSpec events
- ConfigurationTranslator: Converts between WaveSpec SDKConfig and ChatKitOptions
- WidgetNormalizer: Extracts and validates widget data
- BackendProtocolHelpers: Testing utilities for backend integration
- MockBackend: Mock server for testing ChatKit backend protocol
Key Features
- ✅ Web Component testing in Node.js (jsdom)
- ✅ Event-driven streaming support (real-time event observation)
- ✅ DOM CustomEvent collection and translation
- ✅ Widget system support (25+ component types)
- ✅ Backend protocol mocking
- ✅ File upload testing (two-phase and direct strategies)
- ✅ React integration utilities
Installation
pnpm add @wavespec/adapter-openai-chatkitSecurity Model
ChatKit uses a secure proxy pattern. Your OpenAI API key should NEVER be exposed to clients.
Critical Requirements
- Configure Domain Allowlist - Restrict which domains can use your ChatKit integration in the OpenAI Platform
- Implement User Authentication - Verify user identity before creating session tokens in your backend
- Protect API Keys - Store API keys in server-side environment variables only
- Review Security Guide - Read docs/security.md before deploying to production
Quick Security Check
- Is your API key in client-side code? INSECURE
- Is your domain allowlist set to
*? INSECURE - Does your backend verify users before creating sessions? SECURE
Secure Architecture
Browser Your Backend OpenAI API
| | |
| Domain Key + | API Key + |
| Session Token | Session Token |
| | |
+--------HTTPS-------> (Auth Check) |
+-------HTTPS-------->See Security Guide for complete documentation and Secure Examples for working code.
Table of Contents
- Overview
- Architecture
- Installation
- Security Model
- Quick Start
- SDK Integration Guide
- Backend Integration
- Operations
- Events
- Quick Start with Templates
- Documentation
Quick Start
WaveSpec Testing
import { OpenAIChatKitAdapter } from '@wavespec/adapter-openai-chatkit';
// Configure adapter
const config = {
type: 'openai-chatkit',
api: {
// Custom backend configuration (url + domainKey)
url: 'http://localhost:3000/chatkit',
domainKey: 'dk_test_123'
},
theme: 'light',
composer: { placeholder: 'Ask me anything...' }
};
// Create adapter instance
const adapter = new OpenAIChatKitAdapter();
// Connect
await adapter.connect(config, context);
// Run operations
const result = await adapter.run({
operation: 'send_message',
params: { text: 'Hello!' }
}, context);
// Disconnect
await adapter.disconnect();Event-Driven Streaming
Stream events in real-time during operation execution:
// Use streamEvents() for real-time event observation
const generator = adapter.streamEvents({
operation: 'send_message',
params: { text: 'Hello!' }
}, context);
// Yield events as they occur
for await (const event of generator) {
console.log('Event:', event.type, event.timestamp);
if (event.type === 'response_start') {
console.log('Response started');
}
}
// Get final result after streaming completes
const finalIteration = await generator.next();
if (finalIteration.done) {
const result = finalIteration.value;
console.log('Result:', result);
}See Streaming Guide for complete documentation.
Frontend Integration
React Example
import React from 'react';
import { ChatKit, useChatKit } from '@openai/chatkit-react';
import type { ChatKitOptions } from '@openai/chatkit';
export function MyChat() {
const { control } = useChatKit({
api: {
url: 'http://localhost:3000/chatkit',
domainKey: 'dk_your_domain_key'
},
onError: (event) => console.error('ChatKit error:', event.error),
onThreadChange: (event) => console.log('Thread changed:', event.threadId),
onResponseEnd: () => console.log('Response complete')
} satisfies ChatKitOptions);
return (
<div>
<button onClick={() => control.sendUserMessage({ text: 'Hello!' })}>
Send Message
</button>
<button onClick={() => control.setThreadId(null)}>
New Thread
</button>
<ChatKit control={control} className="h-[600px]" />
</div>
);
}Vanilla JavaScript Example
<openai-chatkit id="chatkit"></openai-chatkit>
<script type="module">
const chatkit = document.getElementById('chatkit');
// Configure
await chatkit.setOptions({
api: {
url: 'http://localhost:3000/chatkit',
domainKey: 'dk_your_domain_key'
},
theme: 'light'
});
// Listen for events
chatkit.addEventListener('chatkit.ready', () => {
console.log('ChatKit ready!');
});
chatkit.addEventListener('chatkit.error', (event) => {
console.error('Error:', event.detail.error);
});
// Send message
await chatkit.sendUserMessage({ text: 'Hello!' });
</script>See Frontend Integration Guide for complete documentation and examples.
SDK Integration Guide
ChatKit requires integration with both frontend and backend components. Here are quick examples to get you started:
Frontend Integration (React)
Quick React component example:
import { ChatKit } from '@openai/chatkit-react';
function App() {
return (
<ChatKit
api={{
getClientSecret: async () => {
// Call your backend to get a session token
const res = await fetch('/api/chatkit/session');
const { client_secret } = await res.json();
return client_secret;
}
}}
theme="light"
startScreen={{
greeting: "Hello! How can I help you today?",
prompts: ["Tell me a joke", "What can you do?"]
}}
/>
);
}Backend Integration (Express)
Quick backend example for session creation:
import express from 'express';
const app = express();
app.post('/api/chatkit/session', async (req, res) => {
const response = await fetch('https://api.openai.com/v1/chatkit/sessions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'OpenAI-Beta': 'chatkit_beta=v1',
'Content-Type': 'application/json',
},
body: JSON.stringify({
workflow: { id: process.env.CHATKIT_WORKFLOW_ID },
user: req.body.user || 'anonymous'
})
});
const data = await response.json();
res.json({ client_secret: data.client_secret });
});
app.listen(3000);Backend Integration (Next.js)
Quick Next.js API route example:
// app/api/chatkit/session/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const body = await request.json();
const response = await fetch('https://api.openai.com/v1/chatkit/sessions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'OpenAI-Beta': 'chatkit_beta=v1',
'Content-Type': 'application/json',
},
body: JSON.stringify({
workflow: { id: process.env.CHATKIT_WORKFLOW_ID },
user: body.user || 'anonymous'
})
});
const data = await response.json();
return NextResponse.json({ client_secret: data.client_secret });
}Complete SDK Documentation
For comprehensive SDK integration including TypeScript types, error handling, advanced patterns, and testing:
CLI Discovery Commands
Quickly access examples and documentation via CLI:
# View SDK integration details
harness sdk openai-chatkit
# Frontend examples
harness example openai-chatkit:with-widgets
# Backend examples
harness example openai-chatkit:with-backend
# Interactive tutorial
harness tutorial openai-chatkit
# List all templates
harness templates openai-chatkitBackend Integration
ChatKit requires a backend server to create sessions and handle authentication. You can build your backend in TypeScript using direct API calls - no Python required!
Quick Example
// Express backend for ChatKit
app.post('/api/chatkit/session', async (req, res) => {
const response = await fetch('https://api.openai.com/v1/chatkit/sessions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'OpenAI-Beta': 'chatkit_beta=v1',
'Content-Type': 'application/json',
},
body: JSON.stringify({
workflow: { id: process.env.CHATKIT_WORKFLOW_ID },
user: 'user-id-here',
}),
});
const { client_secret } = await response.json();
res.json({ client_secret });
});Testing Support
For testing, use the built-in mock server:
import { BackendProtocolHelpers } from '@wavespec/adapter-openai-chatkit';
const server = BackendProtocolHelpers.createMockServer({
port: 3000,
domainKey: 'dk_test_123',
handlers: {
'message': async (req) => [
{ type: 'response.start', data: {} },
{ type: 'response.text', data: { text: 'Hello!' } },
{ type: 'response.end', data: {} }
]
}
});
await server.start();Learn More
- Express Example - Full working Express server
- Next.js Example - Next.js API route example
- FastAPI Example - Python backend option
- Secure Integration Guide - Production deployment patterns
For comprehensive backend documentation including session management, SSE streaming, and production patterns, see the Secure Integration Examples.
VCR Testing
The ChatKit adapter supports VCR cassette recording and replay through the harness CLI. See harness VCR documentation for usage.
Operations
| Operation | Description |
|-----------|-------------|
| set_options | Configure ChatKit instance |
| focus_composer | Focus the message input |
| set_thread | Switch to a thread |
| send_message | Send a user message |
| set_composer | Set draft without sending |
| fetch_updates | Manually fetch updates |
| send_action | Send custom widget action |
Events
The adapter translates ChatKit DOM CustomEvents to WaveSpec lifecycle events:
| ChatKit Event | WaveSpec Event |
|--------------|----------------|
| chatkit.ready | component_ready |
| chatkit.error | error |
| chatkit.response.start | response_start |
| chatkit.response.end | response_end |
| chatkit.thread.change | thread_change |
| chatkit.thread.load.start | thread_load_start |
| chatkit.thread.load.end | thread_load_end |
| chatkit.log | diagnostic |
Quick Start with Templates
Get started quickly using pre-built test templates with the WaveSpec harness:
# List available templates
harness templates chatkit
# Generate an example test
harness example chatkit:init
# Run the test
harness run test.yamlAvailable Templates
init- Minimal hosted integration using OpenAI-hosted backendbasic- Custom backend with domain key authenticationwith-widgets- Widget rendering and interaction testingwith-backend- Full backend integration with file uploads
Each template provides a complete, runnable example that you can customize for your needs.
Documentation
Comprehensive guides to help you get the most out of ChatKit:
Security (Read This First!)
- Security Guide - Comprehensive security documentation covering secure proxy pattern, domain allowlist, token refresh, and production deployment
- Troubleshooting Guide - Common security issues and solutions with debugging tips
- Secure Backend Examples - Working backend implementations (Express, Next.js, FastAPI)
Getting Started
- Getting Started Guide - Complete setup guide with decision tree for choosing hosted vs custom backend, 5-minute quickstart, and troubleshooting
SDK Integration
- SDK Integration Guide - Complete guide for using the adapter programmatically from TypeScript/JavaScript, including API reference, configuration examples, error handling, and testing patterns
Frontend Integration
- Frontend Integration Guide - Complete guide for React hooks, event callbacks, and vanilla JS integration
- React Integration Example - Complete React component with hooks and event handlers
- Vanilla JS Example - Browser-based example without build tools
Configuration & Operations
- Configuration Reference - Complete reference for all configuration options including API config, theme customization, UI configuration, event callbacks, and internationalization (100+ locales)
- Operations Guide - Detailed documentation for all 7 adapter operations with examples and error handling
Advanced Topics
- Widget Testing Guide - Comprehensive guide to all 25+ widget types with examples, validation rules, and action handling
- Backend Integration - See the Backend Integration section above for TypeScript examples and testing support. For production patterns, see Secure Integration Examples
Examples
- Examples Directory - Five complete, runnable TypeScript examples:
basic-chat.ts- Simple message sending and response handlingwidget-interaction.ts- Widget rendering and action triggersfile-upload.ts- File attachment handling (two-phase and direct)multi-thread.ts- Thread creation and managementerror-handling.ts- Error recovery patterns and retry logic
Run any example with: tsx docs/examples/basic-chat.ts
Development Status
🚧 In Development - Phase 1 implementation in progress
License
MIT
