@clivly/chat-widget 0.17.0 → 0.17.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/LICENSE +21 -0
- package/README.md +30 -13
- package/dist/browser-mount.cjs +415 -69
- package/dist/browser-mount.mjs +415 -69
- package/dist/browser.cjs +415 -69
- package/dist/browser.mjs +415 -69
- package/dist/index.cjs +415 -69
- package/dist/index.mjs +415 -69
- package/dist/widget.global.js +180 -21
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Clivly
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ transport; installing this package does not change how your server reports
|
|
|
8
8
|
liveness.
|
|
9
9
|
|
|
10
10
|
> **New here? Start with
|
|
11
|
-
> [Adding the chat widget](
|
|
11
|
+
> [Adding the chat widget](https://clivly.com/docs/guides/chat-widget)** — the
|
|
12
12
|
> canonical end-to-end guide (widget record, session route, embed, operator
|
|
13
13
|
> inbox). This README is the API-level reference for the package's entrypoints.
|
|
14
14
|
|
|
@@ -185,13 +185,17 @@ no identity at all.
|
|
|
185
185
|
|
|
186
186
|
The session is created when the visitor opens the launcher, not on page load —
|
|
187
187
|
otherwise every visitor who merely loaded a page would create an empty thread in
|
|
188
|
-
your inbox.
|
|
188
|
+
your inbox. For a visitor you have identified it starts on the launcher press
|
|
189
|
+
(and on hover or keyboard focus when this browser holds a thread to resume;
|
|
190
|
+
hover never starts a new thread), and the panel opens straight into the
|
|
191
|
+
conversation shell rather than flashing the form.
|
|
189
192
|
|
|
190
193
|
### This is not authentication
|
|
191
194
|
|
|
192
195
|
A seeded identity is self-reported: anyone can edit a prop in React devtools or
|
|
193
196
|
a `data-` attribute in the element inspector. It removes the typing, nothing
|
|
194
|
-
more.
|
|
197
|
+
more. An unverified email never claims an existing contact: if the address
|
|
198
|
+
already belongs to one, the chat stays unlinked from it.
|
|
195
199
|
|
|
196
200
|
To make the identity trustworthy, pass `resolveUser` to
|
|
197
201
|
`createChatSessionHandler` on your backend. It resolves the caller's real
|
|
@@ -200,7 +204,7 @@ contact verified:
|
|
|
200
204
|
|
|
201
205
|
```ts
|
|
202
206
|
createChatSessionHandler({
|
|
203
|
-
apiKey: process.env.
|
|
207
|
+
apiKey: process.env.CLIVLY_SECRET_KEY,
|
|
204
208
|
resolveUser: async (request) => {
|
|
205
209
|
const session = await auth.getSession(request);
|
|
206
210
|
return session ? { id: session.user.id, email: session.user.email, name: session.user.name } : null;
|
|
@@ -214,7 +218,8 @@ Use both together for a signed-in user: `defaultVisitor` removes the form,
|
|
|
214
218
|
## Placement and launcher
|
|
215
219
|
|
|
216
220
|
The widget floats in the bottom-right corner of the viewport, clear of the
|
|
217
|
-
device's safe-area insets. Below
|
|
221
|
+
device's safe-area insets. Below 30rem the open panel is a full-screen sheet and
|
|
222
|
+
the launcher hides while it is open. Below 48rem the launcher is a 48px icon-only
|
|
218
223
|
button, so it does not cover the host page's pagination or form controls; on
|
|
219
224
|
wider screens it is a pill with an icon and your `launcherLabel`. The label is
|
|
220
225
|
the button's accessible name either way, and `aria-expanded` reports whether
|
|
@@ -254,7 +259,7 @@ the panel is open.
|
|
|
254
259
|
|
|
255
260
|
The widget ships light and dark palettes and follows the host app by default.
|
|
256
261
|
For integration recipes (Tailwind, next-themes, a custom toggle) see
|
|
257
|
-
[the
|
|
262
|
+
[the chat widget guide](https://clivly.com/docs/guides/chat-widget).
|
|
258
263
|
|
|
259
264
|
### `theme`
|
|
260
265
|
|
|
@@ -375,9 +380,10 @@ on the server). The widget then:
|
|
|
375
380
|
|
|
376
381
|
- shows the server-written greeting, and every automated or AI message, with an
|
|
377
382
|
**Automated** / **AI assistant** badge (`message.automation` says which);
|
|
378
|
-
- offers the topics as
|
|
379
|
-
|
|
380
|
-
teammate's reply
|
|
383
|
+
- offers the topics as a compact strip docked above the message box (a
|
|
384
|
+
sideways-scrolling row on narrow or touch screens) while `support.state` is
|
|
385
|
+
`"automated"`, and hides them after a handoff or a teammate's reply
|
|
386
|
+
(`support.state` server event);
|
|
381
387
|
- shows *The AI assistant is looking for an answer…* while an
|
|
382
388
|
`assistant.status` event says `thinking`.
|
|
383
389
|
|
|
@@ -386,6 +392,11 @@ transport** opts in with the optional `ChatTransportConnection.selectTopic()`;
|
|
|
386
392
|
without it, a click is sent as the topic's label in an ordinary message. A
|
|
387
393
|
payload without `support` renders exactly as before.
|
|
388
394
|
|
|
395
|
+
The widget remembers its own look — name, brand colour, greeting and topics — in
|
|
396
|
+
browser storage per widget (never a message, name or email), so the launcher
|
|
397
|
+
wears your brand colour from first paint; every session refreshes it, so a
|
|
398
|
+
colour changed in the dashboard applies the next time the widget opens.
|
|
399
|
+
|
|
389
400
|
## Build outputs
|
|
390
401
|
|
|
391
402
|
The package currently produces:
|
|
@@ -414,6 +425,11 @@ export const POST = createChatSessionHandler({
|
|
|
414
425
|
`@clivly/sdk` exports the same handler if you depend on it directly. Don't import
|
|
415
426
|
from `clivly` (the package root) — that entry is the CLI and is Node-only.
|
|
416
427
|
|
|
428
|
+
The handler also forwards the visitor's IP address so Clivly can rate-limit new
|
|
429
|
+
chats per visitor instead of per host server. It reads `cf-connecting-ip`,
|
|
430
|
+
`x-real-ip` or the first `x-forwarded-for` entry; pass
|
|
431
|
+
`resolveVisitorIp: (request) => string | null` if your proxy uses another header.
|
|
432
|
+
|
|
417
433
|
Use the handler rather than hand-writing the proxy: it puts `origin` in the
|
|
418
434
|
request body (the backend requires it there, and only falls back to the `Origin`
|
|
419
435
|
header), accepts `visitorToken: null` for a first-time visitor, and turns an
|
|
@@ -435,6 +451,7 @@ unreachable Clivly into a JSON `502` instead of a thrown `fetch`.
|
|
|
435
451
|
| A brand-new widget refuses everything | An empty origin list permits nothing | Add at least one origin |
|
|
436
452
|
| `503 widget_not_configured` | The Clivly server cannot sign widget sessions | A Clivly-side configuration problem, not something in your app — contact Clivly support |
|
|
437
453
|
| Session request returns an opaque `400` | The route was hand-written and omits `origin` from the **body**, or rejects `visitorToken: null` | Use `createChatSessionHandler` from `clivly/sdk` |
|
|
454
|
+
| `429 rate_limited` on the session request | The visitor's IP, or your workspace as a whole, has started too many new chats recently | Wait and retry; resuming an existing thread is not counted |
|
|
438
455
|
| `404` on the session request | `sessionUrl` does not match where you mounted the route | `clivly add widget` writes `/api/clivly/widget/session` — match it, or set `sessionUrl` to your path |
|
|
439
456
|
| Bundle throws on `node:fs` / `node:child_process` | Something imported the `clivly` package root | Import the handler from `clivly/sdk` |
|
|
440
457
|
| A returning visitor starts a fresh thread on another device | By design — conversations resume by opaque `visitorToken` in `localStorage`, never by the (unverified) email | Not a bug; resuming by email would leak a known customer's history |
|
|
@@ -443,10 +460,10 @@ unreachable Clivly into a JSON `502` instead of a thrown `fetch`.
|
|
|
443
460
|
|
|
444
461
|
## Related documentation
|
|
445
462
|
|
|
446
|
-
- **[Adding the chat widget](
|
|
447
|
-
- [Connecting to Clivly Cloud](
|
|
448
|
-
- [`@clivly/sdk`
|
|
449
|
-
- [`clivly` CLI
|
|
463
|
+
- **[Adding the chat widget](https://clivly.com/docs/guides/chat-widget)** — the canonical end-to-end guide
|
|
464
|
+
- [Connecting to Clivly Cloud](https://clivly.com/docs/getting-started/quickstart) — the overall integration guide
|
|
465
|
+
- [`@clivly/sdk` reference](https://clivly.com/docs/reference/packages) — `createChatSessionHandler` and the rest of the runtime
|
|
466
|
+
- [`clivly` CLI reference](https://clivly.com/docs/reference/cli) — `clivly add widget`
|
|
450
467
|
|
|
451
468
|
## License
|
|
452
469
|
|