@askly/widget 2.4.0 → 2.6.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 +27 -2
- package/dist/icons.d.ts +2 -0
- package/dist/identity.d.ts +16 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/markdown.d.ts +31 -0
- package/dist/widget.d.ts +3 -1
- package/dist/widget.js +2 -2
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ Askly.identify({
|
|
|
89
89
|
| :--- | :--- | :--- |
|
|
90
90
|
| `userId` | `string` | **Required.** Your application's user ID. |
|
|
91
91
|
| `hash` | `string` | HMAC-SHA256 of `userId + timestamp`, using your Widget Secret Key. |
|
|
92
|
-
| `timestamp` | `number` | Unix seconds the hash was generated for. Valid for 5 minutes. |
|
|
92
|
+
| `timestamp` | `number` | **Required with `hash`.** Unix seconds the hash was generated for. Valid for 5 minutes. |
|
|
93
93
|
| `email` / `name` / `phone` | `string` | Optional profile fields shown to your agents. |
|
|
94
94
|
| `attributes` | `object` | Any extra traits you want on the contact record. |
|
|
95
95
|
|
|
@@ -108,6 +108,11 @@ const hash = crypto
|
|
|
108
108
|
|
|
109
109
|
Without a valid `hash` the traits are still used locally, but Askly will not link the accounts.
|
|
110
110
|
|
|
111
|
+
> **Known limitation:** a signature is accepted for 5 minutes from its `timestamp`. On a page that
|
|
112
|
+
> stays open longer, call `Askly.identify()` again with a freshly generated `hash` and `timestamp`
|
|
113
|
+
> (for example on a timer, or before the user opens the chat). If `identify()` is rejected, the
|
|
114
|
+
> reason is logged to the browser console.
|
|
115
|
+
|
|
111
116
|
#### Logging out
|
|
112
117
|
|
|
113
118
|
```javascript
|
|
@@ -116,7 +121,13 @@ Askly.shutdown(); // the same, and remove the widget from the page
|
|
|
116
121
|
```
|
|
117
122
|
|
|
118
123
|
Call one of these on logout, particularly for shared computers — otherwise the next person to
|
|
119
|
-
use the browser inherits the previous person's conversations.
|
|
124
|
+
use the browser inherits the previous person's conversations. `reset()` takes effect immediately
|
|
125
|
+
in an open widget: the transcript on screen is cleared, a new anonymous visitor id is issued, and
|
|
126
|
+
any identity passed to `init()` stops being sent. After `shutdown()` you can call `init()` again.
|
|
127
|
+
|
|
128
|
+
Both really do discard the anonymous visitor: the next message comes from a new visitor with no
|
|
129
|
+
history. Call them on logout only — not on every page load for guests, and not to hide the widget
|
|
130
|
+
on some routes (use `includePaths` / `excludePaths`, or `Askly.close()`, for that).
|
|
120
131
|
|
|
121
132
|
#### Identifying at init time
|
|
122
133
|
|
|
@@ -196,6 +207,20 @@ Askly.init({
|
|
|
196
207
|
|
|
197
208
|
None required. The widget talks to Askly's hosted backend automatically — you only provide an `appId`.
|
|
198
209
|
|
|
210
|
+
### Reply formatting
|
|
211
|
+
|
|
212
|
+
The server and the widget share one rendering contract, the **Askly reply markdown subset v1**. The AI is instructed to write only this subset, the server normalises anything else away, and the widget renders exactly this subset with a small built-in parser (no third-party markdown library). Every message carries a `format` field: `"markdown"` for AI replies, `"text"` for operator replies and visitor messages, which are shown verbatim with URLs auto-linked.
|
|
213
|
+
|
|
214
|
+
| Allowed | Syntax |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| Paragraphs | blank line between them; a single newline is a soft break |
|
|
217
|
+
| Bold, italic | `**bold**`, `*italic*` or `_italic_` |
|
|
218
|
+
| Inline code, code blocks | `` `code` ``, fenced ```` ``` ```` with an optional language |
|
|
219
|
+
| Lists | `- item`, `* item`, `1. item`; never nested |
|
|
220
|
+
| Links | `[text](https://…)` (https, http, mailto, tel) and bare URLs |
|
|
221
|
+
|
|
222
|
+
Headings, tables, images, blockquotes, horizontal rules and raw HTML are not part of the contract and appear as literal text. The canonical definition lives in `src/markdown.ts`; the server copy is `app/services/reply_format.py`.
|
|
223
|
+
|
|
199
224
|
## Development
|
|
200
225
|
|
|
201
226
|
```bash
|
package/dist/icons.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export declare const Minus: ({ size, color, strokeWidth, ...rest }: IconProps) =
|
|
|
9
9
|
export declare const ArrowUp: ({ size, color, strokeWidth, ...rest }: IconProps) => React.ReactSVGElement;
|
|
10
10
|
export declare const Mic: ({ size, color, strokeWidth, ...rest }: IconProps) => React.ReactSVGElement;
|
|
11
11
|
export declare const MicOff: ({ size, color, strokeWidth, ...rest }: IconProps) => React.ReactSVGElement;
|
|
12
|
+
export declare const Volume2: ({ size, color, strokeWidth, ...rest }: IconProps) => React.ReactSVGElement;
|
|
13
|
+
export declare const VolumeX: ({ size, color, strokeWidth, ...rest }: IconProps) => React.ReactSVGElement;
|
|
12
14
|
export declare const Home: ({ size, color, strokeWidth, ...rest }: IconProps) => React.ReactSVGElement;
|
|
13
15
|
export declare const Compass: ({ size, color, strokeWidth, ...rest }: IconProps) => React.ReactSVGElement;
|
|
14
16
|
export declare const MessageSquare: ({ size, color, strokeWidth, ...rest }: IconProps) => React.ReactSVGElement;
|
package/dist/identity.d.ts
CHANGED
|
@@ -17,12 +17,17 @@
|
|
|
17
17
|
* The stable per-browser token for this organization, minting one if needed.
|
|
18
18
|
* Scoped per org so a browser visiting two Askly-powered sites keeps them separate.
|
|
19
19
|
*/
|
|
20
|
-
export declare function getVisitorId(orgId: string): string;
|
|
20
|
+
export declare function getVisitorId(orgId: string, adoptFrom?: string): string;
|
|
21
21
|
/**
|
|
22
22
|
* Forget this browser's identity and chat history — call on logout so the next person at
|
|
23
23
|
* a shared computer starts clean rather than inheriting the previous session.
|
|
24
24
|
*/
|
|
25
25
|
export declare function resetVisitor(orgId: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Record that data initialised under `scope` (the app id, or "detect") actually lives under
|
|
28
|
+
* `resolved` (the organization id from remote config). Not personal data, so reset keeps it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function rememberResolvedScope(scope: string, resolved: string): void;
|
|
26
31
|
/** A fresh server-side thread id. Mirrors the local chat id so one chat is one thread. */
|
|
27
32
|
export declare function newThreadKey(): string;
|
|
28
33
|
export interface AsklyIdentity {
|
|
@@ -30,7 +35,10 @@ export interface AsklyIdentity {
|
|
|
30
35
|
userId: string;
|
|
31
36
|
/** HMAC-SHA256 of `userId + timestamp` under the org's widget secret, computed server-side. */
|
|
32
37
|
hash?: string;
|
|
33
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Unix seconds the hash was generated for. Required with `hash`: the server recomputes the
|
|
40
|
+
* HMAC from this exact value and rejects it once it is more than 5 minutes old.
|
|
41
|
+
*/
|
|
34
42
|
timestamp?: number;
|
|
35
43
|
email?: string;
|
|
36
44
|
name?: string;
|
|
@@ -47,4 +55,10 @@ type IdentityListener = (identity: AsklyIdentity) => void;
|
|
|
47
55
|
export declare function publishIdentity(identity: AsklyIdentity): void;
|
|
48
56
|
export declare function subscribeIdentity(listener: IdentityListener): () => void;
|
|
49
57
|
export declare function clearIdentity(): void;
|
|
58
|
+
type ResetListener = () => void;
|
|
59
|
+
/** How many times reset() has run on this page. Lets a widget notice a reset it missed. */
|
|
60
|
+
export declare function getResetGeneration(): number;
|
|
61
|
+
/** Tell the mounted widget that Askly.reset() ran, so it drops what it holds in memory. */
|
|
62
|
+
export declare function publishReset(): void;
|
|
63
|
+
export declare function subscribeReset(listener: ResetListener): () => void;
|
|
50
64
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface AsklyConfig {
|
|
|
9
9
|
themeColor?: string;
|
|
10
10
|
theme?: "light" | "dark" | "auto";
|
|
11
11
|
enableVoiceChat?: boolean;
|
|
12
|
+
readAloud?: boolean;
|
|
12
13
|
welcomeMessage?: string;
|
|
13
14
|
placeholderText?: string;
|
|
14
15
|
organizationLogo?: string;
|
|
@@ -26,6 +27,7 @@ export interface AsklyConfig {
|
|
|
26
27
|
excludePaths?: string[];
|
|
27
28
|
includePaths?: string[];
|
|
28
29
|
configOverride?: Record<string, any>;
|
|
30
|
+
debug?: boolean;
|
|
29
31
|
onMessageSent?: (message: string) => void;
|
|
30
32
|
onMessageReceived?: (reply: string) => void;
|
|
31
33
|
onChatOpened?: () => void;
|