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