Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 161 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,161 @@
# webagent
Embeddable GenAI-powered web chat widget with client-side agent loop, tool calling, WebMCP support, and Cloudflare Workers backend
# @vibetechnologies/webagent

Embeddable GenAI-powered web chat widget with client-side agent loop, tool calling, WebMCP support, and Cloudflare Workers backend.

[![CI](https://github.com/VibeTechnologies/webagent/actions/workflows/ci.yml/badge.svg)](https://github.com/VibeTechnologies/webagent/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/@vibetechnologies/webagent)](https://www.npmjs.com/package/@vibetechnologies/webagent)

## Features

- 🤖 Client-side AI agent loop (Vercel AI SDK)
- 🔧 5 built-in tools: web_fetch, skill, todo, send_email, escalate_to_human
- 📚 TF-IDF knowledge base search
- 💾 Session persistence (IndexedDB / localStorage)
- 🌐 WebMCP support (Chrome 146+) — provider + consumer
- 🎨 Shadow DOM isolation — works on any website
- ☁️ Cloudflare Workers backend (D1, KV, R2, Queues)
- 🔑 Hybrid API keys: BYOK + managed

## Quick Start

### CDN (Recommended)

```html
<script src="https://unpkg.com/@vibetechnologies/webagent/dist/webagent.min.js"></script>
<script>
WebAgent.init({
apiBase: 'https://your-worker.workers.dev',
apiKey: 'wa_your_managed_key',
welcomeMessage: 'Hi! How can I help you today?',
});
</script>
```

### npm

```bash
npm install @vibetechnologies/webagent
```

```typescript
import { WebAgent } from '@vibetechnologies/webagent';

const agent = WebAgent.init({
apiBase: 'https://your-worker.workers.dev',
apiKey: 'wa_your_managed_key',
welcomeMessage: 'Hi! How can I help?',
theme: 'dark',
position: 'bottom-right',
persistence: 'indexeddb',
sessionTtlDays: 7,
});

// Later: agent.destroy();
```

## Configuration

| Option | Type | Default | Description |
|---|---|---|---|
| `apiBase` | `string` | *required* | Backend worker URL |
| `apiKey` | `string` | `undefined` | API key (BYOK `sk-...` or managed `wa_...`) |
| `systemPrompt` | `string` | `'You are a helpful support agent.'` | System prompt |
| `skills` | `Skill[]` | `[]` | API skills for tool calling |
| `knowledgeBaseUrl` | `string` | `undefined` | URL to knowledge base JSON |
| `theme` | `'light' \| 'dark' \| 'auto' \| ThemeConfig` | `'light'` | Theme |
| `position` | `'bottom-right' \| 'bottom-left'` | `'bottom-right'` | FAB position |
| `welcomeMessage` | `string` | `undefined` | Initial greeting |
| `persistence` | `'indexeddb' \| 'localStorage' \| 'none'` | `'indexeddb'` | Session storage |
| `maxSteps` | `number` | `10` | Max tool-calling steps |
| `model` | `string` | `'gpt-4o-mini'` | LLM model name |
| `supportEmail` | `string` | `'support@example.com'` | Escalation recipient |
| `sessionTtlDays` | `number` | `7` | Session TTL in days |
| `onEscalation` | `(ticket) => void` | `undefined` | Escalation callback |
| `onMessage` | `(message) => void` | `undefined` | Message callback |

## Skills

See the [Skill Authoring Guide](docs/skills.md) for full documentation on creating and registering API skills.

## Architecture

```
┌─────────────────────────────┐
│ Host Website │
│ ┌────────────────────────┐ │
│ │ Shadow DOM │ │
│ │ ┌──────────────────┐ │ │
│ │ │ Chat Widget UI │ │ │
│ │ │ (Preact) │ │ │
│ │ └────────┬─────────┘ │ │
│ │ │ │ │
│ │ ┌────────▼─────────┐ │ │
│ │ │ Agent Loop │ │ │
│ │ │ (Vercel AI SDK) │ │ │
│ │ │ ┌─────────────┐ │ │ │
│ │ │ │ Tools │ │ │ │
│ │ │ │ • web_fetch │ │ │ │
│ │ │ │ • skill │ │ │ │
│ │ │ │ • todo │ │ │ │
│ │ │ │ • send_email │ │ │ │
│ │ │ │ • escalate │ │ │ │
│ │ │ └─────────────┘ │ │ │
│ │ └────────┬─────────┘ │ │
│ └───────────┼────────────┘ │
└──────────────┼──────────────┘
│ HTTPS
┌──────────────▼──────────────┐
│ Cloudflare Workers │
│ ┌─────────┐ ┌───────────┐ │
│ │ LLM │ │ Fetch │ │
│ │ Proxy │ │ Proxy │ │
│ └─────────┘ └───────────┘ │
│ ┌─────────┐ ┌───────────┐ │
│ │ Email │ │ Escalate │ │
│ │ Queue │ │ Tickets │ │
│ └─────────┘ └───────────┘ │
│ ┌─────────┐ ┌───────────┐ │
│ │ KB (R2) │ │ Admin │ │
│ └─────────┘ └───────────┘ │
│ D1 · KV · R2 · Queues │
└──────────────────────────────┘
```

## WebMCP Support

The widget supports the [WebMCP](https://developer.chrome.com/blog/webmcp-epp) standard (Chrome 146+):

### As Provider
Skills registered with the widget are automatically exposed via `navigator.modelContext.registerTool()`, making them available to browser-level AI agents.

### As Consumer
The widget can discover and use tools registered by the host page or other extensions via the WebMCP API.

### Declarative Forms
```html
<form toolname="search-products" tooldescription="Search the product catalog">
<input name="query" toolparamdescription="Search query" />
<button type="submit">Search</button>
</form>
```

## Packages

| Package | Description |
|---|---|
| `@vibetechnologies/webagent` | Client-side chat widget |
| `@vibetechnologies/webagent-backend` | Cloudflare Workers backend |

## Development

```bash
pnpm install
pnpm typecheck # Type-check all packages
pnpm build # Build all packages
pnpm test # Run tests
pnpm dev # Dev mode (all packages)
```

## License

MIT
183 changes: 183 additions & 0 deletions docs/deploy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# Deployment Guide

## Prerequisites

- [Node.js 22+](https://nodejs.org/)
- [pnpm 9+](https://pnpm.io/)
- [Cloudflare account](https://dash.cloudflare.com/)
- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/)

## Backend Deployment

### 1. Create Cloudflare Resources

```bash
# Login to Cloudflare
npx wrangler login

# Create D1 database
npx wrangler d1 create webagent-db

# Create KV namespace
npx wrangler kv namespace create KV

# Create R2 bucket
npx wrangler r2 bucket create webagent-kb

# Create Queue
npx wrangler queues create webagent-emails
```

### 2. Update wrangler.toml

Update `packages/backend/wrangler.toml` with the IDs from step 1:

```toml
[[d1_databases]]
binding = "DB"
database_name = "webagent-db"
database_id = "YOUR_D1_DATABASE_ID"

[[kv_namespaces]]
binding = "KV"
id = "YOUR_KV_NAMESPACE_ID"
```

### 3. Set Secrets

```bash
cd packages/backend

# Admin secret for API key management
npx wrangler secret put ADMIN_SECRET

# Resend API key for email delivery
npx wrangler secret put RESEND_API_KEY
```

### 4. Run Migrations

```bash
npx wrangler d1 migrations apply webagent-db
```

### 5. Deploy

```bash
pnpm --filter @vibetechnologies/webagent-backend deploy
```

## Widget Publishing

### npm

```bash
cd packages/widget
pnpm build
npm publish --access public
```

### CDN

After publishing to npm, the widget is available via:
- unpkg: `https://unpkg.com/@vibetechnologies/webagent/dist/webagent.min.js`
- jsDelivr: `https://cdn.jsdelivr.net/npm/@vibetechnologies/webagent/dist/webagent.min.js`

## Customer API Key Setup

### Create a managed key

```bash
curl -X POST https://your-worker.workers.dev/api/admin/keys \
-H "Content-Type: application/json" \
-H "X-Admin-Secret: YOUR_ADMIN_SECRET" \
-d '{
"customerId": "customer-123",
"provider": "openai",
"providerApiKey": "sk-..."
}'
```

Response: `{ "success": true, "customerKey": "wa_abc123...", "customerId": "customer-123" }`

### BYOK (Bring Your Own Key)

Customers can pass their own OpenAI/Anthropic key directly:

```html
<script>
WebAgent.init({
apiBase: 'https://your-worker.workers.dev',
apiKey: 'sk-...', // Their own OpenAI key
});
</script>
```

## Knowledge Base Setup

### Upload knowledge base chunks

```bash
curl -X PUT https://your-worker.workers.dev/api/kb/my-docs \
-H "Content-Type: application/json" \
-H "X-Admin-Secret: YOUR_ADMIN_SECRET" \
-d '[
{
"id": "getting-started",
"title": "Getting Started",
"content": "Welcome to our product...",
"keywords": ["setup", "install", "start"]
}
]'
```

### Configure widget to use KB

```html
<script>
WebAgent.init({
apiBase: 'https://your-worker.workers.dev',
apiKey: 'wa_xxx',
knowledgeBaseUrl: 'https://your-worker.workers.dev/api/kb/my-docs',
});
</script>
```

## Environment Variables

| Variable | Required | Description |
|---|---|---|
| `ADMIN_SECRET` | Yes | Secret for admin API endpoints |
| `RESEND_API_KEY` | Yes | [Resend](https://resend.com) API key for email |

## Cloudflare Free Tier Limits

| Resource | Limit |
|---|---|
| Workers requests | 100,000/day |
| D1 reads | 5,000,000/day |
| D1 writes | 100,000/day |
| D1 storage | 5 GB |
| KV reads | 100,000/day |
| KV writes | 1,000/day |
| R2 storage | 10 GB |
| R2 reads | 10,000,000/month |
| Queues messages | 1,000,000/month |

## CI/CD

The repository includes GitHub Actions workflows:

- **CI** (`.github/workflows/ci.yml`): Runs on PRs — typecheck, lint, test, build
- **Publish** (`.github/workflows/publish.yml`): Publishes to npm on GitHub Release
- **Deploy** (`.github/workflows/deploy.yml`): Deploys backend on push to main

### Setting up CI/CD secrets

In your GitHub repo settings → Secrets:

| Secret | Purpose |
|---|---|
| `NPM_TOKEN` | npm publish token |
| `CLOUDFLARE_API_TOKEN` | Wrangler deploy token |
| `CLOUDFLARE_ACCOUNT_ID` | Your Cloudflare account ID |
Loading
Loading