@nlxai/core 1.2.3-alpha.2 → 1.2.3
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 +1877 -34
- package/lib/index.cjs +90 -55
- package/lib/index.d.ts +255 -213
- package/lib/index.esm.js +90 -55
- package/lib/index.umd.js +1 -1
- package/package.json +12 -12
- package/typedoc.cjs +9 -2
package/lib/index.cjs
CHANGED
|
@@ -6,7 +6,7 @@ var ReconnectingWebSocket = require('reconnecting-websocket');
|
|
|
6
6
|
var uuid = require('uuid');
|
|
7
7
|
|
|
8
8
|
var name = "@nlxai/core";
|
|
9
|
-
var version$1 = "1.2.3
|
|
9
|
+
var version$1 = "1.2.3";
|
|
10
10
|
var description = "Low-level SDK for building NLX experiences";
|
|
11
11
|
var type = "module";
|
|
12
12
|
var main = "lib/index.cjs";
|
|
@@ -22,40 +22,40 @@ var exports$1 = {
|
|
|
22
22
|
};
|
|
23
23
|
var scripts = {
|
|
24
24
|
build: "rm -rf lib && rollup -c --configPlugin typescript --configImportAttributesKey with",
|
|
25
|
-
docs: "rm -rf docs/ && typedoc && concat-md --decrease-title-levels --dir-name-as-title docs/ > docs/index.md",
|
|
26
25
|
"lint:check": "eslint src/ --ext .ts,.tsx,.js,.jsx --max-warnings 0",
|
|
27
26
|
lint: "eslint src/ --ext .ts,.tsx,.js,.jsx --fix",
|
|
28
27
|
prepublish: "npm run build",
|
|
29
|
-
"preview-docs": "npm run docs && comrak --unsafe --gfm -o docs/index.html docs/index.md && open docs/index.html",
|
|
30
|
-
"publish-docs": "npm run docs && mv docs/index.md ../website/src/content/headless-api-reference.md",
|
|
31
28
|
test: "typedoc --emit none",
|
|
32
|
-
tsc: "tsc"
|
|
29
|
+
tsc: "tsc",
|
|
30
|
+
"update-readme:docs": "rm -rf docs/ && typedoc",
|
|
31
|
+
"update-readme:merge": "../../scripts/transclude-markdown.js",
|
|
32
|
+
"update-readme": "npm run update-readme:docs && npm run update-readme:merge"
|
|
33
33
|
};
|
|
34
34
|
var author = "Peter Szerzo <peter@nlx.ai>";
|
|
35
35
|
var license = "MIT";
|
|
36
36
|
var devDependencies = {
|
|
37
|
-
"@types/isomorphic-fetch": "^0.0.
|
|
38
|
-
"@types/node": "^
|
|
39
|
-
"@types/ramda": "0.
|
|
37
|
+
"@types/isomorphic-fetch": "^0.0.39",
|
|
38
|
+
"@types/node": "^24.10.1",
|
|
39
|
+
"@types/ramda": "0.31.1",
|
|
40
40
|
"@types/uuid": "^9.0.7",
|
|
41
41
|
"concat-md": "^0.5.1",
|
|
42
42
|
"eslint-config-nlx": "*",
|
|
43
43
|
prettier: "^3.1.0",
|
|
44
44
|
"rollup-config-nlx": "*",
|
|
45
|
-
typedoc: "^0.
|
|
46
|
-
"typedoc-plugin-markdown": "^
|
|
45
|
+
typedoc: "^0.28.14",
|
|
46
|
+
"typedoc-plugin-markdown": "^4.9.0",
|
|
47
47
|
typescript: "^5.5.4"
|
|
48
48
|
};
|
|
49
49
|
var dependencies = {
|
|
50
50
|
"isomorphic-fetch": "^3.0.0",
|
|
51
|
-
ramda: "^0.
|
|
51
|
+
ramda: "^0.32.0",
|
|
52
52
|
"reconnecting-websocket": "^4.4.0",
|
|
53
53
|
uuid: "^9.0.1"
|
|
54
54
|
};
|
|
55
55
|
var publishConfig = {
|
|
56
56
|
access: "public"
|
|
57
57
|
};
|
|
58
|
-
var gitHead = "
|
|
58
|
+
var gitHead = "3902161e95745dd4a9cfb68bb469755a62b421f5";
|
|
59
59
|
var packageJson = {
|
|
60
60
|
name: name,
|
|
61
61
|
version: version$1,
|
|
@@ -127,18 +127,6 @@ const safeJsonParse = (val) => {
|
|
|
127
127
|
return null;
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
|
-
/**
|
|
131
|
-
* Helper method to decide when a new {@link Config} requires creating a new {@link ConversationHandler} or whether the old `Config`'s
|
|
132
|
-
* `ConversationHandler` can be used.
|
|
133
|
-
*
|
|
134
|
-
* The order of configs doesn't matter.
|
|
135
|
-
* @param config1 -
|
|
136
|
-
* @param config2 -
|
|
137
|
-
* @returns true if `createConversation` should be called again
|
|
138
|
-
*/
|
|
139
|
-
const shouldReinitialize = (config1, config2) => {
|
|
140
|
-
return !ramda.equals(config1, config2);
|
|
141
|
-
};
|
|
142
130
|
const getBaseDomain = (url) => url.match(/(bots\.dev\.studio\.nlx\.ai|bots\.studio\.nlx\.ai|apps\.nlx\.ai|dev\.apps\.nlx\.ai)/g)?.[0] ?? "apps.nlx.ai";
|
|
143
131
|
/**
|
|
144
132
|
* When a HTTP URL is provided, deduce the websocket URL. Otherwise, return the argument.
|
|
@@ -175,41 +163,45 @@ const normalizeToHttp = (applicationUrl) => {
|
|
|
175
163
|
const isWebsocketUrl = (url) => {
|
|
176
164
|
return url.indexOf("wss://") === 0;
|
|
177
165
|
};
|
|
178
|
-
/**
|
|
179
|
-
* Check whether a configuration is value.
|
|
180
|
-
* @param config - Chat configuration
|
|
181
|
-
* @returns isValid - Whether the configuration is valid
|
|
182
|
-
*/
|
|
183
|
-
const isConfigValid = (config) => {
|
|
184
|
-
const applicationUrl = config.applicationUrl ?? "";
|
|
185
|
-
return applicationUrl.length > 0;
|
|
186
|
-
};
|
|
187
166
|
/**
|
|
188
167
|
* Call this to create a conversation handler.
|
|
189
|
-
* @param
|
|
168
|
+
* @param configuration - The necessary configuration to create the conversation.
|
|
190
169
|
* @returns The {@link ConversationHandler} is a bundle of functions to interact with the conversation.
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* import { createConversation } from "@nlx/core";
|
|
173
|
+
*
|
|
174
|
+
* const conversation = createConversation({
|
|
175
|
+
* applicationUrl: "https://apps.nlx.ai/c/cfab3-243ad-232dc",
|
|
176
|
+
* headers: {
|
|
177
|
+
* "nlx-api-key": "4393029032-dwsd",
|
|
178
|
+
* },
|
|
179
|
+
* userId: "abcd-1234",
|
|
180
|
+
* languageCode: "en-US",
|
|
181
|
+
* });
|
|
182
|
+
* ```
|
|
191
183
|
*/
|
|
192
|
-
function createConversation(
|
|
184
|
+
function createConversation(configuration) {
|
|
193
185
|
let socket;
|
|
194
186
|
let socketMessageQueue = [];
|
|
195
187
|
let socketMessageQueueCheckInterval = null;
|
|
196
188
|
let voicePlusSocket;
|
|
197
189
|
let voicePlusSocketMessageQueue = [];
|
|
198
190
|
let voicePlusSocketMessageQueueCheckInterval = null;
|
|
199
|
-
const applicationUrl =
|
|
191
|
+
const applicationUrl = configuration.applicationUrl ?? "";
|
|
200
192
|
// Check if the application URL has a language code appended to it
|
|
201
193
|
if (/[-|_][a-z]{2,}[-|_][A-Z]{2,}$/.test(applicationUrl)) {
|
|
202
194
|
Console.warn("Since v1.0.0, the language code is no longer added at the end of the application URL. Please remove the modifier (e.g. '-en-US') from the URL, and specify it in the `languageCode` parameter instead.");
|
|
203
195
|
}
|
|
204
196
|
const eventListeners = { voicePlusCommand: [] };
|
|
205
|
-
const initialConversationId =
|
|
197
|
+
const initialConversationId = configuration.conversationId ?? uuid.v4();
|
|
206
198
|
let state = {
|
|
207
|
-
responses:
|
|
208
|
-
languageCode:
|
|
209
|
-
userId:
|
|
199
|
+
responses: configuration.responses ?? [],
|
|
200
|
+
languageCode: configuration.languageCode,
|
|
201
|
+
userId: configuration.userId,
|
|
210
202
|
conversationId: initialConversationId,
|
|
211
203
|
};
|
|
212
|
-
const fullApplicationHttpUrl = () => `${normalizeToHttp(applicationUrl)}${
|
|
204
|
+
const fullApplicationHttpUrl = () => `${normalizeToHttp(applicationUrl)}${configuration.experimental?.completeApplicationUrl === true
|
|
213
205
|
? ""
|
|
214
206
|
: `-${state.languageCode}`}`;
|
|
215
207
|
const setState = (change,
|
|
@@ -228,7 +220,7 @@ function createConversation(config) {
|
|
|
228
220
|
type: exports.ResponseType.Failure,
|
|
229
221
|
receivedAt: new Date().getTime(),
|
|
230
222
|
payload: {
|
|
231
|
-
text:
|
|
223
|
+
text: configuration.failureMessage ?? defaultFailureMessage,
|
|
232
224
|
},
|
|
233
225
|
};
|
|
234
226
|
setState({
|
|
@@ -300,8 +292,8 @@ function createConversation(config) {
|
|
|
300
292
|
conversationId: state.conversationId,
|
|
301
293
|
...body,
|
|
302
294
|
languageCode: state.languageCode,
|
|
303
|
-
channelType:
|
|
304
|
-
environment:
|
|
295
|
+
channelType: configuration.experimental?.channelType,
|
|
296
|
+
environment: configuration.environment,
|
|
305
297
|
};
|
|
306
298
|
if (isWebsocketUrl(applicationUrl)) {
|
|
307
299
|
if (socket?.readyState === 1) {
|
|
@@ -316,7 +308,7 @@ function createConversation(config) {
|
|
|
316
308
|
const res = await fetch(fullApplicationHttpUrl(), {
|
|
317
309
|
method: "POST",
|
|
318
310
|
headers: {
|
|
319
|
-
...(
|
|
311
|
+
...(configuration.headers ?? {}),
|
|
320
312
|
Accept: "application/json",
|
|
321
313
|
"Content-Type": "application/json",
|
|
322
314
|
"nlx-sdk-version": packageJson.version,
|
|
@@ -353,7 +345,7 @@ function createConversation(config) {
|
|
|
353
345
|
// If the socket is already set up, tear it down first
|
|
354
346
|
teardownWebsocket();
|
|
355
347
|
const url = new URL(applicationUrl);
|
|
356
|
-
if (
|
|
348
|
+
if (configuration.experimental?.completeApplicationUrl !== true) {
|
|
357
349
|
url.searchParams.set("languageCode", state.languageCode);
|
|
358
350
|
url.searchParams.set("channelKey", `${url.searchParams.get("channelKey") ?? ""}-${state.languageCode}`);
|
|
359
351
|
}
|
|
@@ -386,17 +378,17 @@ function createConversation(config) {
|
|
|
386
378
|
const setupCommandWebsocket = () => {
|
|
387
379
|
// If the socket is already set up, tear it down first
|
|
388
380
|
teardownCommandWebsocket();
|
|
389
|
-
if (
|
|
381
|
+
if (configuration.bidirectional !== true) {
|
|
390
382
|
return;
|
|
391
383
|
}
|
|
392
384
|
const url = new URL(normalizeToWebsocket(applicationUrl));
|
|
393
|
-
if (
|
|
385
|
+
if (configuration.experimental?.completeApplicationUrl !== true) {
|
|
394
386
|
url.searchParams.set("languageCode", state.languageCode);
|
|
395
387
|
url.searchParams.set("channelKey", `${url.searchParams.get("channelKey") ?? ""}-${state.languageCode}`);
|
|
396
388
|
}
|
|
397
389
|
url.searchParams.set("conversationId", state.conversationId);
|
|
398
390
|
url.searchParams.set("type", "voice-plus");
|
|
399
|
-
const apiKey =
|
|
391
|
+
const apiKey = configuration.headers["nlx-api-key"];
|
|
400
392
|
if (!isWebsocketUrl(applicationUrl) && apiKey != null) {
|
|
401
393
|
url.searchParams.set("apiKey", apiKey);
|
|
402
394
|
}
|
|
@@ -540,7 +532,7 @@ function createConversation(config) {
|
|
|
540
532
|
const res = await fetch(`${fullApplicationHttpUrl()}/context`, {
|
|
541
533
|
method: "POST",
|
|
542
534
|
headers: {
|
|
543
|
-
...(
|
|
535
|
+
...(configuration.headers ?? {}),
|
|
544
536
|
Accept: "application/json",
|
|
545
537
|
"Content-Type": "application/json",
|
|
546
538
|
"nlx-conversation-id": state.conversationId,
|
|
@@ -621,7 +613,7 @@ function createConversation(config) {
|
|
|
621
613
|
const res = await fetch(`${url}-${state.languageCode}/requestToken`, {
|
|
622
614
|
method: "POST",
|
|
623
615
|
headers: {
|
|
624
|
-
...(
|
|
616
|
+
...(configuration.headers ?? {}),
|
|
625
617
|
Accept: "application/json",
|
|
626
618
|
"Content-Type": "application/json",
|
|
627
619
|
"nlx-conversation-id": state.conversationId,
|
|
@@ -682,9 +674,52 @@ function createConversation(config) {
|
|
|
682
674
|
};
|
|
683
675
|
}
|
|
684
676
|
/**
|
|
685
|
-
*
|
|
686
|
-
* @param
|
|
687
|
-
* @returns
|
|
677
|
+
* Check whether a configuration is valid.
|
|
678
|
+
* @param configuration - Conversation configuration
|
|
679
|
+
* @returns Whether the configuration is valid?
|
|
680
|
+
*/
|
|
681
|
+
const isConfigValid = (configuration) => {
|
|
682
|
+
const applicationUrl = configuration.applicationUrl ?? "";
|
|
683
|
+
return applicationUrl.length > 0;
|
|
684
|
+
};
|
|
685
|
+
/**
|
|
686
|
+
* Helper method to decide when a new {@link Config} requires creating a new {@link ConversationHandler} or whether the old `Config`'s
|
|
687
|
+
* `ConversationHandler` can be used.
|
|
688
|
+
*
|
|
689
|
+
* The order of configs doesn't matter.
|
|
690
|
+
* @param config1 -
|
|
691
|
+
* @param config2 -
|
|
692
|
+
* @returns true if `createConversation` should be called again
|
|
693
|
+
*/
|
|
694
|
+
const shouldReinitialize = (config1, config2) => {
|
|
695
|
+
return !ramda.equals(config1, config2);
|
|
696
|
+
};
|
|
697
|
+
/**
|
|
698
|
+
* Get current expiration timestamp from a list of responses. Can be used to determine if a conversation has timed out.
|
|
699
|
+
* @example
|
|
700
|
+
* ```typescript
|
|
701
|
+
* import { useState } from "react";
|
|
702
|
+
* import { getCurrentExpirationTimestamp } from "@nlxai/core";
|
|
703
|
+
*
|
|
704
|
+
* const [isTimedOut, setIsTimedOut] = useState(false);
|
|
705
|
+
*
|
|
706
|
+
* conversation.subscribe((responses) => {
|
|
707
|
+
* const expirationTimestamp = getCurrentExpirationTimestamp(responses);
|
|
708
|
+
* if (expirationTimestamp != null && expirationTimestamp < new Date().getTime()) {
|
|
709
|
+
* setIsTimedOut(true);
|
|
710
|
+
* }
|
|
711
|
+
* });
|
|
712
|
+
*
|
|
713
|
+
* return (<div>
|
|
714
|
+
* {isTimedOut ? (
|
|
715
|
+
* <p>Your session has timed out. Please start a new conversation.</p>
|
|
716
|
+
* ) : (
|
|
717
|
+
* <p>Your session is active.</p>
|
|
718
|
+
* )}
|
|
719
|
+
* </div>
|
|
720
|
+
* ```
|
|
721
|
+
* @param responses - The current list of user and application responses (first argument in the subscribe callback)
|
|
722
|
+
* @returns An expiration timestamp in Unix Epoch (`new Date().getTime()`), or `null` if this is not known (typically occurs if the application has not responded yet)
|
|
688
723
|
*/
|
|
689
724
|
const getCurrentExpirationTimestamp = (responses) => {
|
|
690
725
|
let expirationTimestamp = null;
|
|
@@ -712,7 +747,7 @@ const getCurrentExpirationTimestamp = (responses) => {
|
|
|
712
747
|
* console.log(response);
|
|
713
748
|
* });
|
|
714
749
|
* ```
|
|
715
|
-
* @typeParam
|
|
750
|
+
* @typeParam Params - the type of the function's params, e.g. for `sendText` it's `text: string, context?: Context`
|
|
716
751
|
* @param fn - the function to wrap (e.g. `convo.sendText`, `convo.sendChoice`, etc.)
|
|
717
752
|
* @param convo - the `ConversationHandler` (from {@link createConversation})
|
|
718
753
|
* @param timeout - the timeout in milliseconds
|