@fluxyte/sdk 0.9.0 → 0.10.0
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 +700 -666
- package/dist/core/client.d.ts +19 -0
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +29 -0
- package/dist/core/client.js.map +1 -1
- package/dist/core/commerce.d.ts +54 -0
- package/dist/core/commerce.d.ts.map +1 -0
- package/dist/core/commerce.js +2 -0
- package/dist/core/commerce.js.map +1 -0
- package/dist/generated/openapi.d.ts +46 -1
- package/dist/generated/openapi.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/react/useChat.d.ts +2 -0
- package/dist/react/useChat.d.ts.map +1 -1
- package/dist/react/useStreamingChat.d.ts.map +1 -1
- package/dist/react/useVoiceChat.d.ts.map +1 -1
- package/dist/vanilla/index.d.ts +1 -0
- package/dist/vanilla/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,666 +1,700 @@
|
|
|
1
|
-
# Fluxyte SDK (TypeScript)
|
|
2
|
-
|
|
3
|
-
The official TypeScript SDK for the Fluxyte Onboarding AI API: a context-aware,
|
|
4
|
-
documentation-grounded assistant designed for onboarding and setup flows (not generic chat).
|
|
5
|
-
|
|
6
|
-
## Unreleased
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- `
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
- `
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
console.log(
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
-
|
|
540
|
-
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
3. `
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
```
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
1
|
+
# Fluxyte SDK (TypeScript)
|
|
2
|
+
|
|
3
|
+
The official TypeScript SDK for the Fluxyte Onboarding AI API: a context-aware,
|
|
4
|
+
documentation-grounded assistant designed for onboarding and setup flows (not generic chat).
|
|
5
|
+
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
- Commerce cart SDK methods and typed server-authoritative cart contracts are available on this feature branch (not yet published).
|
|
9
|
+
|
|
10
|
+
## Commerce cart SDK (unreleased)
|
|
11
|
+
|
|
12
|
+
The Commerce cart is **server-authoritative** and separate from the ordinary chat session. Use a public `pk_*` API key, and keep the server-minted cart credential private. Do not log, publish, or place it in URLs. The SDK does not automatically persist this bearer credential.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { OnboardingAIClient } from "@fluxyte/sdk";
|
|
16
|
+
|
|
17
|
+
const client = new OnboardingAIClient("pk_YOUR_PUBLIC_KEY");
|
|
18
|
+
const session = await client.createCommerceCartSession();
|
|
19
|
+
let credential = session.credential;
|
|
20
|
+
let cart = session.cart;
|
|
21
|
+
|
|
22
|
+
const result = await client.mutateCommerceCart({
|
|
23
|
+
credential,
|
|
24
|
+
expectedRevision: cart.revision,
|
|
25
|
+
requestKey: crypto.randomUUID(), // reuse this key when retrying the SAME mutation
|
|
26
|
+
mutation: { kind: "ADD", offeringId: "PUBLISHED_OFFERING_ID", quantity: 2 },
|
|
27
|
+
});
|
|
28
|
+
cart = result.cart;
|
|
29
|
+
|
|
30
|
+
const preflight = await client.preflightCommerceCheckout({
|
|
31
|
+
credential,
|
|
32
|
+
expectedRevision: cart.revision,
|
|
33
|
+
});
|
|
34
|
+
// Preflight is a server-side quote/eligibility check, NOT an order or payment confirmation.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Available helpers: `createCommerceCartSession()`, `renewCommerceCartSession(credential)`, `readCommerceCart(credential)`, `mutateCommerceCart({ credential, expectedRevision, requestKey, mutation })`, and `preflightCommerceCheckout({ credential, expectedRevision })`. Mutations support `ADD`, `SET_QUANTITY`, and `REMOVE`. The backend validates offering availability, prices, currency, revision, and idempotency. On a stale revision, read the latest cart before deciding whether to issue a **new** mutation; do not blindly replay a different action under the same request key. Renewal requires an unexpired credential and does not revoke the prior credential.
|
|
38
|
+
|
|
39
|
+
These methods require a deployed backend with the Commerce cart routes and configured session signing/rate-limit infrastructure. They do not initiate payment or guarantee checkout success. Existing chat, streaming, voice and legacy Commerce action APIs remain available. No package release has been published for these unreleased changes.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
- Chat and voice now use top-level `sessionId` or `userId`; their context is optional.
|
|
43
|
+
- `PublicChatContext` contains only validated catalogue/step hints, diagnostics, runtime metadata, locale, and timezone.
|
|
44
|
+
- Structured `error` and `attemptedAction` objects provide richer troubleshooting context.
|
|
45
|
+
- Named public context, request, response, diagnostic, and event types are exported from all entrypoints.
|
|
46
|
+
|
|
47
|
+
## What's New In 0.7.0
|
|
48
|
+
|
|
49
|
+
- Product Catalogue offering cards now expose optional `imageAlt` and `videoUrl` fields.
|
|
50
|
+
- Use `imageAlt` when rendering catalogue images and open `videoUrl` as a validated hosted-video destination.
|
|
51
|
+
- Existing `imageUrl`, pricing, availability, and Commerce action fields remain backward compatible.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const response = await client.chat({
|
|
55
|
+
message: "Show me your plans",
|
|
56
|
+
sessionId: "session_123",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
for (const offering of response.commerce?.offerings ?? []) {
|
|
60
|
+
console.log(offering.imageUrl, offering.imageAlt, offering.videoUrl);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## What's New In 0.6.0
|
|
65
|
+
|
|
66
|
+
- Product Catalogue responses now include typed `commerce` presentation data.
|
|
67
|
+
- Commerce presentations contain products/services offerings, prices, availability, features, and safe action IDs.
|
|
68
|
+
- `openCommerceAction()` resolves an external checkout only after the API validates the organization, plan, catalogue publication, offering availability, and action.
|
|
69
|
+
- `useStreamingChat()` now exposes both `commerce` and `resources` from the completed response.
|
|
70
|
+
|
|
71
|
+
## What's New In 0.5.0
|
|
72
|
+
|
|
73
|
+
- Structured resources are available on chat, streaming, and voice responses.
|
|
74
|
+
- Supported resource kinds: `VIDEO`, `AUDIO`, `STORE`, `REDIRECT`, `REFERRAL`, and `CHECKOUT`.
|
|
75
|
+
- Video and audio resources can include a safe `embedUrl` for inline rendering.
|
|
76
|
+
- `useStreamingChat()` now exposes the completed response's `resources`.
|
|
77
|
+
|
|
78
|
+
## Install
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm install @fluxyte/sdk
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
|
|
86
|
+
- Browser or Node.js 18+ (global `fetch` available)
|
|
87
|
+
- A Fluxyte API key (sent as `X-API-Key`)
|
|
88
|
+
- `pk_*` for browser/public SDK usage
|
|
89
|
+
- `sk_*` for backend/server usage only
|
|
90
|
+
|
|
91
|
+
## Authentication (API Key)
|
|
92
|
+
|
|
93
|
+
Treat your API key like a password. Do not commit it to source control.
|
|
94
|
+
|
|
95
|
+
### Create an API key
|
|
96
|
+
|
|
97
|
+
1. Sign up at `https://fluxyte.com/signup`
|
|
98
|
+
2. Verify your email
|
|
99
|
+
3. Open the `Account` menu
|
|
100
|
+
4. Select `API Keys`
|
|
101
|
+
5. Click `Create API Key`
|
|
102
|
+
6. Choose key type:
|
|
103
|
+
- `pk_*` (PUBLIC) for frontend/browser SDK usage
|
|
104
|
+
- `sk_*` (SECRET) for backend/server-only usage
|
|
105
|
+
7. Copy your API key (shown once)
|
|
106
|
+
|
|
107
|
+
### Use an API key
|
|
108
|
+
|
|
109
|
+
All integrations authenticate with an API key sent in the `X-API-Key` header.
|
|
110
|
+
|
|
111
|
+
- Use `pk_*` keys in browser/public SDK integrations
|
|
112
|
+
- Use `sk_*` keys only in backend/server environments
|
|
113
|
+
- For `pk_*` keys, configure allowed origins to restrict frontend domains
|
|
114
|
+
- The key controls organization access, docs scope, and analytics ownership
|
|
115
|
+
|
|
116
|
+
### Environment examples
|
|
117
|
+
|
|
118
|
+
- Vite: `VITE_FLUXYTE_API_KEY=pk_...`
|
|
119
|
+
- Next.js: `NEXT_PUBLIC_FLUXYTE_API_KEY=pk_...` (public key only)
|
|
120
|
+
- Server: `FLUXYTE_API_KEY=sk_...`
|
|
121
|
+
|
|
122
|
+
The SDK rejects `sk_*` keys in browser environments to prevent accidental exposure.
|
|
123
|
+
|
|
124
|
+
## Key Management
|
|
125
|
+
|
|
126
|
+
### Key Purpose
|
|
127
|
+
|
|
128
|
+
- `pk_*` (PUBLIC): for browser/frontend SDK usage.
|
|
129
|
+
- `sk_*` (SECRET): for backend/server usage only.
|
|
130
|
+
|
|
131
|
+
### How to get keys
|
|
132
|
+
|
|
133
|
+
1. Sign in to Fluxyte dashboard.
|
|
134
|
+
2. Go to `Account` -> `API Keys`.
|
|
135
|
+
3. Create a key and choose type:
|
|
136
|
+
- `PUBLIC (pk_*)` for frontend SDK traffic.
|
|
137
|
+
- `SECRET (sk_*)` for backend automation or server integrations.
|
|
138
|
+
4. Copy the key immediately (shown once).
|
|
139
|
+
|
|
140
|
+
### Allowed origins (PUBLIC keys)
|
|
141
|
+
|
|
142
|
+
For `pk_*` keys, configure allowed origins in dashboard (for example `https://app.example.com`).
|
|
143
|
+
This limits where browser-based SDK requests are accepted from.
|
|
144
|
+
|
|
145
|
+
### Rotation and revocation
|
|
146
|
+
|
|
147
|
+
- Rotate keys on a regular schedule (recommended every 60-90 days).
|
|
148
|
+
- Keep a short overlap window where old and new keys are both valid during rollout.
|
|
149
|
+
- Revoke keys immediately if exposed.
|
|
150
|
+
- Update environment variables and redeploy clients after rotation.
|
|
151
|
+
|
|
152
|
+
### Environment examples
|
|
153
|
+
|
|
154
|
+
- Frontend: `NEXT_PUBLIC_FLUXYTE_API_KEY=pk_...`
|
|
155
|
+
- Backend: `FLUXYTE_API_KEY=sk_...`
|
|
156
|
+
|
|
157
|
+
Never expose `sk_*` in browser bundles, client logs, or public repos.
|
|
158
|
+
|
|
159
|
+
## Choose An Entrypoint
|
|
160
|
+
|
|
161
|
+
The SDK ships multiple entrypoints, all with the same API surface:
|
|
162
|
+
|
|
163
|
+
- `@fluxyte/sdk/react` (React hooks + provider)
|
|
164
|
+
- `@fluxyte/sdk/node` (server-side; validates `fetch` availability)
|
|
165
|
+
- `@fluxyte/sdk/vanilla` (browser usage without React)
|
|
166
|
+
- `@fluxyte/sdk` (base exports)
|
|
167
|
+
|
|
168
|
+
## Create A Client (Node / Vanilla)
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { OnboardingAIClient } from "@fluxyte/sdk/node";
|
|
172
|
+
|
|
173
|
+
const client = new OnboardingAIClient(process.env.FLUXYTE_API_KEY!);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Client Options (Session Handling)
|
|
177
|
+
|
|
178
|
+
The SDK enforces stable identity. Chat and voice accept top-level `sessionId` or
|
|
179
|
+
`userId`; onboarding events retain identity inside their event context.
|
|
180
|
+
|
|
181
|
+
- By default, it auto-generates and reuses `sessionId` when missing.
|
|
182
|
+
- You can disable this with `autoSessionId: false`.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
const client = new OnboardingAIClient(process.env.FLUXYTE_API_KEY!, {
|
|
186
|
+
autoSessionId: true, // default
|
|
187
|
+
sessionStorageKey: "fluxyte_onboarding_session_id", // browser storage key
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Chat Completions (Non-Streaming)
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
const res = await client.chat({
|
|
195
|
+
message: "How do I connect my database?",
|
|
196
|
+
sessionId: "sess_123",
|
|
197
|
+
context: {
|
|
198
|
+
stepSlug: "connect_database",
|
|
199
|
+
pageUrl: "https://app.example.com/setup/database",
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
console.log(res.answerId);
|
|
204
|
+
console.log(res.reply);
|
|
205
|
+
console.log(res.confidence);
|
|
206
|
+
console.log(res.sources);
|
|
207
|
+
console.log(res.resources);
|
|
208
|
+
console.log(res.commerce);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Product Catalogue and Commerce
|
|
212
|
+
|
|
213
|
+
When an organization has published catalogue items and its plan includes Commerce,
|
|
214
|
+
chat responses may include a structured presentation alongside the natural-language
|
|
215
|
+
reply:
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
for (const offering of res.commerce?.offerings ?? []) {
|
|
219
|
+
console.log(offering.name);
|
|
220
|
+
console.log(offering.priceAmountMinor, offering.currency);
|
|
221
|
+
console.log(offering.availability);
|
|
222
|
+
console.log(offering.features);
|
|
223
|
+
console.log(offering.actions);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (res.commerce?.hasMore) {
|
|
227
|
+
// Send a normal semantic continuation, such as "Show me more".
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The API returns at most five offerings for catalogue discovery at a time. Do not
|
|
232
|
+
implement client-side slicing or infer the next page; send the user's semantic
|
|
233
|
+
continuation so the server can advance durable Commerce state.
|
|
234
|
+
|
|
235
|
+
Catalogue actions are typed as:
|
|
236
|
+
|
|
237
|
+
- `EXTERNAL_CHECKOUT` — resolve through `openCommerceAction()`.
|
|
238
|
+
- `REQUEST_QUOTE` — send the action label/intention through chat.
|
|
239
|
+
- `CONTACT_SALES` — send the action label/intention through chat.
|
|
240
|
+
|
|
241
|
+
Only external checkout is a redirect. Never construct or cache checkout URLs from
|
|
242
|
+
catalogue data. Resolve the selected action immediately before navigation:
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
const action = offering.actions.find(
|
|
246
|
+
(candidate) => candidate.kind === "EXTERNAL_CHECKOUT",
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
if (action) {
|
|
250
|
+
const redirect = await client.openCommerceAction(action.id, "sess_123");
|
|
251
|
+
if (redirect.kind === "REDIRECT") {
|
|
252
|
+
window.location.assign(redirect.url);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Rich Content Resources
|
|
258
|
+
|
|
259
|
+
When approved knowledge or a flow step includes a related resource, the response
|
|
260
|
+
can contain:
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
type ContentResource = {
|
|
264
|
+
id: string;
|
|
265
|
+
kind: "VIDEO" | "AUDIO" | "STORE" | "REDIRECT" | "REFERRAL" | "CHECKOUT";
|
|
266
|
+
url: string;
|
|
267
|
+
label: string;
|
|
268
|
+
embedUrl?: string | null;
|
|
269
|
+
};
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Use `url` for links and actions. Use `embedUrl` only when it is present; it is
|
|
273
|
+
the server-approved URL intended for an embedded video or audio player.
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
for (const resource of res.resources ?? []) {
|
|
277
|
+
if (resource.embedUrl) {
|
|
278
|
+
renderEmbeddedMedia(resource.embedUrl, resource.label);
|
|
279
|
+
} else {
|
|
280
|
+
renderResourceLink(resource.url, resource.label);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Chat Completions (Streaming via SSE)
|
|
286
|
+
|
|
287
|
+
Streaming is useful when you want:
|
|
288
|
+
|
|
289
|
+
- live typing UX
|
|
290
|
+
- progressive rendering
|
|
291
|
+
- early access to `answerId` (for feedback)
|
|
292
|
+
|
|
293
|
+
Streaming lifecycle:
|
|
294
|
+
|
|
295
|
+
1. `meta` (contains `answerId`)
|
|
296
|
+
2. `delta` (partial text; one or more)
|
|
297
|
+
3. `done` (confidence, sources, resources, commerce)
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
const stop = client.streamChat(
|
|
301
|
+
{
|
|
302
|
+
message: "What's the next step?",
|
|
303
|
+
sessionId: "sess_123",
|
|
304
|
+
context: { stepSlug: "connect_database" },
|
|
305
|
+
},
|
|
306
|
+
(event) => {
|
|
307
|
+
if (event.type === "meta") console.log("Answer ID:", event.answerId);
|
|
308
|
+
if (event.type === "delta") process.stdout.write(event.replyDelta);
|
|
309
|
+
if (event.type === "done") {
|
|
310
|
+
console.log("\nConfidence:", event.confidence);
|
|
311
|
+
console.log("Sources:", event.sources);
|
|
312
|
+
console.log("Resources:", event.resources);
|
|
313
|
+
console.log("Commerce:", event.commerce);
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
(err) => {
|
|
317
|
+
// Optional: handle auth/network/server errors.
|
|
318
|
+
console.error("Streaming error:", err);
|
|
319
|
+
},
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
// stop() cancels streaming
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Voice Chat (Speech In + Optional Speech Out)
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
const voice = await client.voiceChat({
|
|
329
|
+
audioBase64: "BASE64_AUDIO",
|
|
330
|
+
mimeType: "audio/webm",
|
|
331
|
+
userId: "user_123",
|
|
332
|
+
context: { stepSlug: "connect_database", locale: "en-NG" },
|
|
333
|
+
synthesize: true,
|
|
334
|
+
voice: "alloy",
|
|
335
|
+
audioFormat: "mp3",
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
console.log(voice.transcript); // text recognized from audio
|
|
339
|
+
console.log(voice.reply); // AI text reply
|
|
340
|
+
console.log(voice.replyAudioBase64); // optional synthesized voice
|
|
341
|
+
console.log(voice.resources); // approved related links or embedded media
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Context
|
|
345
|
+
|
|
346
|
+
Context is optional for chat and voice requests. Identity is separate and required;
|
|
347
|
+
the SDK auto-generates a reusable `sessionId` unless `autoSessionId` is disabled.
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
type PublicChatContext = {
|
|
351
|
+
catalogueSubjectId?: string;
|
|
352
|
+
stepSlug?: string;
|
|
353
|
+
endpoint?: string;
|
|
354
|
+
pageUrl?: string;
|
|
355
|
+
fieldHelp?: {
|
|
356
|
+
fieldKey: string;
|
|
357
|
+
label?: string;
|
|
358
|
+
task?: string;
|
|
359
|
+
currentValue?: string;
|
|
360
|
+
};
|
|
361
|
+
error?: {
|
|
362
|
+
code?: string;
|
|
363
|
+
description?: string;
|
|
364
|
+
field?: string;
|
|
365
|
+
source?: "client" | "server" | "network" | "third_party";
|
|
366
|
+
httpStatus?: number;
|
|
367
|
+
retryable?: boolean;
|
|
368
|
+
};
|
|
369
|
+
attemptedAction?: {
|
|
370
|
+
name: string;
|
|
371
|
+
description?: string;
|
|
372
|
+
target?: string;
|
|
373
|
+
status?: "started" | "blocked" | "failed" | "completed";
|
|
374
|
+
};
|
|
375
|
+
sdk?: "react" | "node" | "vanilla" | "rest";
|
|
376
|
+
sdkVersion?: string;
|
|
377
|
+
appVersion?: string;
|
|
378
|
+
environment?: "development" | "staging" | "production";
|
|
379
|
+
locale?: string;
|
|
380
|
+
timezone?: string;
|
|
381
|
+
};
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Best practices:
|
|
385
|
+
|
|
386
|
+
- Pass `catalogueSubjectId` when the customer is viewing a published product or service.
|
|
387
|
+
- Pass `stepSlug` when the customer is inside a published onboarding step.
|
|
388
|
+
- Pass `fieldHelp` for headless field-level guidance. Your application owns the button, layout, and any field update.
|
|
389
|
+
- Keep `sessionId` and `userId` at the request's top level, outside context.
|
|
390
|
+
- Treat context like application state (update it as the user moves)
|
|
391
|
+
- For task assistance or troubleshooting, pass non-secret diagnostic context when known
|
|
392
|
+
|
|
393
|
+
Identity guidance:
|
|
394
|
+
|
|
395
|
+
- Anonymous visitors: let SDK auto-manage `sessionId` or pass your own persisted ID.
|
|
396
|
+
- Logged-in users: pass a stable top-level `userId`.
|
|
397
|
+
|
|
398
|
+
### Localization & Timezone
|
|
399
|
+
|
|
400
|
+
Pass optional localization and timezone fields so the API can tailor user-facing
|
|
401
|
+
formatting and time-aware utility responses:
|
|
402
|
+
|
|
403
|
+
```ts
|
|
404
|
+
context: {
|
|
405
|
+
locale: "en-US", // browser/client locale for user-facing formatting
|
|
406
|
+
timezone: "Africa/Lagos", // IANA timezone for the current user
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
- `locale` — browser/client locale (for example `en-US`, `en-NG`) used for user-facing formatting.
|
|
411
|
+
- `timezone` — IANA timezone for the current user (for example `America/New_York`, `Africa/Lagos`, `Europe/London`).
|
|
412
|
+
|
|
413
|
+
### Task and troubleshooting context
|
|
414
|
+
|
|
415
|
+
The public assistant can use structured context to understand the user's current task
|
|
416
|
+
and troubleshoot with fewer clarification turns. Pass only non-secret values:
|
|
417
|
+
|
|
418
|
+
```ts
|
|
419
|
+
await client.chat({
|
|
420
|
+
message: "I get a 401 when I send my first message",
|
|
421
|
+
userId: "user_123",
|
|
422
|
+
context: {
|
|
423
|
+
sdk: "react",
|
|
424
|
+
sdkVersion: "0.8.0",
|
|
425
|
+
appVersion: "2026.08.30",
|
|
426
|
+
environment: "production",
|
|
427
|
+
endpoint: "/v1/chat/completions",
|
|
428
|
+
pageUrl: "https://app.example.com/setup/chat",
|
|
429
|
+
error: {
|
|
430
|
+
code: "AUTHENTICATION_FAILED",
|
|
431
|
+
description: "The first chat request returned 401 after the user saved their public API key.",
|
|
432
|
+
source: "server",
|
|
433
|
+
httpStatus: 401,
|
|
434
|
+
retryable: false,
|
|
435
|
+
},
|
|
436
|
+
attemptedAction: {
|
|
437
|
+
name: "send_first_chat_message",
|
|
438
|
+
description: "Send the first message from the React setup screen.",
|
|
439
|
+
target: "Public AI chat",
|
|
440
|
+
status: "failed",
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
});
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
- `sdk` identifies the client or entrypoint in use.
|
|
447
|
+
- `sdkVersion` identifies the Fluxyte SDK version and `appVersion` the integrating app.
|
|
448
|
+
- `environment` is `development`, `staging`, or `production`.
|
|
449
|
+
- `endpoint` identifies the affected API route or operation.
|
|
450
|
+
- `error` carries structured, customer-safe diagnostics, including a comprehensive description.
|
|
451
|
+
- `attemptedAction` describes the action, target, and outcome without duplicating the user's message.
|
|
452
|
+
|
|
453
|
+
Do not put API keys, access tokens, passwords, request bodies containing personal
|
|
454
|
+
data, or other secrets in context.
|
|
455
|
+
|
|
456
|
+
### Headless field help
|
|
457
|
+
|
|
458
|
+
The SDK does not render field-help buttons or mutate form values. Build the UI that
|
|
459
|
+
fits your application and send the current field as context:
|
|
460
|
+
|
|
461
|
+
```ts
|
|
462
|
+
await client.chat({
|
|
463
|
+
message: "What should I enter here?",
|
|
464
|
+
context: {
|
|
465
|
+
stepSlug: "business-details",
|
|
466
|
+
pageUrl: window.location.href,
|
|
467
|
+
fieldHelp: {
|
|
468
|
+
fieldKey: "annualRevenue",
|
|
469
|
+
label: "Annual revenue",
|
|
470
|
+
task: "Completing a business loan application",
|
|
471
|
+
currentValue: "50000",
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
`fieldHelp` improves routing but is not evidence. When `stepSlug` resolves to an
|
|
478
|
+
authored input field, its server-owned definition remains authoritative. Never send
|
|
479
|
+
passwords, tokens, payment credentials, identity secrets, or other sensitive values.
|
|
480
|
+
|
|
481
|
+
#### Field-help properties
|
|
482
|
+
|
|
483
|
+
| Property | Required | Purpose |
|
|
484
|
+
| --- | --- | --- |
|
|
485
|
+
| `fieldKey` | Yes | Stable form or property key used to identify the field. |
|
|
486
|
+
| `label` | No | Customer-visible label that helps interpret unfamiliar field keys. |
|
|
487
|
+
| `task` | No | Short description of the form or task the customer is completing. |
|
|
488
|
+
| `currentValue` | No | Non-sensitive value useful for explaining formatting or validation. |
|
|
489
|
+
|
|
490
|
+
Use `stepSlug` whenever the field belongs to a published Fluxyte flow step. Public AI
|
|
491
|
+
validates that step against the organization's catalogue and uses its authored input
|
|
492
|
+
definition when the `fieldKey` matches. Without `stepSlug`, field help can still use
|
|
493
|
+
approved Knowledge content, but the client-provided label, task, and value never become
|
|
494
|
+
authoritative evidence.
|
|
495
|
+
|
|
496
|
+
Field-help requests continue through the standard Public AI architecture:
|
|
497
|
+
|
|
498
|
+
- Flow or Task Assist handles guidance tied to an authored flow step.
|
|
499
|
+
- Knowledge handles documented field meaning and requirements.
|
|
500
|
+
- Troubleshooting handles rejected values and field-related errors.
|
|
501
|
+
- Utility is not selected merely because a field contains a number, date, or currency.
|
|
502
|
+
- The normal evidence, policy, multilingual, and response-composition stages remain active.
|
|
503
|
+
|
|
504
|
+
The same context works with `chat`, `streamChat`, and `voiceChat`:
|
|
505
|
+
|
|
506
|
+
```ts
|
|
507
|
+
const context: PublicChatContext = {
|
|
508
|
+
stepSlug: "business-details",
|
|
509
|
+
fieldHelp: {
|
|
510
|
+
fieldKey: "annualRevenue",
|
|
511
|
+
label: "Annual revenue",
|
|
512
|
+
task: "Completing a business loan application",
|
|
513
|
+
},
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
const answer = await client.chat({
|
|
517
|
+
message: "What does this field mean?",
|
|
518
|
+
context,
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
const stop = client.streamChat(
|
|
522
|
+
{ message: "What format should I use?", context },
|
|
523
|
+
(event) => console.log(event),
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
const voice = await client.voiceChat({
|
|
527
|
+
audioBase64,
|
|
528
|
+
mimeType: "audio/webm",
|
|
529
|
+
context,
|
|
530
|
+
});
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Your application decides whether field help appears as an icon, tooltip, side panel,
|
|
534
|
+
chat prompt, or another interface. Responses are guidance only: do not update a field
|
|
535
|
+
unless your application explicitly validates the value and the customer accepts it.
|
|
536
|
+
|
|
537
|
+
Security rules:
|
|
538
|
+
|
|
539
|
+
- Omit `currentValue` unless it materially improves the answer.
|
|
540
|
+
- Never send passwords, passcodes, tokens, API keys, PINs, OTPs, card details,
|
|
541
|
+
government identifiers, private documents, or hidden form values.
|
|
542
|
+
- Prefer a customer-safe error description through `context.error` when troubleshooting.
|
|
543
|
+
- Keep stable user/session identity at the request top level, not inside `fieldHelp`.
|
|
544
|
+
|
|
545
|
+
## Onboarding Events
|
|
546
|
+
|
|
547
|
+
Events power onboarding analytics, drop-off detection, and AI insights.
|
|
548
|
+
|
|
549
|
+
Supported event types:
|
|
550
|
+
|
|
551
|
+
1. `FLOW_STARTED`
|
|
552
|
+
|
|
553
|
+
- User begins a tracked onboarding flow.
|
|
554
|
+
- Send once when the flow is entered.
|
|
555
|
+
|
|
556
|
+
2. `STEP_VIEWED`
|
|
557
|
+
|
|
558
|
+
- User lands on or opens a specific step.
|
|
559
|
+
- Send whenever the current step changes.
|
|
560
|
+
|
|
561
|
+
3. `STEP_COMPLETED`
|
|
562
|
+
|
|
563
|
+
- User successfully completes a step.
|
|
564
|
+
- Send only after verified completion signal.
|
|
565
|
+
|
|
566
|
+
4. `FLOW_COMPLETED`
|
|
567
|
+
|
|
568
|
+
- User completes all required steps in the flow.
|
|
569
|
+
- Send once at successful finish.
|
|
570
|
+
|
|
571
|
+
5. `ABANDONED`
|
|
572
|
+
|
|
573
|
+
- User exits/stalls before completion.
|
|
574
|
+
- Send when inactivity timeout or explicit exit indicates drop-off.
|
|
575
|
+
|
|
576
|
+
Recommended minimum context for event quality:
|
|
577
|
+
|
|
578
|
+
- `flowId`
|
|
579
|
+
- `stepId` (for step-level events)
|
|
580
|
+
- stable identity (`context.sessionId` or `context.userId`)
|
|
581
|
+
|
|
582
|
+
Typical event sequence:
|
|
583
|
+
|
|
584
|
+
1. `FLOW_STARTED`
|
|
585
|
+
2. `STEP_VIEWED` (step 1)
|
|
586
|
+
3. `STEP_COMPLETED` (step 1)
|
|
587
|
+
4. `STEP_VIEWED` (step 2)
|
|
588
|
+
5. `STEP_COMPLETED` (step 2)
|
|
589
|
+
6. `FLOW_COMPLETED`
|
|
590
|
+
|
|
591
|
+
Drop-off sequence example:
|
|
592
|
+
|
|
593
|
+
1. `FLOW_STARTED`
|
|
594
|
+
2. `STEP_VIEWED` (step 1)
|
|
595
|
+
3. `STEP_VIEWED` (step 2)
|
|
596
|
+
4. `ABANDONED`
|
|
597
|
+
|
|
598
|
+
```ts
|
|
599
|
+
await client.sendEvent({
|
|
600
|
+
type: "STEP_COMPLETED",
|
|
601
|
+
context: {
|
|
602
|
+
flowId: "premium-support-setup",
|
|
603
|
+
stepId: "connect-database",
|
|
604
|
+
userId: "customer_123",
|
|
605
|
+
},
|
|
606
|
+
});
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
## Feedback
|
|
610
|
+
|
|
611
|
+
```ts
|
|
612
|
+
await client.submitFeedback({
|
|
613
|
+
answerId: "ans_7xk9p2m",
|
|
614
|
+
rating: "GOOD",
|
|
615
|
+
comment: "Clear explanation and actionable advice",
|
|
616
|
+
});
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
## React Usage (Recommended)
|
|
620
|
+
|
|
621
|
+
```tsx
|
|
622
|
+
import { OnboardingAIClient } from "@fluxyte/sdk";
|
|
623
|
+
import { OnboardingAIProvider } from "@fluxyte/sdk/react";
|
|
624
|
+
|
|
625
|
+
const client = new OnboardingAIClient(import.meta.env.VITE_FLUXYTE_API_KEY);
|
|
626
|
+
|
|
627
|
+
export function App() {
|
|
628
|
+
return (
|
|
629
|
+
<OnboardingAIProvider client={client}>
|
|
630
|
+
{/* your app */}
|
|
631
|
+
</OnboardingAIProvider>
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### React Hooks
|
|
637
|
+
|
|
638
|
+
```tsx
|
|
639
|
+
import { useChat } from "@fluxyte/sdk/react";
|
|
640
|
+
|
|
641
|
+
const { send, data, loading, error } = useChat();
|
|
642
|
+
|
|
643
|
+
await send({
|
|
644
|
+
message: "How do I connect my database?",
|
|
645
|
+
sessionId: "sess_123",
|
|
646
|
+
context: { stepSlug: "connect_database" },
|
|
647
|
+
});
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
```tsx
|
|
651
|
+
import { useStreamingChat } from "@fluxyte/sdk/react";
|
|
652
|
+
|
|
653
|
+
const { text, answerId, confidence, resources, commerce, streaming, start, stop } =
|
|
654
|
+
useStreamingChat();
|
|
655
|
+
|
|
656
|
+
start({
|
|
657
|
+
message: "What's the next step?",
|
|
658
|
+
context: { stepSlug: "connect_database" },
|
|
659
|
+
});
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
```tsx
|
|
663
|
+
import { useVoiceChat } from "@fluxyte/sdk/react";
|
|
664
|
+
|
|
665
|
+
const { sendVoice, loading, data, error } = useVoiceChat();
|
|
666
|
+
|
|
667
|
+
const res = await sendVoice({
|
|
668
|
+
audioBase64: "BASE64_AUDIO",
|
|
669
|
+
mimeType: "audio/webm",
|
|
670
|
+
context: { stepSlug: "connect_database" },
|
|
671
|
+
synthesize: true,
|
|
672
|
+
voice: "alloy",
|
|
673
|
+
audioFormat: "mp3",
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
console.log(res.transcript);
|
|
677
|
+
console.log(res.reply);
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
## Multi-Target
|
|
681
|
+
|
|
682
|
+
Use `context.product` or `context.service` to isolate onboarding targets under one account (apps, APIs, and services).
|
|
683
|
+
|
|
684
|
+
## Error Handling
|
|
685
|
+
|
|
686
|
+
```ts
|
|
687
|
+
import { APIError } from "@fluxyte/sdk";
|
|
688
|
+
|
|
689
|
+
try {
|
|
690
|
+
await client.chat(/* ... */);
|
|
691
|
+
} catch (err) {
|
|
692
|
+
if (err instanceof APIError) {
|
|
693
|
+
console.error(err.status, err.message);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
## License
|
|
699
|
+
|
|
700
|
+
Commercial. See `LICENSE.md`.
|