@lorikeetai/react-native-sdk 1.2.0 → 2.0.0-alpha.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 +144 -2
- package/dist/index.cjs +693 -214
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -41
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +93 -41
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +665 -212
- package/dist/index.js.map +1 -1
- package/package.json +34 -26
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LorikeetCX.ai
|
|
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
|
@@ -2,12 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
SDK containing embeddable React Native components that renders the LorikeetCX web widget inside a react-native-webview.
|
|
4
4
|
|
|
5
|
+
> **Alpha.** The surface can still change between releases. Resume, storage and
|
|
6
|
+
> token refresh are host responsibilities today; see [Resuming a
|
|
7
|
+
> conversation](#resuming-a-conversation) and [Identity](#identity).
|
|
8
|
+
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
11
|
+
The three native modules are peer dependencies, so install them alongside the
|
|
12
|
+
SDK. Name them explicitly rather than relying on your package manager to add
|
|
13
|
+
them for you: npm and pnpm auto-install peers, but **neither Yarn Classic nor
|
|
14
|
+
Yarn Berry does, and neither fails the install.** Classic prints `has unmet peer
|
|
15
|
+
dependency`, Berry prints `YN0002 ... doesn't provide`, and both exit
|
|
16
|
+
successfully, and the failure surfaces later, when Metro cannot resolve the
|
|
17
|
+
module.
|
|
18
|
+
Metro reports one missing module at a time, so install all three at once.
|
|
19
|
+
|
|
20
|
+
Name the SDK's version too. Alphas go to the `alpha` dist tag, not `latest`, so a
|
|
21
|
+
bare `pnpm add @lorikeetai/react-native-sdk` installs the 1.x line, and no
|
|
22
|
+
semver range reaches a prerelease either.
|
|
23
|
+
|
|
7
24
|
```bash
|
|
8
|
-
pnpm add @lorikeetai/react-native-sdk
|
|
25
|
+
pnpm add @lorikeetai/react-native-sdk@2.0.0-alpha.1 \
|
|
26
|
+
react-native-webview@^13.15.0 \
|
|
27
|
+
react-native-safe-area-context@^5.6.0 \
|
|
28
|
+
react-native-svg@^15.13.0
|
|
9
29
|
```
|
|
10
30
|
|
|
31
|
+
These are native modules, so rebuild rather than just restarting the bundler:
|
|
32
|
+
`pod install` for iOS, a Gradle sync for Android.
|
|
33
|
+
|
|
34
|
+
The peer ranges are bounded to the major versions this release is built and
|
|
35
|
+
tested against, so an unpinned install cannot silently resolve to an untested
|
|
36
|
+
major. Widening them is a change that needs testing, not a version bump.
|
|
37
|
+
|
|
38
|
+
### Upgrading from 1.x
|
|
39
|
+
|
|
40
|
+
- **Peer dependencies.** The three modules above used to arrive transitively.
|
|
41
|
+
Declare them yourself, and rebuild native.
|
|
42
|
+
- **`webviewProps` now reach the WebView.** The drop-in previously discarded
|
|
43
|
+
them. If you were passing props that silently did nothing, they take effect
|
|
44
|
+
now.
|
|
45
|
+
- **Lazy ticket creation.** A ticket is no longer created when the widget opens,
|
|
46
|
+
which changes when conversations appear in your Lorikeet queue and in anything
|
|
47
|
+
counting them.
|
|
48
|
+
|
|
11
49
|
## Basic Usage
|
|
12
50
|
|
|
13
51
|
```tsx
|
|
@@ -32,6 +70,109 @@ export default function Screen() {
|
|
|
32
70
|
- `customisations` (optional): Widget customization options from `@lorikeetai/web-sdk`
|
|
33
71
|
- `styles` (optional): Style overrides for the header text
|
|
34
72
|
- `onWebViewMessage` (optional): Handler for messages from the webview
|
|
73
|
+
- `ticketId` (optional): Resume this conversation instead of starting a new one
|
|
74
|
+
- `session` (optional): The session token that authorises `ticketId`
|
|
75
|
+
- `metadata` (optional): Arbitrary context attached to the conversation, for
|
|
76
|
+
routing or for the agent to read. Survives a resume
|
|
77
|
+
- `webviewProps` (optional): Forwarded to the underlying WebView. The SDK's
|
|
78
|
+
defaults for media playback, scaling and the loading state can all be
|
|
79
|
+
overridden; `onMessage` is additive, so the SDK reads the bridge first and
|
|
80
|
+
then calls yours
|
|
81
|
+
|
|
82
|
+
## Resuming a conversation
|
|
83
|
+
|
|
84
|
+
Without `ticketId`, every mount loads `/widget`, and `/widget` mints a new
|
|
85
|
+
ticket. A customer who closes the app and comes back gets an empty chat while
|
|
86
|
+
their previous ticket stays open.
|
|
87
|
+
|
|
88
|
+
The widget reports what you need to resume over the WebView bridge. Store both
|
|
89
|
+
values, scoped to the customer, somewhere that survives an app restart, and pass
|
|
90
|
+
them back on the next mount:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
const [resume, setResume] = useState<{ ticketId?: string; session?: string }>(
|
|
94
|
+
{},
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
void loadResumeForCustomer(customerId).then(setResume)
|
|
99
|
+
}, [customerId])
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<LorikeetWidgetView
|
|
103
|
+
publicKey="wk_xxx"
|
|
104
|
+
authToken={token}
|
|
105
|
+
ticketId={resume.ticketId}
|
|
106
|
+
session={resume.session}
|
|
107
|
+
onWebViewMessage={(event) => {
|
|
108
|
+
const message = JSON.parse(event.nativeEvent.data)
|
|
109
|
+
if (message.type === 'persistLorikeetTicketId') {
|
|
110
|
+
void saveResumeForCustomer(customerId, { ticketId: message.ticketId })
|
|
111
|
+
}
|
|
112
|
+
if (message.type === 'persistLorikeetSession') {
|
|
113
|
+
void saveResumeForCustomer(customerId, { session: message.session })
|
|
114
|
+
}
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Pass both or neither. `session` authorises exactly the ticket it was issued
|
|
121
|
+
for, and a resume without it fails with `CUSTOMER_ID_MISSING`.
|
|
122
|
+
|
|
123
|
+
The SDK does not store these for you, and it does not clear them. On logout,
|
|
124
|
+
clear your own copy, or the next customer on that device resumes the previous
|
|
125
|
+
one's conversation.
|
|
126
|
+
|
|
127
|
+
While `ticketId` is set, the header's new-chat icon reloads that conversation
|
|
128
|
+
rather than starting a new one. To start a new one, clear your stored
|
|
129
|
+
`ticketId` and `session` and let the next mount fall back to `/widget`.
|
|
130
|
+
|
|
131
|
+
## Identity
|
|
132
|
+
|
|
133
|
+
The public key, base URL and auth token are one unit, and a conversation belongs
|
|
134
|
+
to the credentials that created it. Never take some of the three from one source
|
|
135
|
+
and the rest from another, even briefly during a render.
|
|
136
|
+
|
|
137
|
+
When any of them change, which includes logout and switching environment, clear
|
|
138
|
+
your stored `ticketId` and `session` at the same time. Keeping them across a
|
|
139
|
+
credential change either resumes the previous customer's conversation on a
|
|
140
|
+
shared device or sends a ticket id to a backend that has never heard of it.
|
|
141
|
+
|
|
142
|
+
Anything you load or persist asynchronously needs to be discarded if the
|
|
143
|
+
credentials moved on while it was in flight; a write that lands late will
|
|
144
|
+
otherwise put the old conversation back.
|
|
145
|
+
|
|
146
|
+
## App lifecycle
|
|
147
|
+
|
|
148
|
+
The drop-in handles two failures that a WebView does not recover from on its own:
|
|
149
|
+
|
|
150
|
+
- **Renderer death.** When the OS kills the WebView's content process, the view
|
|
151
|
+
goes permanently blank with no error. The SDK detects this on both platforms
|
|
152
|
+
and remounts.
|
|
153
|
+
- **A stale stream after a long background.** The chat page gives its message
|
|
154
|
+
stream ten attempts with backoff capped at 30s, then stops trying. If the app
|
|
155
|
+
was backgrounded past that budget, the SDK remounts on return rather than
|
|
156
|
+
showing a conversation whose stream is dead. Shorter absences are left alone,
|
|
157
|
+
so an app switch does not cost the customer a draft message.
|
|
158
|
+
|
|
159
|
+
In both cases the remount resumes the conversation that was on screen. The SDK
|
|
160
|
+
watches the bridge for the live ticket and its session, so a conversation created
|
|
161
|
+
by a mount that had no `ticketId` is not lost, which is what a naive reload would
|
|
162
|
+
do: it would load `/widget` again and mint a second ticket. That memory
|
|
163
|
+
lasts for the life of the component and is scoped to the credentials that
|
|
164
|
+
produced it; surviving a process death is still your storage's job.
|
|
165
|
+
|
|
166
|
+
If you compose the parts yourself rather than using `LorikeetWidgetView`, both
|
|
167
|
+
are yours to handle.
|
|
168
|
+
|
|
169
|
+
## Customisation encoding
|
|
170
|
+
|
|
171
|
+
`customisations` is serialised as base64 of its UTF-8 bytes, which is what the
|
|
172
|
+
chat page decodes. Any Unicode is safe, including emoji and typographic
|
|
173
|
+
punctuation. Earlier versions used the global `btoa`, which accepts Latin-1
|
|
174
|
+
only: a title such as `Self's AI Agent` with a typographic apostrophe threw
|
|
175
|
+
during render.
|
|
35
176
|
|
|
36
177
|
## Headless components
|
|
37
178
|
|
|
@@ -71,7 +212,8 @@ WebView component that handles the widget content.
|
|
|
71
212
|
|
|
72
213
|
- `uri` (required): The URI that the web view will load
|
|
73
214
|
- `baseUrl` (optional): Base URL for the Lorikeet API (defaults to `https://chat.lorikeetcx.ai`)
|
|
74
|
-
- `webviewProps` (optional): Passed through to the webview component
|
|
215
|
+
- `webviewProps` (optional): Passed through to the webview component. The SDK
|
|
216
|
+
adds external-link handling on `onNavigationStateChange` and then calls yours
|
|
75
217
|
|
|
76
218
|
## Development
|
|
77
219
|
|