@copilotkit/react-ui 1.10.7-next.0 → 1.50.0-beta.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.
Files changed (129) hide show
  1. package/CHANGELOG.md +0 -9
  2. package/dist/{chunk-VTYBYTE6.mjs → chunk-3JYVJHL5.mjs} +7 -7
  3. package/dist/chunk-3YWFGNSM.mjs +32 -0
  4. package/dist/chunk-3YWFGNSM.mjs.map +1 -0
  5. package/dist/{chunk-YBRHDFVQ.mjs → chunk-CQ2WALZ7.mjs} +2 -2
  6. package/dist/{chunk-OWX6YJZH.mjs → chunk-E6WVAOQA.mjs} +9 -5
  7. package/dist/chunk-E6WVAOQA.mjs.map +1 -0
  8. package/dist/{chunk-WBPBTTQD.mjs → chunk-FFJHOZX6.mjs} +4 -4
  9. package/dist/{chunk-MJEYL3FK.mjs → chunk-G35HUUDA.mjs} +26 -260
  10. package/dist/chunk-G35HUUDA.mjs.map +1 -0
  11. package/dist/{chunk-V6DDX4LH.mjs → chunk-GDSZGYCE.mjs} +2 -2
  12. package/dist/{chunk-ZJCHKHE4.mjs → chunk-HBZW7E5Z.mjs} +13 -10
  13. package/dist/chunk-HBZW7E5Z.mjs.map +1 -0
  14. package/dist/{chunk-KX44MLR6.mjs → chunk-IHFR6PYG.mjs} +1 -1
  15. package/dist/chunk-IHFR6PYG.mjs.map +1 -0
  16. package/dist/{chunk-2XARU6EY.mjs → chunk-MPF6BJUF.mjs} +5 -3
  17. package/dist/chunk-MPF6BJUF.mjs.map +1 -0
  18. package/dist/{chunk-W26XFBEG.mjs → chunk-NGJ32FAP.mjs} +3 -3
  19. package/dist/chunk-NGJ32FAP.mjs.map +1 -0
  20. package/dist/{chunk-RKULVDQO.mjs → chunk-ODEHR7KI.mjs} +9 -2
  21. package/dist/chunk-ODEHR7KI.mjs.map +1 -0
  22. package/dist/chunk-OYRZ4VLU.mjs +12 -0
  23. package/dist/chunk-OYRZ4VLU.mjs.map +1 -0
  24. package/dist/chunk-QB3GUN2N.mjs +31 -0
  25. package/dist/chunk-QB3GUN2N.mjs.map +1 -0
  26. package/dist/{chunk-PIFTVJG3.mjs → chunk-SOB5EIL7.mjs} +2 -2
  27. package/dist/components/chat/Chat.d.ts +3 -98
  28. package/dist/components/chat/Chat.js +79 -275
  29. package/dist/components/chat/Chat.js.map +1 -1
  30. package/dist/components/chat/Chat.mjs +11 -13
  31. package/dist/components/chat/Header.mjs +4 -4
  32. package/dist/components/chat/Input.d.ts +1 -1
  33. package/dist/components/chat/Input.js +11 -8
  34. package/dist/components/chat/Input.js.map +1 -1
  35. package/dist/components/chat/Input.mjs +1 -1
  36. package/dist/components/chat/Messages.d.ts +3 -3
  37. package/dist/components/chat/Messages.js +33 -4
  38. package/dist/components/chat/Messages.js.map +1 -1
  39. package/dist/components/chat/Messages.mjs +5 -5
  40. package/dist/components/chat/Modal.d.ts +1 -6
  41. package/dist/components/chat/Modal.js +85 -279
  42. package/dist/components/chat/Modal.js.map +1 -1
  43. package/dist/components/chat/Modal.mjs +14 -14
  44. package/dist/components/chat/Popup.d.ts +1 -6
  45. package/dist/components/chat/Popup.js +85 -279
  46. package/dist/components/chat/Popup.js.map +1 -1
  47. package/dist/components/chat/Popup.mjs +15 -15
  48. package/dist/components/chat/Sidebar.d.ts +1 -6
  49. package/dist/components/chat/Sidebar.js +85 -279
  50. package/dist/components/chat/Sidebar.js.map +1 -1
  51. package/dist/components/chat/Sidebar.mjs +15 -15
  52. package/dist/components/chat/Suggestion.js.map +1 -1
  53. package/dist/components/chat/Suggestion.mjs +1 -1
  54. package/dist/components/chat/Suggestions.d.ts +1 -1
  55. package/dist/components/chat/Suggestions.js +19 -12
  56. package/dist/components/chat/Suggestions.js.map +1 -1
  57. package/dist/components/chat/Suggestions.mjs +2 -2
  58. package/dist/components/chat/index.d.ts +0 -5
  59. package/dist/components/chat/index.js +85 -279
  60. package/dist/components/chat/index.js.map +1 -1
  61. package/dist/components/chat/index.mjs +16 -16
  62. package/dist/components/chat/messages/AssistantMessage.js.map +1 -1
  63. package/dist/components/chat/messages/AssistantMessage.mjs +1 -1
  64. package/dist/components/chat/messages/LegacyRenderMessage.js +28 -3
  65. package/dist/components/chat/messages/LegacyRenderMessage.js.map +1 -1
  66. package/dist/components/chat/messages/LegacyRenderMessage.mjs +4 -4
  67. package/dist/components/chat/messages/RenderMessage.js +21 -3
  68. package/dist/components/chat/messages/RenderMessage.js.map +1 -1
  69. package/dist/components/chat/messages/RenderMessage.mjs +3 -3
  70. package/dist/components/chat/messages/UserMessage.js +19 -3
  71. package/dist/components/chat/messages/UserMessage.js.map +1 -1
  72. package/dist/components/chat/messages/UserMessage.mjs +1 -1
  73. package/dist/components/chat/props.d.ts +4 -0
  74. package/dist/components/chat/props.js.map +1 -1
  75. package/dist/components/dev-console/console.mjs +3 -3
  76. package/dist/components/dev-console/index.mjs +4 -4
  77. package/dist/components/index.d.ts +0 -5
  78. package/dist/components/index.js +85 -279
  79. package/dist/components/index.js.map +1 -1
  80. package/dist/components/index.mjs +17 -17
  81. package/dist/hooks/index.d.ts +1 -0
  82. package/dist/hooks/index.js +2 -24
  83. package/dist/hooks/index.js.map +1 -1
  84. package/dist/hooks/index.mjs +1 -1
  85. package/dist/hooks/use-copilot-chat-suggestions.d.ts +4 -26
  86. package/dist/hooks/use-copilot-chat-suggestions.js +2 -24
  87. package/dist/hooks/use-copilot-chat-suggestions.js.map +1 -1
  88. package/dist/hooks/use-copilot-chat-suggestions.mjs +1 -1
  89. package/dist/index.css +0 -2
  90. package/dist/index.css.map +1 -1
  91. package/dist/index.d.ts +0 -5
  92. package/dist/index.js +88 -304
  93. package/dist/index.js.map +1 -1
  94. package/dist/index.mjs +18 -18
  95. package/dist/types/suggestions.d.ts +1 -0
  96. package/dist/types/suggestions.js.map +1 -1
  97. package/package.json +8 -7
  98. package/src/components/chat/Chat.tsx +24 -325
  99. package/src/components/chat/Input.tsx +13 -12
  100. package/src/components/chat/Messages.tsx +8 -4
  101. package/src/components/chat/Suggestion.tsx +2 -2
  102. package/src/components/chat/Suggestions.tsx +6 -2
  103. package/src/components/chat/messages/AssistantMessage.tsx +1 -0
  104. package/src/components/chat/messages/LegacyRenderMessage.tsx +7 -0
  105. package/src/components/chat/messages/RenderMessage.tsx +2 -0
  106. package/src/components/chat/messages/UserMessage.tsx +30 -6
  107. package/src/components/chat/props.ts +4 -0
  108. package/src/css/messages.css +0 -2
  109. package/src/hooks/use-copilot-chat-suggestions.tsx +6 -57
  110. package/src/types/suggestions.ts +1 -0
  111. package/tsup.config.ts +1 -1
  112. package/dist/chunk-226ZMOE3.mjs +0 -24
  113. package/dist/chunk-226ZMOE3.mjs.map +0 -1
  114. package/dist/chunk-2XARU6EY.mjs.map +0 -1
  115. package/dist/chunk-EYRKZDP5.mjs +0 -32
  116. package/dist/chunk-EYRKZDP5.mjs.map +0 -1
  117. package/dist/chunk-KX44MLR6.mjs.map +0 -1
  118. package/dist/chunk-MJEYL3FK.mjs.map +0 -1
  119. package/dist/chunk-OWX6YJZH.mjs.map +0 -1
  120. package/dist/chunk-RKULVDQO.mjs.map +0 -1
  121. package/dist/chunk-VVL6JFCJ.mjs +0 -16
  122. package/dist/chunk-VVL6JFCJ.mjs.map +0 -1
  123. package/dist/chunk-W26XFBEG.mjs.map +0 -1
  124. package/dist/chunk-ZJCHKHE4.mjs.map +0 -1
  125. /package/dist/{chunk-VTYBYTE6.mjs.map → chunk-3JYVJHL5.mjs.map} +0 -0
  126. /package/dist/{chunk-YBRHDFVQ.mjs.map → chunk-CQ2WALZ7.mjs.map} +0 -0
  127. /package/dist/{chunk-WBPBTTQD.mjs.map → chunk-FFJHOZX6.mjs.map} +0 -0
  128. /package/dist/{chunk-V6DDX4LH.mjs.map → chunk-GDSZGYCE.mjs.map} +0 -0
  129. /package/dist/{chunk-PIFTVJG3.mjs.map → chunk-SOB5EIL7.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -4,51 +4,51 @@ import "./chunk-MMVDU6DF.mjs";
4
4
  import "./chunk-SC6JRFAJ.mjs";
5
5
  import {
6
6
  CopilotSidebar
7
- } from "./chunk-PIFTVJG3.mjs";
7
+ } from "./chunk-SOB5EIL7.mjs";
8
8
  import "./chunk-WB3YULQ4.mjs";
