@chatbotkit/react 1.6.0 → 1.8.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.
Files changed (41) hide show
  1. package/README.md +198 -9
  2. package/dist/cjs/actions/complete.cjs +178 -0
  3. package/dist/cjs/actions/complete.d.ts +38 -0
  4. package/dist/cjs/components/ConversationManager.cjs +26 -0
  5. package/dist/cjs/components/ConversationManager.d.ts +5 -0
  6. package/dist/cjs/hooks/useConversationManager.cjs +99 -114
  7. package/dist/cjs/hooks/useConversationManager.d.ts +13 -52
  8. package/dist/cjs/hooks/useConversationManagerRemote.cjs +83 -0
  9. package/dist/cjs/hooks/useConversationManagerRemote.d.ts +20 -0
  10. package/dist/cjs/hooks/useConversationManagerState.cjs +32 -0
  11. package/dist/cjs/hooks/useConversationManagerState.d.ts +10 -0
  12. package/dist/cjs/hooks/useConversationManagerStateReducer.cjs +112 -0
  13. package/dist/cjs/hooks/useConversationManagerStateReducer.d.ts +42 -0
  14. package/dist/cjs/index.cjs +4 -1
  15. package/dist/cjs/index.d.ts +1 -0
  16. package/dist/cjs/utils/it.cjs +9 -0
  17. package/dist/cjs/utils/it.d.ts +1 -0
  18. package/dist/cjs/utils/stream.cjs +2 -2
  19. package/dist/cjs/utils/stream.d.ts +6 -7
  20. package/dist/esm/actions/complete.d.ts +38 -0
  21. package/dist/esm/actions/complete.js +173 -0
  22. package/dist/esm/components/AutoScroller.js +1 -1
  23. package/dist/esm/components/ConversationManager.d.ts +5 -0
  24. package/dist/esm/components/ConversationManager.js +21 -0
  25. package/dist/esm/hooks/useConversationManager.d.ts +13 -52
  26. package/dist/esm/hooks/useConversationManager.js +99 -114
  27. package/dist/esm/hooks/useConversationManagerRemote.d.ts +20 -0
  28. package/dist/esm/hooks/useConversationManagerRemote.js +78 -0
  29. package/dist/esm/hooks/useConversationManagerState.d.ts +10 -0
  30. package/dist/esm/hooks/useConversationManagerState.js +27 -0
  31. package/dist/esm/hooks/useConversationManagerStateReducer.d.ts +42 -0
  32. package/dist/esm/hooks/useConversationManagerStateReducer.js +105 -0
  33. package/dist/esm/index.d.ts +1 -0
  34. package/dist/esm/index.js +1 -0
  35. package/dist/esm/utils/it.d.ts +1 -0
  36. package/dist/esm/utils/it.js +5 -0
  37. package/dist/esm/utils/stream.d.ts +6 -7
  38. package/dist/esm/utils/stream.js +2 -2
  39. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  40. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  41. package/package.json +122 -2
