@copilotkit/react-ui 0.36.0-mme-push-to-talk.0 → 0.36.0-mme-pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +174 -167
- package/CHANGELOG.md +12 -0
- package/dist/{chunk-DMAQBCTX.mjs → chunk-4MKP23AD.mjs} +6 -4
- package/dist/chunk-4MKP23AD.mjs.map +1 -0
- package/dist/{chunk-UVMROYDT.mjs → chunk-6XLZXLM5.mjs} +5 -5
- package/dist/{chunk-UVMROYDT.mjs.map → chunk-6XLZXLM5.mjs.map} +1 -1
- package/dist/{chunk-XYM43AHP.mjs → chunk-7FES2IQA.mjs} +3 -3
- package/dist/chunk-ANO23V2M.mjs +135 -0
- package/dist/chunk-ANO23V2M.mjs.map +1 -0
- package/dist/{chunk-DRNCOXZO.mjs → chunk-BL65ZC6L.mjs} +28 -7
- package/dist/chunk-BL65ZC6L.mjs.map +1 -0
- package/dist/{chunk-PGZDQT74.mjs → chunk-CE7PJAAO.mjs} +2 -2
- package/dist/{chunk-FWTPMPSN.mjs → chunk-FZC7X5PK.mjs} +23 -3
- package/dist/{chunk-FWTPMPSN.mjs.map → chunk-FZC7X5PK.mjs.map} +1 -1
- package/dist/{chunk-Z45ZEXJW.mjs → chunk-LTCJCXCP.mjs} +5 -8
- package/dist/chunk-LTCJCXCP.mjs.map +1 -0
- package/dist/chunk-MRFF7GSQ.mjs +1 -0
- package/dist/{chunk-SKC7AJIV.mjs → chunk-MRXNTQOX.mjs} +1 -3
- package/dist/{chunk-MWFHYCQB.mjs → chunk-PAQWLSA4.mjs} +2 -2
- package/dist/chunk-RT2XG2T7.mjs +25 -0
- package/dist/chunk-RT2XG2T7.mjs.map +1 -0
- package/dist/chunk-T3JTSIHT.mjs +93 -0
- package/dist/chunk-T3JTSIHT.mjs.map +1 -0
- package/dist/{chunk-A7J4KGLP.mjs → chunk-UPTB2MVO.mjs} +2 -2
- package/dist/{chunk-KZME7C5S.mjs → chunk-VUZA5AFH.mjs} +8 -11
- package/dist/chunk-VUZA5AFH.mjs.map +1 -0
- package/dist/{chunk-XWWMYJJF.mjs → chunk-XRODMID5.mjs} +5 -5
- package/dist/{chunk-XWWMYJJF.mjs.map → chunk-XRODMID5.mjs.map} +1 -1
- package/dist/{chunk-ZKLK3M77.mjs → chunk-YQ3D5IQV.mjs} +3 -3
- package/dist/{chunk-WM6BS77F.mjs → chunk-YQFVRDNC.mjs} +2 -2
- package/dist/{chunk-WM6BS77F.mjs.map → chunk-YQFVRDNC.mjs.map} +1 -1
- package/dist/chunk-ZO3GLN23.mjs +137 -0
- package/dist/chunk-ZO3GLN23.mjs.map +1 -0
- package/dist/components/chat/Button.d.ts +1 -1
- package/dist/components/chat/Button.js +2 -30
- package/dist/components/chat/Button.js.map +1 -1
- package/dist/components/chat/Button.mjs +4 -4
- package/dist/components/chat/Chat.d.ts +66 -47
- package/dist/components/chat/Chat.js +274 -430
- package/dist/components/chat/Chat.js.map +1 -1
- package/dist/components/chat/Chat.mjs +16 -17
- package/dist/components/chat/ChatContext.d.ts +17 -22
- package/dist/components/chat/ChatContext.js +23 -8
- package/dist/components/chat/ChatContext.js.map +1 -1
- package/dist/components/chat/ChatContext.mjs +3 -3
- package/dist/components/chat/CodeBlock.js.map +1 -1
- package/dist/components/chat/CodeBlock.mjs +3 -3
- package/dist/components/chat/Header.js.map +1 -1
- package/dist/components/chat/Header.mjs +4 -4
- package/dist/components/chat/Icons.d.ts +6 -5
- package/dist/components/chat/Icons.js +21 -0
- package/dist/components/chat/Icons.js.map +1 -1
- package/dist/components/chat/Icons.mjs +4 -2
- package/dist/components/chat/Input.js +147 -9
- package/dist/components/chat/Input.js.map +1 -1
- package/dist/components/chat/Input.mjs +6 -5
- package/dist/components/chat/Markdown.js.map +1 -1
- package/dist/components/chat/Markdown.mjs +4 -4
- package/dist/components/chat/Messages.js.map +1 -1
- package/dist/components/chat/Messages.mjs +6 -6
- package/dist/components/chat/Modal.d.ts +50 -0
- package/dist/components/chat/Modal.js +1584 -0
- package/dist/components/chat/Modal.js.map +1 -0
- package/dist/components/chat/Modal.mjs +23 -0
- package/dist/components/chat/Popup.d.ts +6 -5
- package/dist/components/chat/Popup.js +288 -249
- package/dist/components/chat/Popup.js.map +1 -1
- package/dist/components/chat/Popup.mjs +16 -15
- package/dist/components/chat/Response.js.map +1 -1
- package/dist/components/chat/Response.mjs +4 -4
- package/dist/components/chat/Sidebar.d.ts +6 -5
- package/dist/components/chat/Sidebar.js +290 -251
- package/dist/components/chat/Sidebar.js.map +1 -1
- package/dist/components/chat/Sidebar.mjs +16 -15
- package/dist/components/chat/Suggestion.d.ts +1 -2
- package/dist/components/chat/Suggestion.js.map +1 -1
- package/dist/components/chat/Suggestion.mjs +3 -3
- package/dist/components/chat/Textarea.d.ts +4 -4
- package/dist/components/chat/Textarea.js +1 -1
- package/dist/components/chat/Textarea.js.map +1 -1
- package/dist/components/chat/Textarea.mjs +2 -2
- package/dist/components/chat/Window.mjs +1 -1
- package/dist/components/chat/index.d.ts +2 -1
- package/dist/components/chat/index.js +294 -253
- package/dist/components/chat/index.js.map +1 -1
- package/dist/components/chat/index.mjs +23 -19
- package/dist/components/chat/props.d.ts +1 -3
- package/dist/components/chat/props.js.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.js +294 -253
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +23 -19
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.js +6 -31
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +2 -22
- package/dist/hooks/use-copilot-chat-suggestions.d.ts +26 -4
- package/dist/hooks/use-copilot-chat-suggestions.js +6 -31
- package/dist/hooks/use-copilot-chat-suggestions.js.map +1 -1
- package/dist/hooks/use-copilot-chat-suggestions.mjs +2 -22
- package/dist/hooks/use-copy-to-clipboard.mjs +1 -1
- package/dist/hooks/use-push-to-talk.d.ts +19 -0
- package/dist/hooks/use-push-to-talk.js +177 -0
- package/dist/hooks/use-push-to-talk.js.map +1 -0
- package/dist/hooks/use-push-to-talk.mjs +12 -0
- package/dist/hooks/use-push-to-talk.mjs.map +1 -0
- package/dist/index.css +60 -8
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +300 -258
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -24
- package/dist/lib/utils.mjs +1 -1
- package/dist/types/suggestions.d.ts +1 -21
- package/dist/types/suggestions.js.map +1 -1
- package/package.json +6 -6
- package/src/components/chat/Button.tsx +2 -35
- package/src/components/chat/Chat.tsx +126 -255
- package/src/components/chat/ChatContext.tsx +8 -22
- package/src/components/chat/Icons.tsx +17 -0
- package/src/components/chat/Input.tsx +37 -5
- package/src/components/chat/Modal.tsx +115 -0
- package/src/components/chat/Popup.tsx +3 -3
- package/src/components/chat/Sidebar.tsx +4 -4
- package/src/components/chat/Suggestion.tsx +6 -2
- package/src/components/chat/Textarea.tsx +1 -1
- package/src/components/chat/index.tsx +1 -0
- package/src/components/chat/props.ts +1 -3
- package/src/css/input.css +18 -8
- package/src/css/panel.css +38 -0
- package/src/css/window.css +3 -1
- package/src/hooks/use-copilot-chat-suggestions.tsx +31 -5
- package/src/hooks/use-push-to-talk.tsx +162 -0
- package/src/styles.css +1 -0
- package/src/types/suggestions.ts +0 -24
- package/dist/chunk-5ASYNEHX.mjs +0 -53
- package/dist/chunk-5ASYNEHX.mjs.map +0 -1
- package/dist/chunk-DMAQBCTX.mjs.map +0 -1
- package/dist/chunk-DRNCOXZO.mjs.map +0 -1
- package/dist/chunk-JPX5ODUX.mjs +0 -266
- package/dist/chunk-JPX5ODUX.mjs.map +0 -1
- package/dist/chunk-KZME7C5S.mjs.map +0 -1
- package/dist/chunk-PEDSZYHE.mjs +0 -36
- package/dist/chunk-PEDSZYHE.mjs.map +0 -1
- package/dist/chunk-UGQQ4WEQ.mjs +0 -1
- package/dist/chunk-Z45ZEXJW.mjs.map +0 -1
- package/dist/components/chat/audio.d.ts +0 -7
- package/dist/components/chat/audio.js +0 -77
- package/dist/components/chat/audio.js.map +0 -1
- package/dist/components/chat/audio.mjs +0 -10
- package/src/components/chat/audio.ts +0 -26
- /package/dist/{chunk-XYM43AHP.mjs.map → chunk-7FES2IQA.mjs.map} +0 -0
- /package/dist/{chunk-PGZDQT74.mjs.map → chunk-CE7PJAAO.mjs.map} +0 -0
- /package/dist/{chunk-SKC7AJIV.mjs.map → chunk-MRFF7GSQ.mjs.map} +0 -0
- /package/dist/{chunk-UGQQ4WEQ.mjs.map → chunk-MRXNTQOX.mjs.map} +0 -0
- /package/dist/{chunk-MWFHYCQB.mjs.map → chunk-PAQWLSA4.mjs.map} +0 -0
- /package/dist/{chunk-A7J4KGLP.mjs.map → chunk-UPTB2MVO.mjs.map} +0 -0
- /package/dist/{chunk-ZKLK3M77.mjs.map → chunk-YQ3D5IQV.mjs.map} +0 -0
- /package/dist/components/chat/{audio.mjs.map → Modal.mjs.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/types/suggestions.ts"],"sourcesContent":["export interface
|
|
1
|
+
{"version":3,"sources":["../../src/types/suggestions.ts"],"sourcesContent":["export interface CopilotChatSuggestion {\n title: string;\n message: string;\n partial?: boolean;\n className?: string;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.36.0-mme-
|
|
7
|
+
"version": "0.36.0-mme-pre.1",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"**/*.css"
|
|
10
10
|
],
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"ts-jest": "^29.1.1",
|
|
36
36
|
"tsup": "^6.7.0",
|
|
37
37
|
"typescript": "^5.2.3",
|
|
38
|
-
"eslint-config-custom": "0.11.0-mme-
|
|
39
|
-
"tailwind-config": "0.10.0-mme-
|
|
40
|
-
"tsconfig": "0.15.0-mme-
|
|
38
|
+
"eslint-config-custom": "0.11.0-mme-pre.1",
|
|
39
|
+
"tailwind-config": "0.10.0-mme-pre.1",
|
|
40
|
+
"tsconfig": "0.15.0-mme-pre.1"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"nanoid": "^4.0.2",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"react-syntax-highlighter": "^15.5.0",
|
|
46
46
|
"remark-gfm": "^3.0.1",
|
|
47
47
|
"remark-math": "^5.1.1",
|
|
48
|
-
"@copilotkit/shared": "0.36.0-mme-
|
|
49
|
-
"@copilotkit/react-core": "0.36.0-mme-
|
|
48
|
+
"@copilotkit/shared": "0.36.0-mme-pre.1",
|
|
49
|
+
"@copilotkit/react-core": "0.36.0-mme-pre.1"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "tsup --clean",
|
|
@@ -1,44 +1,11 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from "react";
|
|
2
1
|
import { ButtonProps } from "./props";
|
|
3
2
|
import { useChatContext } from "./ChatContext";
|
|
4
3
|
|
|
5
|
-
export const Button = ({ open, setOpen
|
|
4
|
+
export const Button = ({ open, setOpen }: ButtonProps) => {
|
|
6
5
|
const context = useChatContext();
|
|
7
|
-
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
8
|
-
const [isLongPress, setIsLongPress] = useState(false);
|
|
9
|
-
|
|
10
|
-
const handleMouseDown = () => {
|
|
11
|
-
timerRef.current = setTimeout(() => {
|
|
12
|
-
setPushToTalk(true);
|
|
13
|
-
setIsLongPress(true);
|
|
14
|
-
}, 500); // 500ms for long press
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const handleMouseUp = () => {
|
|
18
|
-
if (timerRef.current) {
|
|
19
|
-
clearTimeout(timerRef.current);
|
|
20
|
-
setPushToTalk(false);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const handleClick = () => {
|
|
25
|
-
if (!isLongPress) {
|
|
26
|
-
setOpen(!open);
|
|
27
|
-
} else {
|
|
28
|
-
setIsLongPress(false);
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// we want to handle the mouse up event event outside of the button component
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
document.addEventListener("mouseup", handleMouseUp);
|
|
35
|
-
return () => {
|
|
36
|
-
document.removeEventListener("mouseup", handleMouseUp);
|
|
37
|
-
};
|
|
38
|
-
}, []);
|
|
39
6
|
|
|
40
7
|
return (
|
|
41
|
-
<div onClick={
|
|
8
|
+
<div onClick={() => setOpen(!open)}>
|
|
42
9
|
<button
|
|
43
10
|
className={`copilotKitButton ${open ? "open" : ""}`}
|
|
44
11
|
aria-label={open ? "Close Chat" : "Open Chat"}
|
|
@@ -1,31 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
/**
|
|
2
|
+
* An embeddable chat panel for CopilotKit.
|
|
3
|
+
*
|
|
4
|
+
* <img src="/images/CopilotChat/CopilotChat.gif" width="500" />
|
|
5
|
+
*
|
|
6
|
+
* A chatbot panel component for the CopilotKit framework. The component allows for a high degree
|
|
7
|
+
* of customization through various props and custom CSS.
|
|
8
|
+
*
|
|
9
|
+
* <RequestExample>
|
|
10
|
+
* ```jsx CopilotChat Example
|
|
11
|
+
* import { CopilotChat } from "@copilotkit/react-ui";
|
|
12
|
+
*
|
|
13
|
+
* <CopilotChat
|
|
14
|
+
* labels={{
|
|
15
|
+
* title: "Your Assistant",
|
|
16
|
+
* initial: "Hi! 👋 How can I assist you today?",
|
|
17
|
+
* }}
|
|
18
|
+
* />
|
|
19
|
+
* ```
|
|
20
|
+
* </RequestExample>
|
|
21
|
+
*
|
|
22
|
+
* ## Custom CSS
|
|
23
|
+
*
|
|
24
|
+
* You can customize the colors of the panel by overriding the CSS variables
|
|
25
|
+
* defined in the [default styles](https://github.com/CopilotKit/CopilotKit/blob/main/CopilotKit/packages/react-ui/src/css/colors.css).
|
|
26
|
+
*
|
|
27
|
+
* For example, to set the primary color to purple:
|
|
28
|
+
*
|
|
29
|
+
* ```jsx
|
|
30
|
+
* <div style={{ "--copilot-kit-primary-color": "#7D5BA6" }}>
|
|
31
|
+
* <CopilotPopup />
|
|
32
|
+
* </div>
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* To further customize the panel, you can override the CSS classes defined
|
|
36
|
+
* [here](https://github.com/CopilotKit/CopilotKit/blob/main/CopilotKit/packages/react-ui/src/css/).
|
|
37
|
+
*
|
|
38
|
+
* For example:
|
|
39
|
+
*
|
|
40
|
+
* ```css
|
|
41
|
+
* .copilotKitButton {
|
|
42
|
+
* border-radius: 0;
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
|
|
9
47
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
ResponseButtonProps,
|
|
16
|
-
SuggestionsProps,
|
|
17
|
-
} from "./props";
|
|
18
|
-
import { Window as DefaultWindow } from "./Window";
|
|
19
|
-
import { Button as DefaultButton } from "./Button";
|
|
20
|
-
import { Header as DefaultHeader } from "./Header";
|
|
48
|
+
ChatContext,
|
|
49
|
+
ChatContextProvider,
|
|
50
|
+
CopilotChatIcons,
|
|
51
|
+
CopilotChatLabels,
|
|
52
|
+
} from "./ChatContext";
|
|
21
53
|
import { Messages as DefaultMessages } from "./Messages";
|
|
22
54
|
import { Input as DefaultInput } from "./Input";
|
|
23
|
-
import { nanoid } from "nanoid";
|
|
24
55
|
import { ResponseButton as DefaultResponseButton } from "./Response";
|
|
25
|
-
import { Suggestion
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
56
|
+
import { Suggestion } from "./Suggestion";
|
|
57
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
58
|
+
import { SystemMessageFunction, useCopilotChat, useCopilotContext } from "@copilotkit/react-core";
|
|
59
|
+
import { nanoid } from "nanoid";
|
|
60
|
+
import { reloadSuggestions } from "./Suggestion";
|
|
61
|
+
import { CopilotChatSuggestion } from "../../types/suggestions";
|
|
28
62
|
import { Message } from "@copilotkit/shared";
|
|
63
|
+
import { InputProps, MessagesProps, ResponseButtonProps } from "./props";
|
|
29
64
|
|
|
30
65
|
/**
|
|
31
66
|
* Props for CopilotChat component.
|
|
@@ -41,29 +76,6 @@ export interface CopilotChatProps {
|
|
|
41
76
|
*/
|
|
42
77
|
instructions?: string;
|
|
43
78
|
|
|
44
|
-
/**
|
|
45
|
-
* Whether the chat window should be open by default.
|
|
46
|
-
* @default false
|
|
47
|
-
*/
|
|
48
|
-
defaultOpen?: boolean;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* If the chat window should close when the user clicks outside of it.
|
|
52
|
-
* @default true
|
|
53
|
-
*/
|
|
54
|
-
clickOutsideToClose?: boolean;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* If the chat window should close when the user hits the Escape key.
|
|
58
|
-
* @default true
|
|
59
|
-
*/
|
|
60
|
-
hitEscapeToClose?: boolean;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* A callback that gets called when the chat window opens or closes.
|
|
64
|
-
*/
|
|
65
|
-
onSetOpen?: (open: boolean) => void;
|
|
66
|
-
|
|
67
79
|
/**
|
|
68
80
|
* A callback that gets called when the in progress state changes.
|
|
69
81
|
*/
|
|
@@ -74,13 +86,6 @@ export interface CopilotChatProps {
|
|
|
74
86
|
*/
|
|
75
87
|
onSubmitMessage?: (message: string) => void;
|
|
76
88
|
|
|
77
|
-
/**
|
|
78
|
-
* The shortcut key to open the chat window.
|
|
79
|
-
* Uses Command-[shortcut] on a Mac and Ctrl-[shortcut] on Windows.
|
|
80
|
-
* @default "/"
|
|
81
|
-
*/
|
|
82
|
-
shortcut?: string;
|
|
83
|
-
|
|
84
89
|
/**
|
|
85
90
|
* Icons can be used to set custom icons for the chat window.
|
|
86
91
|
*/
|
|
@@ -105,21 +110,6 @@ export interface CopilotChatProps {
|
|
|
105
110
|
*/
|
|
106
111
|
showResponseButton?: boolean;
|
|
107
112
|
|
|
108
|
-
/**
|
|
109
|
-
* A custom Window component to use instead of the default.
|
|
110
|
-
*/
|
|
111
|
-
Window?: React.ComponentType<WindowProps>;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* A custom Button component to use instead of the default.
|
|
115
|
-
*/
|
|
116
|
-
Button?: React.ComponentType<ButtonProps>;
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* A custom Header component to use instead of the default.
|
|
120
|
-
*/
|
|
121
|
-
Header?: React.ComponentType<HeaderProps>;
|
|
122
|
-
|
|
123
113
|
/**
|
|
124
114
|
* A custom Messages component to use instead of the default.
|
|
125
115
|
*/
|
|
@@ -146,37 +136,78 @@ export interface CopilotChatProps {
|
|
|
146
136
|
children?: React.ReactNode;
|
|
147
137
|
}
|
|
148
138
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
export const CopilotChat = ({
|
|
139
|
+
export function CopilotChat({
|
|
152
140
|
instructions,
|
|
153
|
-
defaultOpen = false,
|
|
154
|
-
clickOutsideToClose = true,
|
|
155
|
-
hitEscapeToClose = true,
|
|
156
|
-
onSetOpen,
|
|
157
141
|
onSubmitMessage,
|
|
158
|
-
shortcut = "/",
|
|
159
142
|
icons,
|
|
160
143
|
labels,
|
|
161
144
|
makeSystemMessage,
|
|
162
145
|
showResponseButton = true,
|
|
163
146
|
onInProgress,
|
|
164
|
-
Window = DefaultWindow,
|
|
165
|
-
Button = DefaultButton,
|
|
166
|
-
Header = DefaultHeader,
|
|
167
147
|
Messages = DefaultMessages,
|
|
168
148
|
Input = DefaultInput,
|
|
169
149
|
ResponseButton = DefaultResponseButton,
|
|
170
150
|
className,
|
|
171
|
-
|
|
172
|
-
|
|
151
|
+
}: CopilotChatProps) {
|
|
152
|
+
const { visibleMessages, isLoading, currentSuggestions, sendMessage, stop, reload } =
|
|
153
|
+
useCopilotChatLogic(instructions, makeSystemMessage, onInProgress, onSubmitMessage);
|
|
154
|
+
|
|
155
|
+
const context = React.useContext(ChatContext);
|
|
156
|
+
let open = true;
|
|
157
|
+
let setOpen: (open: boolean) => void = () => {};
|
|
158
|
+
if (context) {
|
|
159
|
+
icons = context.icons;
|
|
160
|
+
labels = context.labels;
|
|
161
|
+
open = context.open;
|
|
162
|
+
setOpen = context.setOpen;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<ChatContextProvider icons={icons} labels={labels} open={open} setOpen={setOpen}>
|
|
167
|
+
<div className={`copilotKitPanel ${className}`}>
|
|
168
|
+
<Messages messages={visibleMessages} inProgress={isLoading}>
|
|
169
|
+
{currentSuggestions.length > 0 && (
|
|
170
|
+
<div>
|
|
171
|
+
<h6>Suggested:</h6>
|
|
172
|
+
<div className="suggestions">
|
|
173
|
+
{currentSuggestions.map((suggestion, index) => (
|
|
174
|
+
<Suggestion
|
|
175
|
+
key={index}
|
|
176
|
+
title={suggestion.title}
|
|
177
|
+
message={suggestion.message}
|
|
178
|
+
partial={suggestion.partial}
|
|
179
|
+
className={suggestion.className}
|
|
180
|
+
onClick={(message) => sendMessage(message)}
|
|
181
|
+
/>
|
|
182
|
+
))}
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
)}
|
|
186
|
+
{showResponseButton && visibleMessages.length > 0 && (
|
|
187
|
+
<ResponseButton onClick={isLoading ? stop : reload} inProgress={isLoading} />
|
|
188
|
+
)}
|
|
189
|
+
</Messages>
|
|
190
|
+
<Input inProgress={isLoading} onSend={sendMessage} isVisible={true} />
|
|
191
|
+
</div>
|
|
192
|
+
</ChatContextProvider>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const SUGGESTIONS_DEBOUNCE_TIMEOUT = 1000;
|
|
197
|
+
|
|
198
|
+
export const useCopilotChatLogic = (
|
|
199
|
+
instructions?: string,
|
|
200
|
+
makeSystemMessage?: SystemMessageFunction,
|
|
201
|
+
onInProgress?: (isLoading: boolean) => void,
|
|
202
|
+
onSubmitMessage?: (messageContent: string) => void,
|
|
203
|
+
) => {
|
|
173
204
|
const { visibleMessages, append, reload, stop, isLoading, input, setInput } = useCopilotChat({
|
|
174
205
|
id: nanoid(),
|
|
175
206
|
makeSystemMessage,
|
|
176
207
|
additionalInstructions: instructions,
|
|
177
208
|
});
|
|
178
209
|
|
|
179
|
-
const [currentSuggestions, setCurrentSuggestions] =
|
|
210
|
+
const [currentSuggestions, setCurrentSuggestions] = useState<CopilotChatSuggestion[]>([]);
|
|
180
211
|
const suggestionsAbortControllerRef = useRef<AbortController | null>(null);
|
|
181
212
|
const debounceTimerRef = useRef<any>();
|
|
182
213
|
|
|
@@ -187,24 +218,6 @@ export const CopilotChat = ({
|
|
|
187
218
|
|
|
188
219
|
const context = useCopilotContext();
|
|
189
220
|
|
|
190
|
-
const [chatSuggestionConfiguration, setChatSuggestionConfiguration] = useState<{
|
|
191
|
-
[key: string]: CopilotChatSuggestionConfiguration;
|
|
192
|
-
}>({});
|
|
193
|
-
|
|
194
|
-
const addChatSuggestionConfiguration = (
|
|
195
|
-
id: string,
|
|
196
|
-
suggestion: CopilotChatSuggestionConfiguration,
|
|
197
|
-
) => {
|
|
198
|
-
setChatSuggestionConfiguration((prev) => ({ ...prev, [id]: suggestion }));
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
const removeChatSuggestion = (id: string) => {
|
|
202
|
-
setChatSuggestionConfiguration((prev) => {
|
|
203
|
-
const { [id]: _, ...rest } = prev;
|
|
204
|
-
return rest;
|
|
205
|
-
});
|
|
206
|
-
};
|
|
207
|
-
|
|
208
221
|
useEffect(() => {
|
|
209
222
|
onInProgress?.(isLoading);
|
|
210
223
|
|
|
@@ -212,11 +225,11 @@ export const CopilotChat = ({
|
|
|
212
225
|
|
|
213
226
|
debounceTimerRef.current = setTimeout(
|
|
214
227
|
() => {
|
|
215
|
-
if (!isLoading && Object.keys(chatSuggestionConfiguration).length !== 0) {
|
|
228
|
+
if (!isLoading && Object.keys(context.chatSuggestionConfiguration).length !== 0) {
|
|
216
229
|
suggestionsAbortControllerRef.current = new AbortController();
|
|
217
230
|
reloadSuggestions(
|
|
218
231
|
context,
|
|
219
|
-
chatSuggestionConfiguration,
|
|
232
|
+
context.chatSuggestionConfiguration,
|
|
220
233
|
setCurrentSuggestions,
|
|
221
234
|
suggestionsAbortControllerRef,
|
|
222
235
|
);
|
|
@@ -228,12 +241,7 @@ export const CopilotChat = ({
|
|
|
228
241
|
return () => {
|
|
229
242
|
clearTimeout(debounceTimerRef.current);
|
|
230
243
|
};
|
|
231
|
-
}, [isLoading, chatSuggestionConfiguration]);
|
|
232
|
-
|
|
233
|
-
const setOpen = (open: boolean) => {
|
|
234
|
-
onSetOpen?.(open);
|
|
235
|
-
setOpenState(open);
|
|
236
|
-
};
|
|
244
|
+
}, [isLoading, context.chatSuggestionConfiguration]);
|
|
237
245
|
|
|
238
246
|
const sendMessage = async (messageContent: string) => {
|
|
239
247
|
abortSuggestions();
|
|
@@ -248,151 +256,14 @@ export const CopilotChat = ({
|
|
|
248
256
|
return message;
|
|
249
257
|
};
|
|
250
258
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (!mediaStreamRef.current || !audioContextRef.current) {
|
|
262
|
-
setPushToTalkState(false);
|
|
263
|
-
requestMicAndPlaybackPermission().then((res) => {
|
|
264
|
-
if (res) {
|
|
265
|
-
mediaStreamRef.current = res.stream;
|
|
266
|
-
audioContextRef.current = res.audioContext;
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
} else {
|
|
270
|
-
console.log("Recording started");
|
|
271
|
-
const recordedChunks: Blob[] = [];
|
|
272
|
-
|
|
273
|
-
mediaRecorderRef.current = new MediaRecorder(mediaStreamRef.current);
|
|
274
|
-
mediaRecorderRef.current.start(1000);
|
|
275
|
-
mediaRecorderRef.current.ondataavailable = async (event) => {
|
|
276
|
-
console.log("Recorded audio: ", event.data);
|
|
277
|
-
recordedChunks.push(event.data);
|
|
278
|
-
};
|
|
279
|
-
mediaRecorderRef.current.onstop = async () => {
|
|
280
|
-
console.log("Recording stopped");
|
|
281
|
-
const completeBlob = new Blob(recordedChunks, { type: "audio/mp4" });
|
|
282
|
-
|
|
283
|
-
const formData = new FormData();
|
|
284
|
-
formData.append("file", completeBlob, "recording.mp4");
|
|
285
|
-
|
|
286
|
-
const response = await fetch(context.copilotApiConfig.transcribeAudioUrl!, {
|
|
287
|
-
method: "POST",
|
|
288
|
-
body: formData,
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
if (!response.ok) {
|
|
292
|
-
throw new Error(`Error: ${response.statusText}`);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const transcription = await response.json();
|
|
296
|
-
const message = await sendMessage(transcription.text);
|
|
297
|
-
setLastMessageIdBeforeAudio(message.id);
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
} else {
|
|
301
|
-
if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
|
|
302
|
-
mediaRecorderRef.current.stop();
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
return () => {
|
|
307
|
-
if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
|
|
308
|
-
mediaRecorderRef.current.stop();
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
}, [pushToTalkState]);
|
|
312
|
-
|
|
313
|
-
useEffect(() => {
|
|
314
|
-
if (lastMessageIdBeforeAudio && !isLoading) {
|
|
315
|
-
if (audioContextRef.current) {
|
|
316
|
-
const lastMessageIndex = context.messages.findIndex(
|
|
317
|
-
(message) => message.id === lastMessageIdBeforeAudio,
|
|
318
|
-
);
|
|
319
|
-
|
|
320
|
-
const messagesAfterLast = context.messages
|
|
321
|
-
.slice(lastMessageIndex + 1)
|
|
322
|
-
.filter((message) => message.role === "assistant" && message.content);
|
|
323
|
-
|
|
324
|
-
const text = messagesAfterLast.map((message) => message.content).join("\n");
|
|
325
|
-
const encodedText = encodeURIComponent(text);
|
|
326
|
-
const url = `${context.copilotApiConfig.textToSpeechUrl}?text=${encodedText}`;
|
|
327
|
-
|
|
328
|
-
fetch(url)
|
|
329
|
-
.then((response) => response.arrayBuffer())
|
|
330
|
-
.then((arrayBuffer) => audioContextRef.current!.decodeAudioData(arrayBuffer))
|
|
331
|
-
.then((audioBuffer) => {
|
|
332
|
-
const source = audioContextRef.current!.createBufferSource();
|
|
333
|
-
source.buffer = audioBuffer;
|
|
334
|
-
source.connect(audioContextRef.current!.destination);
|
|
335
|
-
source.start(0);
|
|
336
|
-
})
|
|
337
|
-
.catch((error) => {
|
|
338
|
-
console.error("Error with decoding audio data", error);
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
setLastMessageIdBeforeAudio(null);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}, [isLoading]);
|
|
345
|
-
|
|
346
|
-
return (
|
|
347
|
-
<ChatContextProvider
|
|
348
|
-
icons={icons}
|
|
349
|
-
labels={labels}
|
|
350
|
-
open={openState}
|
|
351
|
-
setOpen={setOpenState}
|
|
352
|
-
addChatSuggestionConfiguration={addChatSuggestionConfiguration}
|
|
353
|
-
removeChatSuggestionConfiguration={removeChatSuggestion}
|
|
354
|
-
>
|
|
355
|
-
{children}
|
|
356
|
-
<div className={className}>
|
|
357
|
-
<Button
|
|
358
|
-
open={openState}
|
|
359
|
-
setOpen={setOpen}
|
|
360
|
-
pushToTalk={pushToTalkState}
|
|
361
|
-
setPushToTalk={setPushToTalkState}
|
|
362
|
-
></Button>
|
|
363
|
-
<Window
|
|
364
|
-
open={openState}
|
|
365
|
-
setOpen={setOpen}
|
|
366
|
-
clickOutsideToClose={clickOutsideToClose}
|
|
367
|
-
shortcut={shortcut}
|
|
368
|
-
hitEscapeToClose={hitEscapeToClose}
|
|
369
|
-
>
|
|
370
|
-
<Header open={openState} setOpen={setOpen} />
|
|
371
|
-
<Messages messages={visibleMessages} inProgress={isLoading}>
|
|
372
|
-
{currentSuggestions.length > 0 && (
|
|
373
|
-
<div>
|
|
374
|
-
<h6>Suggested:</h6>
|
|
375
|
-
<div className="suggestions">
|
|
376
|
-
{currentSuggestions.map((suggestion, index) => (
|
|
377
|
-
<Suggestion
|
|
378
|
-
key={index}
|
|
379
|
-
title={suggestion.title}
|
|
380
|
-
message={suggestion.message}
|
|
381
|
-
partial={suggestion.partial}
|
|
382
|
-
className={suggestion.className}
|
|
383
|
-
onClick={(message) => sendMessage(message)}
|
|
384
|
-
/>
|
|
385
|
-
))}
|
|
386
|
-
</div>
|
|
387
|
-
</div>
|
|
388
|
-
)}
|
|
389
|
-
{showResponseButton && visibleMessages.length > 0 && (
|
|
390
|
-
<ResponseButton onClick={isLoading ? stop : reload} inProgress={isLoading} />
|
|
391
|
-
)}
|
|
392
|
-
</Messages>
|
|
393
|
-
<Input inProgress={isLoading} onSend={sendMessage} isVisible={openState} />
|
|
394
|
-
</Window>
|
|
395
|
-
</div>
|
|
396
|
-
</ChatContextProvider>
|
|
397
|
-
);
|
|
259
|
+
return {
|
|
260
|
+
visibleMessages,
|
|
261
|
+
isLoading,
|
|
262
|
+
currentSuggestions,
|
|
263
|
+
sendMessage,
|
|
264
|
+
stop,
|
|
265
|
+
reload,
|
|
266
|
+
input,
|
|
267
|
+
setInput,
|
|
268
|
+
};
|
|
398
269
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { useMemo, useState } from "react";
|
|
2
2
|
import * as DefaultIcons from "./Icons";
|
|
3
|
-
import { CopilotChatSuggestion, CopilotChatSuggestionConfiguration } from "../../types/suggestions";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Icons for CopilotChat component.
|
|
@@ -53,6 +52,13 @@ export interface CopilotChatIcons {
|
|
|
53
52
|
* @default <RegenerateIcon />
|
|
54
53
|
*/
|
|
55
54
|
regenerateIcon?: React.ReactNode;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The icons to use for push to talk.
|
|
58
|
+
* @default <PushToTalkIcon />
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
pushToTalkIcon?: React.ReactNode;
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
/**
|
|
@@ -76,12 +82,6 @@ export interface CopilotChatLabels {
|
|
|
76
82
|
*/
|
|
77
83
|
placeholder?: string;
|
|
78
84
|
|
|
79
|
-
/**
|
|
80
|
-
* The message to display while the chat GPT is "thinking".
|
|
81
|
-
* @default "Thinking..."
|
|
82
|
-
*/
|
|
83
|
-
thinking?: string;
|
|
84
|
-
|
|
85
85
|
/**
|
|
86
86
|
* The message to display when an error occurs.
|
|
87
87
|
* @default "❌ An error occurred. Please try again."
|
|
@@ -106,11 +106,6 @@ interface ChatContext {
|
|
|
106
106
|
icons: Required<CopilotChatIcons>;
|
|
107
107
|
open: boolean;
|
|
108
108
|
setOpen: (open: boolean) => void;
|
|
109
|
-
addChatSuggestionConfiguration: (
|
|
110
|
-
id: string,
|
|
111
|
-
suggestion: CopilotChatSuggestionConfiguration,
|
|
112
|
-
) => void;
|
|
113
|
-
removeChatSuggestionConfiguration: (id: string) => void;
|
|
114
109
|
}
|
|
115
110
|
|
|
116
111
|
export const ChatContext = React.createContext<ChatContext | undefined>(undefined);
|
|
@@ -134,11 +129,6 @@ interface ChatContextProps {
|
|
|
134
129
|
children?: React.ReactNode;
|
|
135
130
|
open: boolean;
|
|
136
131
|
setOpen: (open: boolean) => void;
|
|
137
|
-
addChatSuggestionConfiguration: (
|
|
138
|
-
id: string,
|
|
139
|
-
suggestion: CopilotChatSuggestionConfiguration,
|
|
140
|
-
) => void;
|
|
141
|
-
removeChatSuggestionConfiguration: (id: string) => void;
|
|
142
132
|
}
|
|
143
133
|
|
|
144
134
|
export const ChatContextProvider = ({
|
|
@@ -150,8 +140,6 @@ export const ChatContextProvider = ({
|
|
|
150
140
|
children,
|
|
151
141
|
open,
|
|
152
142
|
setOpen,
|
|
153
|
-
addChatSuggestionConfiguration,
|
|
154
|
-
removeChatSuggestionConfiguration,
|
|
155
143
|
}: ChatContextProps) => {
|
|
156
144
|
const context = {
|
|
157
145
|
labels: {
|
|
@@ -159,7 +147,6 @@ export const ChatContextProvider = ({
|
|
|
159
147
|
initial: "",
|
|
160
148
|
title: "CopilotKit",
|
|
161
149
|
placeholder: "Type a message...",
|
|
162
|
-
thinking: "Thinking...",
|
|
163
150
|
error: "❌ An error occurred. Please try again.",
|
|
164
151
|
stopGenerating: "Stop generating",
|
|
165
152
|
regenerateResponse: "Regenerate response",
|
|
@@ -177,13 +164,12 @@ export const ChatContextProvider = ({
|
|
|
177
164
|
spinnerIcon: DefaultIcons.SpinnerIcon,
|
|
178
165
|
stopIcon: DefaultIcons.StopIcon,
|
|
179
166
|
regenerateIcon: DefaultIcons.RegenerateIcon,
|
|
167
|
+
pushToTalkIcon: DefaultIcons.PushToTalkIcon,
|
|
180
168
|
},
|
|
181
169
|
icons,
|
|
182
170
|
},
|
|
183
171
|
open,
|
|
184
172
|
setOpen,
|
|
185
|
-
addChatSuggestionConfiguration,
|
|
186
|
-
removeChatSuggestionConfiguration,
|
|
187
173
|
};
|
|
188
174
|
return <ChatContext.Provider value={context}>{children}</ChatContext.Provider>;
|
|
189
175
|
};
|
|
@@ -204,3 +204,20 @@ export const RegenerateIcon = (
|
|
|
204
204
|
<path d="M197.67 186.37a8 8 0 0 1 0 11.29C196.58 198.73 170.82 224 128 224c-37.39 0-64.53-22.4-80-39.85V208a8 8 0 0 1-16 0v-48a8 8 0 0 1 8-8h48a8 8 0 0 1 0 16H55.44C67.76 183.35 93 208 128 208c36 0 58.14-21.46 58.36-21.68a8 8 0 0 1 11.31.05ZM216 40a8 8 0 0 0-8 8v23.85C192.53 54.4 165.39 32 128 32c-42.82 0-68.58 25.27-69.66 26.34a8 8 0 0 0 11.3 11.34C69.86 69.46 92 48 128 48c35 0 60.24 24.65 72.56 40H168a8 8 0 0 0 0 16h48a8 8 0 0 0 8-8V48a8 8 0 0 0-8-8Z" />
|
|
205
205
|
</svg>
|
|
206
206
|
);
|
|
207
|
+
|
|
208
|
+
export const PushToTalkIcon = (
|
|
209
|
+
<svg
|
|
210
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
211
|
+
fill="none"
|
|
212
|
+
viewBox="0 0 24 24"
|
|
213
|
+
strokeWidth={1.5}
|
|
214
|
+
stroke="currentColor"
|
|
215
|
+
className="w-6 h-6"
|
|
216
|
+
>
|
|
217
|
+
<path
|
|
218
|
+
strokeLinecap="round"
|
|
219
|
+
strokeLinejoin="round"
|
|
220
|
+
d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z"
|
|
221
|
+
/>
|
|
222
|
+
</svg>
|
|
223
|
+
);
|