9
9
  import {
10
10
  CopilotPopup
11
- } from "./chunk-YBRHDFVQ.mjs";
12
- import "./chunk-VTYBYTE6.mjs";
11
+ } from "./chunk-CQ2WALZ7.mjs";
12
+ import "./chunk-3JYVJHL5.mjs";
13
13
  import "./chunk-C3GSYRC3.mjs";
14
- import "./chunk-V6DDX4LH.mjs";
14
+ import "./chunk-GDSZGYCE.mjs";
15
15
  import "./chunk-V7W6IM2V.mjs";
16
16
  import {
17
17
  CopilotDevConsole
18
- } from "./chunk-WBPBTTQD.mjs";
19
- import "./chunk-KXE2JCUH.mjs";
20
- import "./chunk-NRA3CFEE.mjs";
21
- import "./chunk-BH6PCAAL.mjs";
18
+ } from "./chunk-FFJHOZX6.mjs";
22
19
  import "./chunk-Q5V6S67N.mjs";
23
20
  import {
24
21
  shouldShowDevConsole
25
22
  } from "./chunk-JY2CSDKN.mjs";
23
+ import "./chunk-KXE2JCUH.mjs";
24
+ import "./chunk-NRA3CFEE.mjs";
25
+ import "./chunk-BH6PCAAL.mjs";
26
26
  import "./chunk-UFN2VWSR.mjs";