@@ -1,7 +1,6 @@
1
- export function stream(source: any): Promise<any>;
2
- export function consume(source: any): {
3
- [Symbol.asyncIterator]: () => {
4
- current: any;
5
- next(): Promise<any>;
6
- };
7
- };
1
+ export function stream(source: StreamSource): StreamResult;
2
+ export function consume(source: ConsumeSource): ConsumeResult;
3
+ export type StreamSource = any;
4
+ export type StreamResult = any;
5
+ export type ConsumeSource = any;
6
+ export type ConsumeResult = any;
@@ -0,0 +1,38 @@
1
+ export function streamComplete(options: Options): import('../utils/stream.js').StreamResult;
2
+ export default complete;
3
+ export type ReactElement = import('react').ReactElement;
4
+ export type ReactNode = import('react').ReactNode;
5
+ export type BasicParametersSchema = Record<string, any>;
6
+ export type ValidatingParametersSchema = {
7
+ schema: BasicParametersSchema;
8
+ validate(value: any): Promise<{
9
+ valid: boolean;
10
+ error?: Error;
11
+ }>;
12
+ };
13
+ export type InputMessage = {
14
+ type: 'bot' | 'user' | 'context' | 'instruction' | 'backstory' | 'activity';
15
+ text: string;
16
+ meta?: Record<string, any>;
17
+ };
18
+ export type RenderFunction = () => AsyncGenerator<ReactNode> | ReactNode | Promise<ReactNode>;
19
+ export type HandlerArgs = any;
20
+ export type HandlerResult = string | ReactElement | {
21
+ text?: string;
22
+ children?: ReactNode;
23
+ render: RenderFunction;
24
+ result?: any;
25
+ };
26
+ export type InputFunction = {
27
+ name: string;
28
+ description: string;
29
+ parameters: BasicParametersSchema | ValidatingParametersSchema;
30
+ handler?: ((args: HandlerArgs) => Promise<HandlerResult>) | undefined;
31
+ };
32
+ export type Options = Omit<import('@chatbotkit/sdk/conversation/v1.js').ConversationCompleteRequest, 'messages' | 'functions'> & {
33
+ client: import('@chatbotkit/sdk').ConversationClient;
34
+ messages: InputMessage[];
35
+ functions?: (InputFunction | (() => InputFunction))[];
36
+ maxRecusion?: number;
37
+ };
38
+ declare function complete({ client, messages, functions, maxRecusion, ...options }: Options): any;
@@ -0,0 +1,173 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { isValidElement } from 'react';
3
+ import { isAsyncGenerator } from '../utils/it.js';
4
+ import { stream } from '../utils/stream.js';
5
+ import { getRandomId } from '../utils/string.js';
6
+ async function* complete({ client, messages, functions, maxRecusion = 3, ...options }) {
7
+ if (maxRecusion <= 0) {
8
+ return;
9
+ }
10
+ messages = messages.slice(0);
11
+ const functionDefinitions = functions?.map((fn) => {
12
+ if (typeof fn === 'function') {
13
+ return fn();
14
+ }
15
+ else {
16
+ return fn;
17
+ }
18
+ });
19
+ let it;
20
+ if (!it) {
21
+ const lastMessage = messages[messages.length - 1];
22
+ if (lastMessage) {
23
+ if (lastMessage.type === 'activity') {
24
+ if (lastMessage.meta?.activity?.type === 'request') {
25
+ messages.pop();
26
+ it = [{ type: 'message', data: lastMessage }];
27
+ }
28
+ }
29
+ }
30
+ }
31
+ if (!it) {
32
+ it = client
33
+ .complete(null, {
34
+ ...options,
35
+ messages: messages.map(({ type, text, meta }) => {
36
+ return {
37
+ type,
38
+ text,
39
+ meta,
40
+ };
41
+ }),
42
+ functions: functionDefinitions?.map(({ name, description, parameters }) => {
43
+ return {
44
+ name,
45
+ description,
46
+ parameters: parameters.schema ? parameters.schema : parameters,
47
+ };
48
+ }),
49
+ })
50
+ .stream();
51
+ }
52
+ if (!it) {
53
+ throw new Error('No stream iterator');
54
+ }
55
+ for await (const item of it) {
56
+ yield item;
57
+ const { type, data } = item;
58
+ if (type === 'message') {
59
+ const message = data;
60
+ messages.push(message);
61
+ if (message.meta?.activity?.type === 'request') {
62
+ const name = message.meta.activity.function?.name;
63
+ const args = message.meta.activity.function?.arguments;
64
+ const fn = functionDefinitions?.find((fn) => fn.name === name);
65
+ if (fn && typeof fn.handler === 'function') {
66
+ if (fn.parameters.validate) {
67
+ const { valid, error } = await fn.parameters.validate(args);
68
+ if (!valid) {
69
+ throw error || new Error('Invalid arguments');
70
+ }
71
+ }
72
+ const output = await fn.handler(args);
73
+ let text;
74
+ let children;
75
+ let result;
76
+ let render;
77
+ if (typeof output === 'string') {
78
+ text = undefined;
79
+ children = undefined;
80
+ render = undefined;
81
+ result = output;
82
+ }
83
+ else if (isValidElement(output)) {
84
+ text = '';
85
+ children = output;
86
+ render = undefined;
87
+ result = undefined;
88
+ }
89
+ else {
90
+ if (typeof output?.text === 'string') {
91
+ text = output.text;
92
+ }
93
+ if (isValidElement(output?.children)) {
94
+ children = output.children;
95
+ }
96
+ if (typeof output?.render === 'function') {
97
+ render = output.render;
98
+ }
99
+ if (output?.result) {
100
+ result = output.result;
101
+ }
102
+ }
103
+ if (text || children) {
104
+ yield {
105
+ type: 'message',
106
+ data: {
107
+ type: 'bot',
108
+ text: text ? text : '',
109
+ children: children ? _jsx(_Fragment, { children: children }) : undefined,
110
+ },
111
+ };
112
+ }
113
+ else if (text || render) {
114
+ const result = await render?.();
115
+ if (isAsyncGenerator(result)) {
116
+ const id = getRandomId('tmp-');
117
+ for await (const item of (result)) {
118
+ yield {
119
+ type: 'message',
120
+ data: {
121
+ id: id,
122
+ type: 'bot',
123
+ text: text ? text : '',
124
+ children: item,
125
+ },
126
+ };
127
+ }
128
+ }
129
+ else {
130
+ yield {
131
+ type: 'message',
132
+ data: {
133
+ type: 'bot',
134
+ text: text ? text : '',
135
+ children: _jsx(_Fragment, { children: result }),
136
+ },
137
+ };
138
+ }
139
+ }
140
+ if (result) {
141
+ const activityMessage = {
142
+ type: 'activity',
143
+ text: '',
144
+ meta: {
145
+ activity: {
146
+ type: 'response',
147
+ function: {
148
+ name,
149
+ arguments: args,
150
+ result: JSON.stringify(result),
151
+ },
152
+ },
153
+ },
154
+ };
155
+ yield { type: 'message', data: activityMessage };
156
+ messages.push(activityMessage);
157
+ yield* complete({
158
+ ...options,
159
+ client,
160
+ messages,
161
+ functions,
162
+ maxRecusion: maxRecusion - 1,
163
+ });
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ export function streamComplete(options) {
171
+ return stream(complete(options));
172
+ }
173
+ export default complete;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useRef, useEffect } from 'react';
2
+ import React, { useEffect, useRef } from 'react';
3
3
  function AutoScrollAnchor() {
4
4
  return _jsx("div", { className: "auto-scroll-anchor", style: { height: '1px' } });
5
5
  }
@@ -0,0 +1,5 @@
1
+ export function ConversationManager({ children, ...options }: import('../hooks/useConversationManager.js').UseConversationManagerOptions & {
2
+ children: import('react').ReactNode;
3
+ }): import('react').ReactElement;
4
+ export const ConversationContext: import("react").Context<import("../hooks/useConversationManager.js").UseConversationManagerResult>;
5
+ export default ConversationManager;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext } from 'react';
3
+ import useConversationManager from '../hooks/useConversationManager.js';
4
+ export const ConversationContext = createContext(({
5
+ message: null,
6
+ messages: [],
7
+ thinking: false,
8
+ typing: false,
9
+ text: '',
10
+ setText: () => { },
11
+ error: null,
12
+ setError: () => { },
13
+ submit: () => { },
14
+ trigger: () => { },
15
+ request: () => { },
16
+ }));
17
+ export function ConversationManager({ children, ...options }) {
18
+ const manager = useConversationManager(options);
19
+ return (_jsx(ConversationContext.Provider, { value: manager, children: children }));
20
+ }
21
+ export default ConversationManager;
@@ -1,57 +1,18 @@
1
- export function useConversationManager(options: {
2
- [key: string]: any;
3
- client?: ConversationClient | undefined;
4
- endpoint?: string | EndpointFunction | undefined;
5
- token?: string | undefined;
6
- conversationId?: string | undefined;
7
- backstory?: string | undefined;
8
- Model?: string | undefined;
9
- datasetId?: string | undefined;
10
- skillsetId?: string | undefined;
11
- }): {
12
- token: string | undefined;
13
- setToken: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
14
- conversationId: string | undefined;
15
- setConversationId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
16
- backstory: string | undefined;
17
- setBackstory: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
18
- model: any;
19
- setModel: import("react").Dispatch<any>;
20
- datasetId: string | undefined;
21
- setDatasetId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
22
- skillsetId: string | undefined;
23
- setSkillsetId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
24
- text: string;
25
- setText: import("react").Dispatch<import("react").SetStateAction<string>>;
1
+ export function useConversationManager({ ...conversationManagerRemoteOptions }: UseConversationManagerOptions): UseConversationManagerResult;
2
+ export default useConversationManager;
3
+ export type Message = import('@chatbotkit/sdk/conversation/v1').Message;
4
+ export type UseConversationManagerRemoteOptions = import('./useConversationManagerRemote.js').UseConversationManagerRemoteOptions;
5
+ export type UseConversationManagerOptions = UseConversationManagerRemoteOptions & {};
6
+ export type UseConversationManagerResult = {
7
+ message: Message | null;
26
8
  messages: Message[];
27
- setMessages: import("react").Dispatch<import("react").SetStateAction<Message[]>>;
28
9
  thinking: boolean;
29
- setThinking: import("react").Dispatch<import("react").SetStateAction<boolean>>;
30
10
  typing: boolean;
31
- setTyping: import("react").Dispatch<import("react").SetStateAction<boolean>>;
32
- error: any;
33
- setError: import("react").Dispatch<any>;
34
- submit: () => Promise<void>;
35
- };
36
- export default useConversationManager;
37
- export type ModelConfig = {
38
- maxTokens?: number;
39
- temperature?: number;
40
- frequencyPenalty?: number;
41
- presencePenalty?: number;
42
- seed?: number;
43
- interactionMaxMessages?: number;
44
- region?: 'us' | 'eu';
45
- };
46
- export type Model = string | {
47
- name: string;
48
- config?: ModelConfig;
49
- };
50
- export type Message = {
51
- id: string;
52
- type: 'bot' | 'user';
53
11
  text: string;
12
+ setText: (text: string) => void;
13
+ error: any;
14
+ setError: (error: any) => void;
15
+ submit: () => void;
16
+ trigger: (name: string) => void;
17
+ request: (name: string, args: any) => void;
54
18
  };
55
- export type EndpointURL = string;
56
- export type EndpointFunction = (conversationId: any, request: any) => AsyncGenerator<any>;
57
- import { ConversationClient } from '@chatbotkit/sdk';
@@ -1,138 +1,123 @@
1
- import { useMemo, useState } from 'react';
2
- import { ConversationClient } from '@chatbotkit/sdk';
3
- import { getRandomId } from '../utils/string.js';
4
- import { cloneAndExtend } from '../utils/object.js';
5
- import { consume } from '../utils/stream.js';
6
- export function useConversationManager(options) {
7
- const { client: _client, endpoint, token: _token, conversationId: _conversationId, backstory: _backstory, model: _model, datasetId: _datasetId, skillsetId: _skillsetId, ...rest } = options;
8
- const [token, setToken] = useState(_token);
9
- const [conversationId, setConversationId] = useState(_conversationId);
10
- const [backstory, setBackstory] = useState(_backstory);
11
- const [model, setModel] = useState(_model);
12
- const [datasetId, setDatasetId] = useState(_datasetId);
13
- const [skillsetId, setSkillsetId] = useState(_skillsetId);
14
- const client = useMemo(() => {
15
- if (typeof endpoint === 'function') {
16
- return {
17
- complete(conversationId, options) {
18
- return {
19
- async *stream() {
20
- yield* consume(endpoint(conversationId, options));
21
- },
22
- };
23
- },
24
- };
25
- }
26
- const options = { ...rest, secret: token || '' };
27
- let thisClient = _client || new ConversationClient(options);
28
- const extension = {};
29
- if (typeof endpoint === 'string') {
30
- extension.url = new URL(globalThis.window?.location?.origin || 'about:blank');
31
- extension.endpoints = {
32
- '/api/v1/conversation/complete': endpoint,
33
- };
34
- }
35
- if (token) {
36
- extension.secret = token;
37
- }
38
- if (Object.keys(extension).length === 0) {
39
- return thisClient;
40
- }
41
- else {
42
- return cloneAndExtend(thisClient, extension);
43
- }
44
- }, [_client, endpoint, token]);
1
+ import { useState } from 'react';
2
+ import useConversationManagerRemote from './useConversationManagerRemote.js';
3
+ import { useConversationManagerState } from './useConversationManagerState.js';
4
+ export function useConversationManager({ ...conversationManagerRemoteOptions }) {
5
+ const remote = useConversationManagerRemote(conversationManagerRemoteOptions);
6
+ const [{ thinking, typing, message, messages, }, { setThinking, setTyping, appendText, appendMessage, },] = useConversationManagerState();
45
7
  const [text, setText] = useState((''));
46
- const [messages, setMessages] = useState(([]));
47
- const [thinking, setThinking] = useState(false);
48
- const [typing, setTyping] = useState(false);
49
8
  const [error, setError] = useState((null));
50
- async function submit() {
51
- if (!text) {
52
- return;
53
- }
54
- setText('');
55
- const userMessage = {
56
- id: getRandomId('message-'),
57
- type: 'user',
58
- text: text,
59
- };
60
- let newMessages = messages.slice(0);
61
- newMessages = [...newMessages, userMessage];
62
- setMessages([...newMessages]);
63
- setThinking(true);
64
- let it;
9
+ async function stream(newMessages) {
10
+ const allMessages = [
11
+ ...messages.map(({ type, text, meta }) => {
12
+ return {
13
+ type,
14
+ text,
15
+ meta,
16
+ };
17
+ }),
18
+ ...(newMessages?.map(({ type, text, meta }) => {
19
+ return {
20
+ type,
21
+ text,
22
+ meta,
23
+ };
24
+ }) || []),
25
+ ].slice(-100);
65
26
  try {
66
- if (conversationId) {
67
- it = client.complete(conversationId, { text });
68
- }
69
- else {
70
- it = client.complete(null, {
71
- backstory: backstory,
72
- model: model,
73
- datasetId: datasetId,
74
- skillsetId: skillsetId,
75
- messages: newMessages.slice(-100),
76
- });
77
- }
78
- }
79
- catch (e) {
80
- setThinking(false);
81
- setError(e);
82
- return;
83
- }
84
- const botMessage = {
85
- id: getRandomId('message-'),
86
- type: 'bot',
87
- text: '',
88
- };
89
- let alreadyStreaming = false;
90
- try {
91
- for await (const event of it.stream()) {
92
- if (event.type === 'token') {
93
- if (!alreadyStreaming) {
94
- alreadyStreaming = true;
95
- newMessages = [...newMessages, botMessage];
96
- setMessages(newMessages);
97
- setThinking(false);
98
- setTyping(true);
27
+ setThinking(true);
28
+ setError(null);
29
+ for await (const item of remote(allMessages)) {
30
+ switch (item.type) {
31
+ case 'token': {
32
+ appendText(item.data.token);
33
+ break;
34
+ }
35
+ case 'message': {
36
+ appendMessage(item.data);
37
+ break;
99
38
  }
100
- botMessage.text += event.data.token;
101
- setMessages([...newMessages]);
102
39
  }
103
40
  }
104
41
  }
105
42
  catch (e) {
106
43
  setError(e);
44
+ if (typeof process !== 'undefined' &&
45
+ process.env.NODE_ENV === 'development') {
46
+ console.error(e);
47
+ }
107
48
  }
108
49
  finally {
50
+ setThinking(false);
109
51
  setTyping(false);
110
52
  }
111
53
  }
54
+ async function submit(thisText) {
55
+ if (thinking || typing) {
56
+ return;
57
+ }
58
+ if (!thisText) {
59
+ if (!text) {
60
+ return;
61
+ }
62
+ thisText = text;
63
+ setText('');
64
+ }
65
+ const userMessage = {
66
+ type: 'user',
67
+ text: thisText,
68
+ };
69
+ appendMessage(userMessage);
70
+ await stream([userMessage]);
71
+ }
72
+ async function trigger(name) {
73
+ if (thinking || typing) {
74
+ return;
75
+ }
76
+ const activityMessage = {
77
+ type: 'activity',
78
+ text: '',
79
+ meta: {
80
+ activity: {
81
+ type: 'trigger',
82
+ function: {
83
+ name: name,
84
+ },
85
+ },
86
+ },
87
+ };
88
+ await stream([activityMessage]);
89
+ }
90
+ async function request(name, args) {
91
+ if (thinking || typing) {
92
+ return;
93
+ }
94
+ const activityMessage = {
95
+ type: 'activity',
96
+ text: '',
97
+ meta: {
98
+ activity: {
99
+ type: 'request',
100
+ function: {
101
+ name: name,
102
+ arguments: args,
103
+ },
104
+ },
105
+ },
106
+ };
107
+ await stream([activityMessage]);
108
+ }
112
109
  return {
113
- token,
114
- setToken,
115
- conversationId,
116
- setConversationId,
117
- backstory,
118
- setBackstory,
119
- model,
120
- setModel,
121
- datasetId,
122
- setDatasetId,
123
- skillsetId,
124
- setSkillsetId,
125
- text,
126
- setText,
110
+ message,
127
111
  messages,
128
- setMessages,
129
112
  thinking,
130
- setThinking,
131
113
  typing,
132
- setTyping,
114
+ text,
115
+ setText,
133
116
  error,
134
117
  setError,
135
118
  submit,
119
+ trigger,
120
+ request,
136
121
  };
137
122
  }
138
123
  export default useConversationManager;
@@ -0,0 +1,20 @@
1
+ export function useConversationManagerRemote({ client: _client, endpoint, conversationId, token, backstory, model, datasetId, skillsetId, privacy, moderation, ...rest }: UseConversationManagerRemoteOptions): UseConversationManagerRemoteResult;
2
+ export default useConversationManagerRemote;
3
+ export type Message = import('@chatbotkit/sdk/conversation/v1').Message;
4
+ export type Model = import('@chatbotkit/sdk/model/v1').Model;
5
+ export type EndpointURL = string;
6
+ export type EndpointFunction = (options: any) => AsyncGenerator<any>;
7
+ export type UseConversationManagerRemoteOptions = {
8
+ client?: ConversationClient;
9
+ endpoint?: EndpointURL | EndpointFunction;
10
+ conversationId?: string;
11
+ token?: string;
12
+ backstory?: string;
13
+ model?: Model;
14
+ datasetId?: string;
15
+ skillsetId?: string;
16
+ privacy?: boolean;
17
+ moderation?: boolean;
18
+ };
19
+ export type UseConversationManagerRemoteResult = (messages: Message[]) => AsyncGenerator<any, void, any>;
20
+ import { ConversationClient } from '@chatbotkit/sdk';
@@ -0,0 +1,78 @@
1
+ import { useMemo } from 'react';
2
+ import { cloneAndExtend } from '../utils/object.js';
3
+ import { consume } from '../utils/stream.js';
4
+ import { ConversationClient } from '@chatbotkit/sdk';
5
+ export function useConversationManagerRemote({ client: _client, endpoint, conversationId, token, backstory, model, datasetId, skillsetId, privacy, moderation, ...rest }) {
6
+ const client = useMemo(() => {
7
+ if (typeof endpoint === 'function') {
8
+ return {
9
+ complete(conversationId, options) {
10
+ return {
11
+ async *stream() {
12
+ yield* consume(endpoint(options));
13
+ },
14
+ };
15
+ },
16
+ };
17
+ }
18
+ const options = { ...rest, secret: token || '' };
19
+ let thisClient = _client || new ConversationClient(options);
20
+ const extension = {};
21
+ if (typeof endpoint === 'string') {
22
+ extension.url = new URL(globalThis.window?.location?.origin || 'about:blank');
23
+ extension.endpoints = {
24
+ '/api/v1/conversation/complete': endpoint,
25
+ };
26
+ }
27
+ if (token) {
28
+ extension.secret = token;
29
+ }
30
+ if (Object.keys(extension).length === 0) {
31
+ return thisClient;
32
+ }
33
+ else {
34
+ return cloneAndExtend(thisClient, extension);
35
+ }
36
+ }, [_client, endpoint, token]);
37
+ const remote = useMemo(() => {
38
+ if (conversationId) {
39
+ return (async function* (messages) {
40
+ const lastUserMessage = [...messages]
41
+ .reverse()
42
+ .find((message) => message.type === 'user');
43
+ if (!lastUserMessage) {
44
+ throw new Error('No user message found');
45
+ }
46
+ yield* client
47
+ .complete(conversationId, { text: lastUserMessage.text })
48
+ .stream();
49
+ });
50
+ }
51
+ else {
52
+ return (async function* (messages) {
53
+ yield* client
54
+ .complete(null, {
55
+ backstory: backstory,
56
+ model: model,
57
+ datasetId: datasetId,
58
+ skillsetId: skillsetId,
59
+ privacy: privacy,
60
+ moderation: moderation,
61
+ messages: messages,
62
+ })
63
+ .stream();
64
+ });
65
+ }
66
+ }, [
67
+ client,
68
+ conversationId,
69
+ backstory,
70
+ model,
71
+ datasetId,
72
+ skillsetId,
73
+ privacy,
74
+ moderation,
75
+ ]);
76
+ return remote;
77
+ }
78
+ export default useConversationManagerRemote;