bunnyquery 1.1.4 → 1.2.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 +112 -148
- package/bunnyquery.css +761 -952
- package/bunnyquery.js +3679 -2478
- package/package.json +22 -11
package/README.md
CHANGED
|
@@ -1,193 +1,157 @@
|
|
|
1
|
-
# BunnyQuery
|
|
1
|
+
# BunnyQuery
|
|
2
2
|
|
|
3
|
-
An embeddable,
|
|
3
|
+
An embeddable, dependency-free AI chat widget for [Skapi](https://www.skapi.com)-powered
|
|
4
|
+
projects. Drop it into any web page and your users get a full chat experience —
|
|
5
|
+
account login/signup, conversation history, file & folder uploads, and a settings
|
|
6
|
+
panel — all talking to your project's **BunnyQuery** AI agent.
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
BunnyQuery is a standalone vanilla-JS port of the BunnyQuery (www.bunnyquery.com) agent
|
|
9
|
+
chatbox. It ships as a single IIFE that exposes `window.BunnyQuery`, plus one
|
|
10
|
+
stylesheet. No build step, no framework, no npm install.
|
|
6
11
|
|
|
7
12
|
## Features
|
|
8
13
|
|
|
9
|
-
- **
|
|
10
|
-
|
|
11
|
-
- **
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- **
|
|
16
|
-
|
|
17
|
-
- **
|
|
18
|
-
|
|
19
|
-
- **
|
|
20
|
-
|
|
14
|
+
- **AI chat** against your project's configured agent (Claude or OpenAI under the
|
|
15
|
+
hood), with streaming-style "Thinking…" indicators and a background indexing queue.
|
|
16
|
+
- **Authentication** — email/password login, optional signup, password change,
|
|
17
|
+
email verification, account recovery, and "Sign in with Google".
|
|
18
|
+
- **Conversation history** — paginated, with "Fetching history…" indicators on
|
|
19
|
+
first load and on scroll-up.
|
|
20
|
+
- **Attachments** — drag-and-drop files and folders, per-file upload status
|
|
21
|
+
(uploading / failed / indexed), and overflow collapsing for large batches.
|
|
22
|
+
- **Settings panel** — in-place inside the chat: light/dark theme, account details,
|
|
23
|
+
newsletter subscription, clear history, and remove account.
|
|
24
|
+
- **Theming** — light and dark modes via CSS custom properties; the choice is
|
|
25
|
+
remembered in `localStorage` and falls back to the OS preference.
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
## Quick Start
|
|
27
|
+
## Requirements
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
- A BunnyQuery project (you need its **project ID**).
|
|
30
|
+
- The [`skapi-js`](https://www.npmjs.com/package/skapi-js) SDK loaded on the page.
|
|
31
|
+
- A mount element with an explicit height (the widget fills its container).
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
## Quick start
|
|
29
34
|
|
|
30
|
-
|
|
35
|
+
Add the two BunnyQuery files and the Skapi SDK, give it a sized container, then
|
|
36
|
+
call `BunnyQuery.init()`:
|
|
31
37
|
|
|
32
38
|
```html
|
|
33
39
|
<!DOCTYPE html>
|
|
34
40
|
<html lang="en">
|
|
35
41
|
<head>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
<meta charset="UTF-8" />
|
|
43
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
44
|
+
|
|
45
|
+
<!-- Skapi SDK + BunnyQuery -->
|
|
46
|
+
<script src="https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js"></script>
|
|
47
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bunnyquery@latest/bunnyquery.css" />
|
|
48
|
+
<script src="https://cdn.jsdelivr.net/npm/bunnyquery@latest/bunnyquery.js"></script>
|
|
42
49
|
</head>
|
|
43
|
-
<body>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
<body style="margin: 0">
|
|
51
|
+
<!-- The widget fills this element, so give it a height -->
|
|
52
|
+
<div id="chatbox" style="width: 100%; height: 100dvh"></div>
|
|
53
|
+
|
|
54
|
+
<script>
|
|
55
|
+
// 1. Create your Skapi instance
|
|
56
|
+
const skapi = new Skapi("<your-project-id>", { autoLogin: true });
|
|
57
|
+
|
|
58
|
+
// 2. Mount BunnyQuery into the container
|
|
59
|
+
BunnyQuery.init(skapi, "chatbox", {
|
|
60
|
+
theme: "light",
|
|
61
|
+
signup: true,
|
|
62
|
+
});
|
|
63
|
+
</script>
|
|
51
64
|
</body>
|
|
52
65
|
</html>
|
|
53
66
|
```
|
|
54
67
|
|
|
55
|
-
That's it
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## API Reference
|
|
60
|
-
|
|
61
|
-
### `BunnyQuery.init(skapi, elementId, dev?)` → `Promise<BunnyQuery>`
|
|
62
|
-
|
|
63
|
-
Initialises the widget and returns the instance.
|
|
64
|
-
|
|
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. |
|
|
70
|
-
|
|
71
|
-
### Static configuration
|
|
72
|
-
|
|
73
|
-
Set these **before** calling `init()`:
|
|
74
|
-
|
|
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). |
|
|
79
|
-
|
|
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:
|
|
81
|
-
|
|
82
|
-
```js
|
|
83
|
-
BunnyQuery.STYLESHEET_URL = 'https://your-cdn.example.com/bunnyquery.css';
|
|
84
|
-
await BunnyQuery.init(skapi, 'bq-client');
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## Built-in Account UI
|
|
90
|
-
|
|
91
|
-
### Login
|
|
68
|
+
That's it — BunnyQuery takes over the `#chatbox` element and renders the login or
|
|
69
|
+
chat view depending on the user's session.
|
|
92
70
|
|
|
93
|
-
|
|
71
|
+
## Files
|
|
94
72
|
|
|
95
|
-
|
|
73
|
+
| File | Purpose |
|
|
74
|
+
| --------------- | ------------------------------------------------------------- |
|
|
75
|
+
| `bunnyquery.js` | The widget. Exposes the global `window.BunnyQuery`. |
|
|
76
|
+
| `bunnyquery.css` | All styles, scoped under `.bq-agent` / `[data-bq-theme]`. |
|
|
96
77
|
|
|
97
|
-
|
|
78
|
+
Host them yourself (same origin recommended) or from a CDN.
|
|
98
79
|
|
|
99
|
-
|
|
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 })`.
|
|
80
|
+
## API
|
|
101
81
|
|
|
102
|
-
|
|
82
|
+
### `BunnyQuery.init(skapi, target, opts?)`
|
|
103
83
|
|
|
104
|
-
|
|
84
|
+
Mounts the widget. Returns the `BunnyQuery` object.
|
|
105
85
|
|
|
106
|
-
|
|
86
|
+
| Argument | Type | Description |
|
|
87
|
+
| -------- | --------------------- | ----------------------------------------------------------------- |
|
|
88
|
+
| `skapi` | `Skapi` | A constructed Skapi instance. **Required.** |
|
|
89
|
+
| `target` | `string \| Element` | The mount element, or the `id` of one. **Required.** |
|
|
90
|
+
| `opts` | `object` | Options (see below). Optional. |
|
|
107
91
|
|
|
108
|
-
|
|
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).
|
|
92
|
+
### Options
|
|
113
93
|
|
|
114
|
-
|
|
94
|
+
| Option | Type | Default | Description |
|
|
95
|
+
| ------------------------ | --------- | -------- | -------------------------------------------------------------------------------------------- |
|
|
96
|
+
| `theme` | `string` | `"light"`| Initial theme, `"light"` or `"dark"`. Overridden by a remembered choice or OS preference. |
|
|
97
|
+
| `signup` | `boolean` | `false` | Enable signup flows (and account remove/recover). When `false`, only existing users can log in. |
|
|
98
|
+
| `googleClientId` | `string` | `null` | Google OAuth client ID. Set this to show "Sign in with Google". |
|
|
99
|
+
| `googleClientSecretName` | `string` | `"ggl"` | The Skapi client-secret name holding your Google OAuth secret. |
|
|
100
|
+
| `signupConfirmationUrl` | `string` | `null` | Link target used in the signup confirmation email. Defaults to the current page URL. |
|
|
101
|
+
| `dev` | `boolean` | `false` | Use the development MCP host and `skapi.app` db-CDN host instead of production. |
|
|
102
|
+
| `mcpBaseUrl` | `string` | `null` | Override the MCP OAuth server base URL entirely (advanced). |
|
|
103
|
+
| `hostDomain` | `string` | `null` | db-CDN host for temporary file URLs. Defaults to `skapi.app` (dev) / `skapi.com` (prod). |
|
|
115
104
|
|
|
116
|
-
|
|
105
|
+
### Methods
|
|
117
106
|
|
|
118
|
-
|
|
107
|
+
The `BunnyQuery` global also exposes:
|
|
119
108
|
|
|
120
|
-
|
|
109
|
+
| Method | Description |
|
|
110
|
+
| -------------------- | ----------------------------------------------------------------- |
|
|
111
|
+
| `setTheme(theme)` | Apply `"light"` or `"dark"` and persist it. |
|
|
112
|
+
| `toggleTheme()` | Switch between light and dark. |
|
|
113
|
+
| `logout()` | Sign the current user out and return to the login view. |
|
|
114
|
+
| `version` | The widget version string. |
|
|
121
115
|
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
border: 1px solid #ccc;
|
|
127
|
-
}
|
|
116
|
+
```js
|
|
117
|
+
BunnyQuery.setTheme("dark");
|
|
118
|
+
BunnyQuery.toggleTheme();
|
|
119
|
+
BunnyQuery.logout();
|
|
128
120
|
```
|
|
129
121
|
|
|
130
|
-
|
|
122
|
+
> `init()` is idempotent — calling it twice logs a warning and returns the existing
|
|
123
|
+
> instance rather than re-mounting.
|
|
131
124
|
|
|
132
|
-
|
|
125
|
+
## Theming
|
|
133
126
|
|
|
134
|
-
|
|
135
|
-
|
|
|
136
|
-
|
|
137
|
-
|
|
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 |
|
|
143
|
-
|
|
144
|
-
Override them on a parent element:
|
|
127
|
+
BunnyQuery is themed with CSS custom properties (`--bq-*`) under a
|
|
128
|
+
`[data-bq-theme="light"|"dark"]` attribute that the widget sets on its own root.
|
|
129
|
+
To customize colors, override the variables in your own stylesheet **after**
|
|
130
|
+
`bunnyquery.css`, scoped to `.bq-agent`:
|
|
145
131
|
|
|
146
132
|
```css
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
--bq-pink: #7c3aed;
|
|
133
|
+
.bq-agent {
|
|
134
|
+
--bq-main: #ff4fa3;
|
|
135
|
+
--bq-ink: #111;
|
|
151
136
|
}
|
|
152
137
|
```
|
|
153
138
|
|
|
154
|
-
|
|
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
|
-
|
|
183
|
-
## Requirements
|
|
139
|
+
The active theme is saved to `localStorage`, so a returning user keeps their choice.
|
|
184
140
|
|
|
185
|
-
|
|
186
|
-
- A modern browser with `crypto.subtle`, `fetch`, and ES2020 support.
|
|
187
|
-
- Node.js 16+ (dev server only).
|
|
141
|
+
## OAuth & redirects
|
|
188
142
|
|
|
189
|
-
|
|
143
|
+
BunnyQuery connects to your AI agent through an MCP OAuth server
|
|
144
|
+
(`mcp.broadwayinc.computer` in production, `mcp-dev.broadwayinc.computer` when
|
|
145
|
+
`dev: true`). After authorization, the OAuth server redirects back to **the current
|
|
146
|
+
host page** — BunnyQuery reads the `?code=…&state=…` parameters, completes the
|
|
147
|
+
exchange, and cleans them from the URL automatically. No dedicated callback page is
|
|
148
|
+
needed; just make sure the page that hosts the widget is a stable, reachable URL.
|
|
190
149
|
|
|
191
|
-
##
|
|
150
|
+
## Notes
|
|
192
151
|
|
|
193
|
-
|
|
152
|
+
- The widget fills its mount element. Give that element a real height (e.g.
|
|
153
|
+
`height: 100dvh`) or it will collapse.
|
|
154
|
+
- File and folder uploads are stored in your Skapi project's database storage and
|
|
155
|
+
served from a temporary db-CDN URL (`hostDomain`); links in chat refresh on expiry.
|
|
156
|
+
- The agent shown in the header (`BunnyQuery · <project name>`) reflects the project
|
|
157
|
+
configured for your Skapi service.
|