27
27
  import {
28
28
  CopilotChat
29
- } from "./chunk-MJEYL3FK.mjs";
29
+ } from "./chunk-G35HUUDA.mjs";
30
30
  import {
31
31
  Suggestions
32
- } from "./chunk-226ZMOE3.mjs";
32
+ } from "./chunk-QB3GUN2N.mjs";
33
33
  import {
34
34
  Suggestion
35
- } from "./chunk-W26XFBEG.mjs";
35
+ } from "./chunk-NGJ32FAP.mjs";
36
36
  import "./chunk-PLHTVHUW.mjs";
37
- import "./chunk-ZJCHKHE4.mjs";
37
+ import "./chunk-HBZW7E5Z.mjs";
38
38
  import "./chunk-ELGRNEAO.mjs";
39
39
  import "./chunk-QIOJXTIQ.mjs";
40
- import "./chunk-OWX6YJZH.mjs";
41
- import "./chunk-RKULVDQO.mjs";
42
- import "./chunk-2XARU6EY.mjs";
40
+ import "./chunk-E6WVAOQA.mjs";
41
+ import "./chunk-ODEHR7KI.mjs";
42
+ import "./chunk-MPF6BJUF.mjs";
43
43
  import {
44
44
  AssistantMessage
45
- } from "./chunk-KX44MLR6.mjs";
45
+ } from "./chunk-IHFR6PYG.mjs";
46
46
  import {
47
47
  ImageRenderer
48
48
  } from "./chunk-DBKRAOH7.mjs";
49
49
  import {
50
50
  UserMessage
51
- } from "./chunk-VVL6JFCJ.mjs";
51
+ } from "./chunk-3YWFGNSM.mjs";
52
52
  import {
53
53
  Markdown
54
54
  } from "./chunk-JZ3RFQQ6.mjs";
@@ -61,7 +61,7 @@ import "./chunk-IU3WTXLQ.mjs";
61
61
  import "./chunk-T26KLXLH.mjs";
62
62
  import {
63
63
  useCopilotChatSuggestions
64
- } from "./chunk-EYRKZDP5.mjs";
64
+ } from "./chunk-OYRZ4VLU.mjs";
65
65
  import "./chunk-54JAUBUJ.mjs";
66
66
  import "./chunk-JGMFJZMG.mjs";
67
67
  import "./chunk-O72ZB5V3.mjs";
@@ -2,6 +2,7 @@ interface CopilotChatSuggestion {
2
2
  title: string;
3
3
  message: string;
4
4
  partial?: boolean;
5
+ isLoading?: boolean;
5
6
  className?: string;
6
7
  }
7
8
 
