bunnyquery 1.0.10 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -60
- package/bunnyquery.css +417 -56
- package/bunnyquery.js +969 -191
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# BunnyQuery Client
|
|
2
2
|
|
|
3
|
-
An embeddable, zero-dependency AI chat widget that connects to a [BunnyQuery](https://www.
|
|
3
|
+
An embeddable, zero-dependency AI chat widget that connects to a [BunnyQuery](https://www.bunnyquery.com) project. Drop two `<script>` tags into any HTML page and your users get a fully featured chat UI backed by Claude or OpenAI — with login, password recovery, account settings, file attachments, persistent history, and MCP-based authentication.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,10 +8,13 @@ An embeddable, zero-dependency AI chat widget that connects to a [BunnyQuery](ht
|
|
|
8
8
|
|
|
9
9
|
- **Plug-and-play embed** — one `<script>` tag, one `BunnyQuery.init()` call.
|
|
10
10
|
- **Claude & OpenAI support** — the AI platform is selected in your project settings; the embed reads it automatically.
|
|
11
|
-
- **
|
|
12
|
-
-
|
|
11
|
+
- **Built-in account UI**
|
|
12
|
+
- Login form (email/username + password).
|
|
13
|
+
- **Forgot password** flow — request a code, set a new password without leaving the embed.
|
|
14
|
+
- **Account settings** dialog — change email (with verification), change password, see verification status.
|
|
15
|
+
- **MCP OAuth** — authentication uses the [Model Context Protocol](https://modelcontextprotocol.io/) OAuth flow (RFC 7591 + PKCE). API keys never reach the browser. After a host login the embed silently exchanges the Skapi session for an MCP access token.
|
|
13
16
|
- **Persistent history** — previous messages are loaded from the server on startup and paginated as the user scrolls up.
|
|
14
|
-
- **File attachments** —
|
|
17
|
+
- **File attachments** — files are uploaded to the Skapi host-file store and linked into the message as temporary CDN URLs.
|
|
15
18
|
- **Clear / logout** — modal-confirmed actions that respect in-flight requests.
|
|
16
19
|
- **Responsive** — collapses to full-screen on narrow viewports.
|
|
17
20
|
- **Read-only mode** — the attach button is hidden automatically when `freeze_database` is set in the project settings.
|
|
@@ -22,19 +25,9 @@ An embeddable, zero-dependency AI chat widget that connects to a [BunnyQuery](ht
|
|
|
22
25
|
|
|
23
26
|
### 1. Get your project ID
|
|
24
27
|
|
|
25
|
-
Sign in at [www.bunnyquery.com](https://www.bunnyquery.com)
|
|
28
|
+
Sign in at [www.bunnyquery.com](https://www.bunnyquery.com), open your project, and copy the **Project ID** from the project settings page.
|
|
26
29
|
|
|
27
|
-
### 2.
|
|
28
|
-
|
|
29
|
-
```html
|
|
30
|
-
<script type="module">
|
|
31
|
-
const PROJECT_ID = 'your-project-id-here'; // ← paste your ID here
|
|
32
|
-
let skapi = new Skapi(PROJECT_ID, { autoLogin: true });
|
|
33
|
-
const bqClient = await BunnyQuery.init(skapi, 'bq-client');
|
|
34
|
-
</script>
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Embedding in Your Own Page
|
|
30
|
+
### 2. Embed it
|
|
38
31
|
|
|
39
32
|
```html
|
|
40
33
|
<!DOCTYPE html>
|
|
@@ -43,9 +36,9 @@ Sign in at [www.bunnyquery.com](https://www.bunnyquery.com) and open your projec
|
|
|
43
36
|
<meta charset="UTF-8" />
|
|
44
37
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
45
38
|
<!-- 1. Skapi SDK -->
|
|
46
|
-
<script src="https://cdn.jsdelivr.net/npm/skapi-js@
|
|
39
|
+
<script src="https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js"></script>
|
|
47
40
|
<!-- 2. BunnyQuery widget (CSS is injected automatically) -->
|
|
48
|
-
<script src="bunnyquery.js"></script>
|
|
41
|
+
<script src="https://cdn.jsdelivr.net/npm/bunnyquery@latest/bunnyquery.js"></script>
|
|
49
42
|
</head>
|
|
50
43
|
<body>
|
|
51
44
|
<!-- 3. Mount point -->
|
|
@@ -59,63 +52,72 @@ Sign in at [www.bunnyquery.com](https://www.bunnyquery.com) and open your projec
|
|
|
59
52
|
</html>
|
|
60
53
|
```
|
|
61
54
|
|
|
62
|
-
The widget
|
|
63
|
-
|
|
64
|
-
```js
|
|
65
|
-
BunnyQuery.STYLESHEET_URL = 'https://your-cdn.example.com/bunnyquery.css';
|
|
66
|
-
await BunnyQuery.init(skapi, 'bq-client');
|
|
67
|
-
```
|
|
55
|
+
That's it. The widget renders the chat if the user is signed in, otherwise it shows the login form.
|
|
68
56
|
|
|
69
57
|
---
|
|
70
58
|
|
|
71
59
|
## API Reference
|
|
72
60
|
|
|
73
|
-
### `BunnyQuery.init(skapi, elementId)` → `Promise<BunnyQuery>`
|
|
61
|
+
### `BunnyQuery.init(skapi, elementId, dev?)` → `Promise<BunnyQuery>`
|
|
74
62
|
|
|
75
63
|
Initialises the widget and returns the instance.
|
|
76
64
|
|
|
77
|
-
| Parameter
|
|
78
|
-
|
|
79
|
-
| `skapi`
|
|
80
|
-
| `elementId` | `string \| HTMLElement`
|
|
65
|
+
| Parameter | Type | Description |
|
|
66
|
+
| ----------- | -------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
67
|
+
| `skapi` | `Skapi` | An initialised `Skapi` instance. |
|
|
68
|
+
| `elementId` | `string \| HTMLElement` | The id string or DOM element to mount the widget into. |
|
|
69
|
+
| `dev` | `boolean` *(optional)* | When `true`, routes every MCP call to the dev MCP host (`MCP_DEV_BASE_URL`). Omit or pass `false` in production. |
|
|
81
70
|
|
|
82
|
-
### Static configuration
|
|
71
|
+
### Static configuration
|
|
83
72
|
|
|
84
|
-
Set these **before** calling `init()
|
|
73
|
+
Set these **before** calling `init()`:
|
|
85
74
|
|
|
86
|
-
| Property
|
|
87
|
-
|
|
88
|
-
| `BunnyQuery.MCP_BASE_URL`
|
|
89
|
-
| `BunnyQuery.STYLESHEET_URL
|
|
75
|
+
| Property | Default | Description |
|
|
76
|
+
| -------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
77
|
+
| `BunnyQuery.MCP_BASE_URL` | `https://mcp.broadwayinc.computer` | Production MCP OAuth server base URL. Override to target a different MCP host. Automatically swapped to the dev host when `init(..., true)` is used. |
|
|
78
|
+
| `BunnyQuery.STYLESHEET_URL`| *(auto-resolved)* | Override the CSS file URL when auto-resolution fails (e.g. CDN-hosted scripts behind a custom domain). |
|
|
90
79
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
## Project Structure
|
|
80
|
+
The widget auto-injects `bunnyquery.css` from the same directory as `bunnyquery.js`. If you bundle the script yourself or serve it from a path that breaks auto-resolution:
|
|
94
81
|
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
├── bunnyquery.js # Widget source (vanilla JS, no build step required)
|
|
99
|
-
├── bunnyquery.css # Widget styles
|
|
100
|
-
└── package.json # Dev server only (basic-node-server)
|
|
82
|
+
```js
|
|
83
|
+
BunnyQuery.STYLESHEET_URL = 'https://your-cdn.example.com/bunnyquery.css';
|
|
84
|
+
await BunnyQuery.init(skapi, 'bq-client');
|
|
101
85
|
```
|
|
102
86
|
|
|
103
87
|
---
|
|
104
88
|
|
|
105
|
-
##
|
|
89
|
+
## Built-in Account UI
|
|
106
90
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
91
|
+
### Login
|
|
92
|
+
|
|
93
|
+
Users who are not signed in see a username/password form. After a successful login the embed silently mints an MCP access token via `oauth.exchangeSession(skapi.session)` and switches to the chat view.
|
|
94
|
+
|
|
95
|
+
### Forgot password
|
|
96
|
+
|
|
97
|
+
A **Forgot password?** link sits under the login submit button and opens a two-step recovery flow inside the same overlay:
|
|
98
|
+
|
|
99
|
+
1. The user enters their email and presses **Send code** — calls `skapi.forgotPassword({ email })`.
|
|
100
|
+
2. The user enters the verification code from their inbox plus a new password (with confirmation), and presses **Reset password** — calls `skapi.resetPassword({ email, code, new_password })`.
|
|
101
|
+
|
|
102
|
+
On success the embed returns to the login form with the email pre-filled and a confirmation notice.
|
|
103
|
+
|
|
104
|
+
### Account settings
|
|
105
|
+
|
|
106
|
+
Once signed in, the chat header shows a **Settings** button between **Clear** and **Logout**. It opens a modal with two sections:
|
|
107
|
+
|
|
108
|
+
- **Email** — shows the current address with a *verified / unverified* badge.
|
|
109
|
+
- For unverified accounts (or right after a change) the user can press **Send code** (`skapi.verifyEmail()`), enter the received code, and press **Verify** (`skapi.verifyEmail({ code })`).
|
|
110
|
+
- Below that, **Change email** updates the address via `skapi.updateProfile({ email })`, marks it unverified, and re-opens the verify flow.
|
|
111
|
+
- **Password** — current / new / confirm fields with a client-side match check, calls `skapi.changePassword({ current_password, new_password })`.
|
|
112
|
+
- Hidden automatically for OpenID / social-login accounts (Cognito password change is not available).
|
|
111
113
|
|
|
112
114
|
---
|
|
113
115
|
|
|
114
116
|
## Customisation
|
|
115
117
|
|
|
116
|
-
###
|
|
118
|
+
### Sizing
|
|
117
119
|
|
|
118
|
-
The widget
|
|
120
|
+
The widget fills the element you mount it into. Control size and chrome with normal CSS:
|
|
119
121
|
|
|
120
122
|
```css
|
|
121
123
|
#bq-client {
|
|
@@ -129,15 +131,15 @@ The widget mounts inside the element you provide. Control its size via CSS on th
|
|
|
129
131
|
|
|
130
132
|
All colours are CSS custom properties scoped to `.bq-agent`:
|
|
131
133
|
|
|
132
|
-
| Variable
|
|
133
|
-
|
|
134
|
-
| `--bq-ink`
|
|
135
|
-
| `--bq-paper`
|
|
136
|
-
| `--bq-muted`
|
|
137
|
-
| `--bq-line`
|
|
138
|
-
| `--bq-hover-bg`
|
|
139
|
-
| `--bq-pink`
|
|
140
|
-
| `--bq-danger`
|
|
134
|
+
| Variable | Default | Usage |
|
|
135
|
+
| ----------------- | ---------- | -------------------- |
|
|
136
|
+
| `--bq-ink` | `#111` | Primary text |
|
|
137
|
+
| `--bq-paper` | `#fff` | Background |
|
|
138
|
+
| `--bq-muted` | `#666` | Secondary text |
|
|
139
|
+
| `--bq-line` | `#c8c8c8` | Borders |
|
|
140
|
+
| `--bq-hover-bg` | `#ebebeb` | Hover states |
|
|
141
|
+
| `--bq-pink` | `#c2185b` | Links |
|
|
142
|
+
| `--bq-danger` | `#c44` | Destructive actions |
|
|
141
143
|
|
|
142
144
|
Override them on a parent element:
|
|
143
145
|
|
|
@@ -151,6 +153,33 @@ Override them on a parent element:
|
|
|
151
153
|
|
|
152
154
|
---
|
|
153
155
|
|
|
156
|
+
## How It Works
|
|
157
|
+
|
|
158
|
+
1. **Skapi** handles user authentication and acts as the serverless backend (database, file storage, request queueing).
|
|
159
|
+
2. **MCP OAuth** — after login the embed exchanges the Skapi session for an MCP access token via `/oauth/session-exchange` (no browser redirect needed). The token is cached in `localStorage` and refreshed automatically on stale-token errors.
|
|
160
|
+
3. **AI requests** are made through `skapi.clientSecretRequest`, which keeps your Claude / OpenAI API key on the Skapi edge — it is never sent to the browser.
|
|
161
|
+
4. **History** is fetched with `skapi.clientSecretRequestHistory` and merged with the live message list. Pending (in-flight) requests are polled every 4 seconds until they resolve.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Project Structure
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
bunnyquery-client/
|
|
169
|
+
├── index.html # Example host page
|
|
170
|
+
├── bunnyquery.js # Widget source (vanilla JS, no build step)
|
|
171
|
+
├── bunnyquery.css # Widget styles (auto-injected)
|
|
172
|
+
└── package.json # Dev server only (basic-node-server)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Run locally:
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
npm run dev # serves the folder on http://localhost:3333
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
154
183
|
## Requirements
|
|
155
184
|
|
|
156
185
|
- A [Skapi](https://www.skapi.com) project with an AI agent configured (Claude or OpenAI).
|