@@ -1 +1 @@
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":[]}
1
+ {"version":3,"sources":["../../src/types/suggestions.ts"],"sourcesContent":["export interface CopilotChatSuggestion {\n title: string;\n message: string;\n partial?: boolean;\n isLoading?: boolean;\n className?: string;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "publishConfig": {
10
10
  "access": "public"
11
11
  },
12
- "version": "1.10.7-next.0",
12
+ "version": "1.50.0-beta.1",
13
13
  "sideEffects": [
14
14
  "**/*.css"
15
15
  ],
@@ -26,11 +26,12 @@
26
26
  "types": "./dist/index.d.ts",
27
27
  "license": "MIT",
28
28
  "peerDependencies": {
29
+ "@copilotkitnext/core": "0.0.22",
29
30
  "react": "^18 || ^19 || ^19.0.0-rc"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@types/jest": "^29.5.4",
33
- "@types/react": "^18.2.5",
34
+ "@types/react": "^19.1.0",
34
35
  "@types/react-syntax-highlighter": "^15.5.7",
35
36
  "eslint": "^8.56.0",
36
37
  "jest": "^29.6.4",
@@ -40,20 +41,20 @@
40
41
  "ts-jest": "^29.1.1",
41
42
  "tsup": "^6.7.0",
42
43
  "typescript": "^5.2.3",
43
- "tailwind-config": "1.4.6",
44
44
  "tsconfig": "1.4.6",
45
+ "tailwind-config": "1.4.6",
45
46
  "eslint-config-custom": "1.4.6"
46
47
  },
47
48
  "dependencies": {
48
- "@headlessui/react": "^2.1.3",
49
+ "@headlessui/react": "^2.2.9",
49
50
  "react-markdown": "^10.1.0",
50
51
  "react-syntax-highlighter": "^15.6.1",
51
52
  "rehype-raw": "^7.0.0",
52
53
  "remark-gfm": "^4.0.1",
53
54
  "remark-math": "^6.0.0",
54
- "@copilotkit/shared": "1.10.7-next.0",
55
- "@copilotkit/runtime-client-gql": "1.10.7-next.0",
56
- "@copilotkit/react-core": "1.10.7-next.0"
55
+ "@copilotkit/react-core": "1.50.0-beta.1",
56
+ "@copilotkit/shared": "1.50.0-beta.1",
57
+ "@copilotkit/runtime-client-gql": "1.50.0-beta.1"
57
58
  },
58
59
  "keywords": [
59
60
  "copilotkit",
@@ -74,14 +74,14 @@ import { RenderMessage as DefaultRenderMessage } from "./messages/RenderMessage"
74
74
  import { AssistantMessage as DefaultAssistantMessage } from "./messages/AssistantMessage";
75
75
  import { UserMessage as DefaultUserMessage } from "./messages/UserMessage";
76
76
  import { ImageRenderer as DefaultImageRenderer } from "./messages/ImageRenderer";
77
- import React, { useEffect, useRef, useState, useCallback, useMemo } from "react";
77
+ import React, { useEffect, useRef, useState, useCallback } from "react";
78
78
  import {
79
79
  SystemMessageFunction,
80
- useCopilotChatInternal as useCopilotChat,
81
80
  useCopilotContext,
82
- useCopilotMessagesContext,
81
+ useCopilotChatInternal,
82
+ HintFunction,
83
+ type ChatSuggestions,
83
84
  } from "@copilotkit/react-core";
84
- import type { SuggestionItem } from "@copilotkit/react-core";
85
85
  import {
86
86
  CopilotKitError,
87
87
  CopilotKitErrorCode,
@@ -91,8 +91,8 @@ import {
91
91
  ErrorVisibility,
92
92
  styledConsole,
93
93
  CopilotErrorHandler,
94
+ randomUUID,
94
95
  } from "@copilotkit/shared";
95
- import { randomId } from "@copilotkit/shared";
96
96
  import {
97
97
  AssistantMessageProps,
98
98
  ChatError,
@@ -107,19 +107,9 @@ import {
107
107
  UserMessageProps,
108
108
  } from "./props";
109
109
 
110
- import { HintFunction, runAgent, stopAgent } from "@copilotkit/react-core";
111
110
  import { ImageUploadQueue } from "./ImageUploadQueue";
112
111
  import { Suggestions as DefaultRenderSuggestionsList } from "./Suggestions";
113
112
 
114
- /**
115
- * The type of suggestions to use in the chat.
116
- *
117
- * `auto` - Suggestions are generated automatically.
118
- * `manual` - Suggestions are controlled programmatically.
119
- * `SuggestionItem[]` - Static suggestions array.
120
- */
121
- export type ChatSuggestions = "auto" | "manual" | SuggestionItem[];
122
-
123
113
  /**
124
114
  * Props for CopilotChat component.
125
115
  */
@@ -625,15 +615,17 @@ export function CopilotChat({
625
615
  stopGeneration,
626
616
  reloadMessages,
627
617
  suggestions: currentSuggestions,
628
- } = useCopilotChatLogic(
618
+ isLoadingSuggestions,
619
+ agent,
620
+ } = useCopilotChatInternal({
629
621
  suggestions,
630
- makeSystemMessage,
631
- disableSystemMessage,
632
- onInProgress,
633
- onSubmitMessage,
634
- onStopGeneration,
635
- onReloadMessages,
636
- );
622
+ });
623
+ // makeSystemMessage,
624
+ // disableSystemMessage,
625
+ // onInProgress,
626
+ // onSubmitMessage,
627
+ // onStopGeneration,
628
+ // onReloadMessages,
637
629
 
638
630
  // Track loading state changes for chat start/stop events
639
631
  const prevIsLoading = useRef(isLoading);
@@ -659,7 +651,12 @@ export function CopilotChat({
659
651
  // Trigger message sent event
660
652
  triggerObservabilityHook("onMessageSent", text);
661
653
 
662
- return sendMessage(text, images);
654
+ // TODO: send images?
655
+ return sendMessage({
656
+ id: randomUUID(),
657
+ content: text,
658
+ role: "user",
659
+ });
663
660
  };
664
661
 
665
662
  const chatContext = React.useContext(ChatContext);
@@ -795,6 +792,7 @@ export function CopilotChat({
795
792
  <RenderSuggestionsList
796
793
  onSuggestionClick={handleSendMessage}
797
794
  suggestions={currentSuggestions}
795
+ isLoading={isLoadingSuggestions}
798
796
  />
799
797
  )}
800
798
  </Messages>
@@ -814,6 +812,8 @@ export function CopilotChat({
814
812
  )}
815
813
  <Input
816
814
  inProgress={isLoading}
815
+ chatReady={Boolean(agent)}
816
+ // @ts-ignore
817
817
  onSend={handleSendMessage}
818
818
  isVisible={isVisible}
819
819
  onStop={stopGeneration}
@@ -845,304 +845,3 @@ export function WrappedCopilotChat({
845
845
  }
846
846
  return <>{children}</>;
847
847
  }
848
-
849
- export const useCopilotChatLogic = (
850
- chatSuggestions: ChatSuggestions,
851
- makeSystemMessage?: SystemMessageFunction,
852
- disableSystemMessage?: boolean,
853
- onInProgress?: (isLoading: boolean) => void,
854
- onSubmitMessage?: (messageContent: string) => Promise<void> | void,
855
- onStopGeneration?: OnStopGeneration,
856
- onReloadMessages?: OnReloadMessages,
857
- ) => {
858
- const {
859
- messages,
860
- sendMessage,
861
- setMessages,
862
- reloadMessages: defaultReloadMessages,
863
- stopGeneration: defaultStopGeneration,
864
- runChatCompletion,
865
- isLoading,
866
- suggestions,
867
- setSuggestions,
868
- generateSuggestions,
869
- resetSuggestions: resetSuggestionsFromHook,
870
- isLoadingSuggestions,
871
- } = useCopilotChat({
872
- makeSystemMessage,
873
- disableSystemMessage,
874
- });
875
-
876
- const generalContext = useCopilotContext();
877
- const messagesContext = useCopilotMessagesContext();
878
-
879
- // Get actions from context for message conversion
880
- const { actions } = generalContext;
881
-
882
- // Suggestion state management
883
- const [suggestionsFailed, setSuggestionsFailed] = useState(false);
884
- const hasGeneratedInitialSuggestions = useRef<boolean>(false);
885
-
886
- // Handle static suggestions (when suggestions prop is an array)
887
- useEffect(() => {
888
- if (Array.isArray(chatSuggestions)) {
889
- setSuggestions(chatSuggestions);
890
- hasGeneratedInitialSuggestions.current = true;
891
- }
892
- }, [JSON.stringify(chatSuggestions), setSuggestions]);
893
-
894
- // Error handling wrapper
895
- const generateSuggestionsWithErrorHandling = useCallback(
896
- async (context: string) => {
897
- try {
898
- await generateSuggestions();
899
- } catch (error) {
900
- console.error("Failed to generate suggestions:", error);
901
- setSuggestionsFailed(true);
902
- }
903
- },
904
- [generateSuggestions],
905
- );
906
-
907
- // Automatic suggestion generation logic
908
- useEffect(() => {
909
- // Only proceed if in auto mode, not currently loading, and not failed
910
- if (chatSuggestions !== "auto" || isLoadingSuggestions || suggestionsFailed) {
911
- return;
912
- }
913
-
914
- // Don't run during chat loading (when the assistant is responding)
915
- if (isLoading) {
916
- return;
917
- }
918
-
919
- // Check if we have any configurations
920
- if (Object.keys(generalContext.chatSuggestionConfiguration).length === 0) {
921
- return;
922
- }
923
-
924
- // Generate initial suggestions when chat is empty
925
- if (messages.length === 0 && !hasGeneratedInitialSuggestions.current) {
926
- hasGeneratedInitialSuggestions.current = true;
927
- generateSuggestionsWithErrorHandling("initial");
928
- return;
929
- }
930
-
931
- // Generate post-message suggestions after assistant responds
932
- if (messages.length > 0 && suggestions.length === 0) {
933
- generateSuggestionsWithErrorHandling("post-message");
934
- return;
935
- }
936
- }, [
937
- chatSuggestions,
938
- isLoadingSuggestions,
939
- suggestionsFailed,
940
- messages.length,
941
- isLoading,
942
- suggestions.length,
943
- Object.keys(generalContext.chatSuggestionConfiguration).join(","), // Use stable string instead of object reference
944
- generateSuggestionsWithErrorHandling,
945
- ]);
946
-
947
- // Reset suggestion state when switching away from auto mode
948
- useEffect(() => {
949
- if (chatSuggestions !== "auto") {
950
- hasGeneratedInitialSuggestions.current = false;
951
- setSuggestionsFailed(false);
952
- }
953
- }, [chatSuggestions]);
954
-
955
- // Memoize context to prevent infinite re-renders
956
- const stableContext = useMemo(
957
- () => ({
958
- ...generalContext,
959
- ...messagesContext,
960
- }),
961
- [
962
- // Only include stable dependencies
963
- generalContext.actions,
964
- messagesContext.messages.length,
965
- generalContext.isLoading,
966
- ],
967
- );
968
-
969
- // Wrapper for resetSuggestions that also resets local state
970
- const resetSuggestions = useCallback(() => {
971
- resetSuggestionsFromHook();
972
- setSuggestionsFailed(false);
973
- hasGeneratedInitialSuggestions.current = false;
974
- }, [resetSuggestionsFromHook]);
975
-
976
- useEffect(() => {
977
- onInProgress?.(isLoading);
978
- }, [onInProgress, isLoading]);
979
-
980
- const safelySendMessage = async (
981
- messageContent: string,
982
- imagesToUse?: Array<{ contentType: string; bytes: string }>,
983
- ) => {
984
- const images = imagesToUse || [];
985
-
986
- // Clear existing suggestions when user sends a message
987
- // This prevents stale suggestions from remaining visible during new conversation flow
988
- if (chatSuggestions === "auto" || chatSuggestions === "manual") {
989
- setSuggestions([]);
990
- }
991
-
992
- let firstMessage: Message | null = null;
993
-
994
- // Send text message if content provided
995
- if (messageContent.trim().length > 0) {
996
- const textMessage: Message = {
997
- id: randomId(),
998
- role: "user",
999
- content: messageContent,
1000
- };
1001
-
1002
- // Call user-provided submit handler if available
1003
- if (onSubmitMessage) {
1004
- try {
1005
- await onSubmitMessage(messageContent);
1006
- } catch (error) {
1007
- console.error("Error in onSubmitMessage:", error);
1008
- }
1009
- }
1010
-
1011
- // Send the message and clear suggestions for auto/manual modes
1012
- await sendMessage(textMessage, {
1013
- followUp: images.length === 0,
1014
- clearSuggestions: chatSuggestions === "auto" || chatSuggestions === "manual",
1015
- });
1016
-
1017
- if (!firstMessage) {
1018
- firstMessage = textMessage;
1019
- }
1020
- }
1021
-
1022
- // Send image messages
1023
- if (images.length > 0) {
1024
- for (let i = 0; i < images.length; i++) {
1025
- const imageMessage = {
1026
- id: randomId(),
1027
- role: "user" as const,
1028
- image: {
1029
- format: images[i].contentType.replace("image/", ""),
1030
- bytes: images[i].bytes,
1031
- },
1032
- } as unknown as Message;
1033
- await sendMessage(imageMessage, { followUp: i === images.length - 1 });
1034
- if (!firstMessage) {
1035
- firstMessage = imageMessage;
1036
- }
1037
- }
1038
- }
1039
-
1040
- if (!firstMessage) {
1041
- // Should not happen if send button is properly disabled, but handle just in case
1042
- return { role: "user", content: "", id: randomId() } as Message; // Return a dummy message
1043
- }
1044
-
1045
- // The hook implicitly triggers API call on appendMessage.
1046
- // We return the first message sent (either text or first image)
1047
- return firstMessage;
1048
- };
1049
-
1050
- const currentAgentName = generalContext.agentSession?.agentName;
1051
- const restartCurrentAgent = async (hint?: HintFunction) => {
1052
- if (generalContext.agentSession) {
1053
- generalContext.setAgentSession({
1054
- ...generalContext.agentSession,
1055
- nodeName: undefined,
1056
- threadId: undefined,
1057
- });
1058
- generalContext.setCoagentStates((prevAgentStates) => {
1059
- return {
1060
- ...prevAgentStates,
1061
- [generalContext.agentSession!.agentName]: {
1062
- ...prevAgentStates[generalContext.agentSession!.agentName],
1063
- threadId: undefined,
1064
- nodeName: undefined,
1065
- runId: undefined,
1066
- },
1067
- };
1068
- });
1069
- }
1070
- };
1071
- const runCurrentAgent = async (hint?: HintFunction) => {
1072
- if (generalContext.agentSession) {
1073
- await runAgent(
1074
- generalContext.agentSession.agentName,
1075
- stableContext,
1076
- messagesContext.messages,
1077
- sendMessage,
1078
- runChatCompletion,
1079
- );
1080
- }
1081
- };
1082
- const stopCurrentAgent = () => {
1083
- if (generalContext.agentSession) {
1084
- stopAgent(generalContext.agentSession.agentName, stableContext);
1085
- }
1086
- };
1087
- const setCurrentAgentState = (state: any) => {
1088
- if (generalContext.agentSession) {
1089
- generalContext.setCoagentStates((prevAgentStates) => {
1090
- return {
1091
- ...prevAgentStates,
1092
- [generalContext.agentSession!.agentName]: {
1093
- state,
1094
- },
1095
- } as any;
1096
- });
1097
- }
1098
- };
1099
-
1100
- function stopGeneration() {
1101
- // Clear suggestions when stopping generation
1102
- setSuggestions([]);
1103
-
1104
- if (onStopGeneration) {
1105
- onStopGeneration({
1106
- messages: messages,
1107
- setMessages,
1108
- stopGeneration: defaultStopGeneration,
1109
- currentAgentName,
1110
- restartCurrentAgent,
1111
- stopCurrentAgent,
1112
- runCurrentAgent,
1113
- setCurrentAgentState,
1114
- });
1115
- } else {
1116
- defaultStopGeneration();
1117
- }
1118
- }
1119
- function reloadMessages(messageId: string) {
1120
- if (onReloadMessages) {
1121
- onReloadMessages({
1122
- messages: messages,
1123
- setMessages,
1124
- stopGeneration: defaultStopGeneration,
1125
- currentAgentName,
1126
- restartCurrentAgent,
1127
- stopCurrentAgent,
1128
- runCurrentAgent,
1129
- setCurrentAgentState,
1130
- messageId,
1131
- });
1132
- } else {
1133
- defaultReloadMessages(messageId);
1134
- }
1135
- }
1136
-
1137
- return {
1138
- messages,
1139
- isLoading,
1140
- suggestions,
1141
- sendMessage: safelySendMessage,
1142
- stopGeneration,
1143
- reloadMessages,
1144
- resetSuggestions,
1145
- context: stableContext,
1146
- actions,
1147
- };
1148
- };
@@ -3,7 +3,7 @@ import { InputProps } from "./props";
3
3
  import { useChatContext } from "./ChatContext";
4
4
  import AutoResizingTextarea from "./Textarea";
5
5
  import { usePushToTalk } from "../../hooks/use-push-to-talk";
6
- import { useCopilotContext } from "@copilotkit/react-core";
6
+ import { useCopilotContext, useCopilotChatInternal } from "@copilotkit/react-core";
7
7
  import { PoweredByTag } from "./PoweredByTag";
8
8
 
9
9
  const MAX_NEWLINES = 6;
@@ -11,7 +11,7 @@ const MAX_NEWLINES = 6;
11
11
  export const Input = ({
12
12
  inProgress,
13
13
  onSend,
14
- isVisible = false,
14
+ chatReady = true,
15
15
  onStop,
16
16
  onUpload,
17
17
  hideStopButton = false,
@@ -71,22 +71,22 @@ export const Input = ({
71
71
  });
72
72
 
73
73
  const isInProgress = inProgress || pushToTalkState === "transcribing";
74
- const buttonIcon =
75
- isInProgress && !hideStopButton ? context.icons.stopIcon : context.icons.sendIcon;
74
+ const { buttonIcon, buttonAlt } = useMemo(() => {
75
+ if (!chatReady) return { buttonIcon: context.icons.spinnerIcon, buttonAlt: "Loading" };
76
+ return isInProgress && !hideStopButton
77
+ ? { buttonIcon: context.icons.stopIcon, buttonAlt: "Stop" }
78
+ : { buttonIcon: context.icons.sendIcon, buttonAlt: "Send" };
79
+ }, [isInProgress, chatReady, hideStopButton, context.icons.stopIcon, context.icons.sendIcon]);
76
80
  const showPushToTalk =
77
81
  pushToTalkConfigured &&
78
82
  (pushToTalkState === "idle" || pushToTalkState === "recording") &&
79
83
  !inProgress;
80
84
 
81
- const canSend = useMemo(() => {
82
- const interruptEvent = copilotContext.langGraphInterruptAction?.event;
83
- const interruptInProgress =
84
- interruptEvent?.name === "LangGraphInterruptEvent" && !interruptEvent?.response;
85
+ const { interrupt } = useCopilotChatInternal();
85
86
 
86
- return (
87
- !isInProgress && text.trim().length > 0 && pushToTalkState === "idle" && !interruptInProgress
88
- );
89
- }, [copilotContext.langGraphInterruptAction?.event, isInProgress, text, pushToTalkState]);
87
+ const canSend = useMemo(() => {
88
+ return !isInProgress && text.trim().length > 0 && pushToTalkState === "idle" && !interrupt;
89
+ }, [interrupt, isInProgress, text, pushToTalkState]);
90
90
 
91
91
  const canStop = useMemo(() => {
92
92
  return isInProgress && !hideStopButton;
@@ -144,6 +144,7 @@ export const Input = ({
144
144
  data-copilotkit-in-progress={inProgress}
145
145
  data-test-id={inProgress ? "copilot-chat-request-in-progress" : "copilot-chat-ready"}
146
146
  className="copilotKitInputControlButton"
147
+ aria-label={buttonAlt}
147
148
  >
148
149
  {buttonIcon}
149
150
  </button>
@@ -1,8 +1,8 @@
1
- import { useEffect, useMemo, useRef } from "react";
1
+ import React, { useEffect, useMemo, useRef } from "react";
2
2
  import { MessagesProps } from "./props";
3
3
  import { useChatContext } from "./ChatContext";
4
4
  import { Message } from "@copilotkit/shared";
5
- import { useCopilotChatInternal as useCopilotChat } from "@copilotkit/react-core";
5
+ import { useCopilotChatInternal } from "@copilotkit/react-core";
6
6
  import { LegacyRenderMessage, LegacyRenderProps } from "./messages/LegacyRenderMessage";
7
7
 
8
8
  export const Messages = ({
@@ -28,8 +28,8 @@ export const Messages = ({
28
28
  RenderResultMessage,
29
29
  RenderImageMessage,
30
30
  }: MessagesProps) => {
31
- const { labels } = useChatContext();
32
- const { messages: visibleMessages, interrupt } = useCopilotChat();
31
+ const { labels, icons } = useChatContext();
32
+ const { messages: visibleMessages, interrupt } = useCopilotChatInternal();
33
33
  const initialMessages = useMemo(() => makeInitialMessages(labels.initial), [labels.initial]);
34
34
  const messages = [...initialMessages, ...visibleMessages];
35
35
  const { messagesContainerRef, messagesEndRef } = useScrollToBottom(messages);
@@ -77,6 +77,8 @@ export const Messages = ({
77
77
  ? (props: any) => <LegacyRenderMessage {...props} legacyProps={legacyProps} />
78
78
  : RenderMessage;
79
79
 
80
+ const LoadingIcon = () => <span>{icons.activityIcon}</span>;
81
+
80
82
  return (
81
83
  <div className="copilotKitMessages" ref={messagesContainerRef}>
82
84
  <div className="copilotKitMessagesContainer">
@@ -86,6 +88,7 @@ export const Messages = ({
86
88
  <MessageRenderer
87
89
  key={index}
88
90
  message={message}
91
+ messages={messages}
89
92
  inProgress={inProgress}
90
93
  index={index}
91
94
  isCurrentMessage={isCurrentMessage}
@@ -101,6 +104,7 @@ export const Messages = ({
101
104
  />
102
105
  );
103
106
  })}
107
+ {messages[messages.length - 1]?.role === "user" && inProgress && <LoadingIcon />}
104
108
  {interrupt}
105
109
  {chatError && ErrorMessage && <ErrorMessage error={chatError} isCurrentMessage />}
106
110
  </div>
@@ -1,4 +1,4 @@
1
- import { useCopilotChatInternal as useCopilotChat } from "@copilotkit/react-core";
1
+ import { useCopilotChatInternal } from "@copilotkit/react-core";
2
2
  import { SmallSpinnerIcon } from "./Icons";
3
3
 
4
4
  interface SuggestionsProps {
@@ -11,7 +11,7 @@ interface SuggestionsProps {
11
11
 
12
12
  export function Suggestion({ title, onClick, partial, className }: SuggestionsProps) {
13
13
  if (!title) return null;
14
- const { isLoading } = useCopilotChat();
14
+ const { isLoading } = useCopilotChatInternal();
15
15
 
16
16
  return (
17
17
  <button
@@ -1,7 +1,11 @@
1
1
  import { Suggestion } from "./Suggestion";
2
2
  import { RenderSuggestionsListProps } from "./props";
3
3
 
4
- export function Suggestions({ suggestions, onSuggestionClick }: RenderSuggestionsListProps) {
4
+ export function Suggestions({
5
+ suggestions,
6
+ onSuggestionClick,
7
+ isLoading,
8
+ }: RenderSuggestionsListProps) {
5
9
  return (
6
10
  <div className="suggestions">
7
11
  {suggestions.map((suggestion, index) => (
@@ -9,7 +13,7 @@ export function Suggestions({ suggestions, onSuggestionClick }: RenderSuggestion
9
13
  key={index}
10
14
  title={suggestion.title}
11
15
  message={suggestion.message}
12
- partial={suggestion.partial}
16
+ partial={suggestion.isLoading ?? suggestion.partial ?? isLoading}
13
17
  className={suggestion.className}
14
18
  onClick={() => onSuggestionClick(suggestion.message)}
15
19
  />