@copilotkit/react-core 1.50.0-beta.1 → 1.50.0-beta.10
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/CHANGELOG.md +93 -0
- package/dist/{chunk-UJBV5GAG.mjs → chunk-3775VM7Y.mjs} +32 -65
- package/dist/chunk-3775VM7Y.mjs.map +1 -0
- package/dist/{chunk-3GURHDG7.mjs → chunk-4HRUQH6U.mjs} +3 -3
- package/dist/{chunk-7BYHZLPL.mjs → chunk-4RRMC7L2.mjs} +4 -4
- package/dist/chunk-4RRMC7L2.mjs.map +1 -0
- package/dist/{chunk-D3QSYDJR.mjs → chunk-7IBF6RBW.mjs} +2 -2
- package/dist/{chunk-GMI4KO4X.mjs → chunk-7SHWECGN.mjs} +2 -2
- package/dist/{chunk-OVYFRPSN.mjs → chunk-ABWT4DRT.mjs} +2 -2
- package/dist/{chunk-WVLHXIFP.mjs → chunk-AFNWX62Q.mjs} +2 -2
- package/dist/{chunk-WVLHXIFP.mjs.map → chunk-AFNWX62Q.mjs.map} +1 -1
- package/dist/{chunk-JRT5BJF3.mjs → chunk-B5ELMVT7.mjs} +2 -2
- package/dist/{chunk-TXI72QHK.mjs → chunk-EG56H77V.mjs} +2 -2
- package/dist/{chunk-DCHSCK62.mjs → chunk-FYMZKPOL.mjs} +36 -42
- package/dist/chunk-FYMZKPOL.mjs.map +1 -0
- package/dist/{chunk-FBD24VEH.mjs → chunk-HE22TZMF.mjs} +2 -2
- package/dist/{chunk-FBD24VEH.mjs.map → chunk-HE22TZMF.mjs.map} +1 -1
- package/dist/chunk-I76HKHPJ.mjs +32 -0
- package/dist/chunk-I76HKHPJ.mjs.map +1 -0
- package/dist/{chunk-LHKZJ2ND.mjs → chunk-PMWUKW3Z.mjs} +3 -3
- package/dist/{chunk-NROJOTQP.mjs → chunk-QNUAXSDP.mjs} +9 -6
- package/dist/chunk-QNUAXSDP.mjs.map +1 -0
- package/dist/{chunk-NG26QEGF.mjs → chunk-T2VBHAAP.mjs} +9 -3
- package/dist/chunk-T2VBHAAP.mjs.map +1 -0
- package/dist/{chunk-QU6NONOD.mjs → chunk-U2ZRVVKT.mjs} +2 -2
- package/dist/{chunk-R4MR43UQ.mjs → chunk-VV56AVPB.mjs} +33 -9
- package/dist/chunk-VV56AVPB.mjs.map +1 -0
- package/dist/{chunk-5X5DJRQQ.mjs → chunk-WF65O6HX.mjs} +2 -7
- package/dist/chunk-WF65O6HX.mjs.map +1 -0
- package/dist/chunk-XDFVCQD3.mjs +27 -0
- package/dist/chunk-XDFVCQD3.mjs.map +1 -0
- package/dist/{chunk-WMJVBMUX.mjs → chunk-YCG6SNAU.mjs} +2 -2
- package/dist/{chunk-3R423LZT.mjs → chunk-YJGPIN3R.mjs} +3 -3
- package/dist/{chunk-BR5YEYZJ.mjs → chunk-YTQHRJUA.mjs} +2 -2
- package/dist/chunk-Z6JV2LRY.mjs +37 -0
- package/dist/chunk-Z6JV2LRY.mjs.map +1 -0
- package/dist/{chunk-24SCZAB4.mjs → chunk-ZYTXB6HH.mjs} +22 -14
- package/dist/chunk-ZYTXB6HH.mjs.map +1 -0
- package/dist/components/CopilotListeners.js +13 -146
- package/dist/components/CopilotListeners.js.map +1 -1
- package/dist/components/CopilotListeners.mjs +1 -6
- package/dist/components/copilot-provider/copilot-messages.js +1 -1
- package/dist/components/copilot-provider/copilot-messages.js.map +1 -1
- package/dist/components/copilot-provider/copilot-messages.mjs +2 -2
- package/dist/components/copilot-provider/copilotkit-props.d.ts +1 -1
- package/dist/components/copilot-provider/copilotkit.d.ts +1 -1
- package/dist/components/copilot-provider/copilotkit.js +35 -40
- package/dist/components/copilot-provider/copilotkit.js.map +1 -1
- package/dist/components/copilot-provider/copilotkit.mjs +9 -9
- package/dist/components/copilot-provider/index.d.ts +1 -1
- package/dist/components/copilot-provider/index.js +35 -40
- package/dist/components/copilot-provider/index.js.map +1 -1
- package/dist/components/copilot-provider/index.mjs +9 -9
- package/dist/components/dev-console/console-trigger.js +1 -1
- package/dist/components/dev-console/console-trigger.js.map +1 -1
- package/dist/components/dev-console/console-trigger.mjs +3 -3
- package/dist/components/dev-console/developer-console-modal.js +1 -1
- package/dist/components/dev-console/developer-console-modal.js.map +1 -1
- package/dist/components/dev-console/developer-console-modal.mjs +2 -2
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +35 -40
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +9 -9
- package/dist/context/copilot-context.d.ts +1 -1
- package/dist/context/copilot-context.js +1 -1
- package/dist/context/copilot-context.js.map +1 -1
- package/dist/context/copilot-context.mjs +1 -1
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/index.js.map +1 -1
- package/dist/context/index.mjs +1 -1
- package/dist/{copilot-context-1cd70a3f.d.ts → copilot-context-ec77e921.d.ts} +3 -3
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +254 -219
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +24 -23
- package/dist/hooks/use-agent-nodename.d.ts +3 -0
- package/dist/hooks/use-agent-nodename.js +56 -0
- package/dist/hooks/use-agent-nodename.js.map +1 -0
- package/dist/hooks/use-agent-nodename.mjs +8 -0
- package/dist/hooks/use-coagent-state-render-bridge.js +8 -5
- package/dist/hooks/use-coagent-state-render-bridge.js.map +1 -1
- package/dist/hooks/use-coagent-state-render-bridge.mjs +2 -2
- package/dist/hooks/use-coagent-state-render.js +1 -1
- package/dist/hooks/use-coagent-state-render.js.map +1 -1
- package/dist/hooks/use-coagent-state-render.mjs +2 -2
- package/dist/hooks/use-coagent.js +58 -21
- package/dist/hooks/use-coagent.js.map +1 -1
- package/dist/hooks/use-coagent.mjs +2 -1
- package/dist/hooks/use-copilot-action.js +5 -1
- package/dist/hooks/use-copilot-action.js.map +1 -1
- package/dist/hooks/use-copilot-action.mjs +2 -2
- package/dist/hooks/use-copilot-additional-instructions.js +1 -1
- package/dist/hooks/use-copilot-additional-instructions.js.map +1 -1
- package/dist/hooks/use-copilot-additional-instructions.mjs +2 -2
- package/dist/hooks/use-copilot-authenticated-action.js +6 -2
- package/dist/hooks/use-copilot-authenticated-action.js.map +1 -1
- package/dist/hooks/use-copilot-authenticated-action.mjs +4 -4
- package/dist/hooks/use-copilot-chat-headless_c.js +128 -140
- package/dist/hooks/use-copilot-chat-headless_c.js.map +1 -1
- package/dist/hooks/use-copilot-chat-headless_c.mjs +6 -6
- package/dist/hooks/{use-configure-chat-suggestions.d.ts → use-copilot-chat-suggestions.d.ts} +2 -3
- package/dist/hooks/use-copilot-chat-suggestions.js +60 -0
- package/dist/hooks/use-copilot-chat-suggestions.js.map +1 -0
- package/dist/hooks/use-copilot-chat-suggestions.mjs +8 -0
- package/dist/hooks/use-copilot-chat-suggestions.mjs.map +1 -0
- package/dist/hooks/use-copilot-chat.js +126 -138
- package/dist/hooks/use-copilot-chat.js.map +1 -1
- package/dist/hooks/use-copilot-chat.mjs +6 -6
- package/dist/hooks/use-copilot-chat_internal.d.ts +18 -1
- package/dist/hooks/use-copilot-chat_internal.js +126 -138
- package/dist/hooks/use-copilot-chat_internal.js.map +1 -1
- package/dist/hooks/use-copilot-chat_internal.mjs +5 -5
- package/dist/hooks/use-copilot-readable.d.ts +1 -1
- package/dist/hooks/use-copilot-readable.js +29 -5
- package/dist/hooks/use-copilot-readable.js.map +1 -1
- package/dist/hooks/use-copilot-readable.mjs +1 -1
- package/dist/hooks/use-default-tool.js +5 -1
- package/dist/hooks/use-default-tool.js.map +1 -1
- package/dist/hooks/use-default-tool.mjs +3 -3
- package/dist/hooks/use-frontend-tool.js +5 -1
- package/dist/hooks/use-frontend-tool.js.map +1 -1
- package/dist/hooks/use-frontend-tool.mjs +1 -1
- package/dist/hooks/use-langgraph-interrupt-render.js +77 -13
- package/dist/hooks/use-langgraph-interrupt-render.js.map +1 -1
- package/dist/hooks/use-langgraph-interrupt-render.mjs +3 -2
- package/dist/hooks/use-langgraph-interrupt.d.ts +1 -1
- package/dist/hooks/use-langgraph-interrupt.js +3 -3
- package/dist/hooks/use-langgraph-interrupt.js.map +1 -1
- package/dist/hooks/use-langgraph-interrupt.mjs +2 -2
- package/dist/hooks/use-make-copilot-document-readable.js +1 -1
- package/dist/hooks/use-make-copilot-document-readable.js.map +1 -1
- package/dist/hooks/use-make-copilot-document-readable.mjs +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +273 -246
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +34 -33
- package/dist/lib/copilot-task.d.ts +1 -1
- package/dist/lib/copilot-task.js.map +1 -1
- package/dist/lib/copilot-task.mjs +10 -10
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +10 -10
- package/dist/types/index.d.ts +1 -1
- package/dist/types/interrupt-action.d.ts +1 -1
- package/dist/types/interrupt-action.js.map +1 -1
- package/dist/utils/index.mjs +3 -3
- package/dist/v2/index.css +4 -0
- package/dist/v2/index.css.map +1 -0
- package/dist/v2/index.js.map +1 -1
- package/dist/v2/index.mjs +2 -0
- package/dist/v2/index.mjs.map +1 -1
- package/jest.config.js +12 -0
- package/package.json +14 -11
- package/src/components/CopilotListeners.tsx +1 -2
- package/src/components/copilot-provider/copilot-messages.tsx +0 -41
- package/src/components/copilot-provider/copilotkit.tsx +31 -31
- package/src/context/copilot-context.tsx +2 -2
- package/src/hooks/__tests__/use-coagent-config.test.ts +189 -129
- package/src/hooks/index.ts +2 -2
- package/src/hooks/use-agent-nodename.ts +30 -0
- package/src/hooks/use-coagent-state-render-bridge.tsx +22 -22
- package/src/hooks/use-coagent.ts +22 -13
- package/src/hooks/use-copilot-chat-suggestions.tsx +124 -0
- package/src/hooks/use-copilot-chat_internal.ts +78 -78
- package/src/hooks/use-copilot-readable.ts +30 -12
- package/src/hooks/use-frontend-tool.ts +10 -2
- package/src/hooks/use-langgraph-interrupt-render.ts +25 -7
- package/src/hooks/use-langgraph-interrupt.ts +2 -3
- package/src/types/interrupt-action.ts +2 -5
- package/src/v2/index.ts +2 -0
- package/tsup.config.ts +1 -1
- package/dist/chunk-24SCZAB4.mjs.map +0 -1
- package/dist/chunk-5X5DJRQQ.mjs.map +0 -1
- package/dist/chunk-7BYHZLPL.mjs.map +0 -1
- package/dist/chunk-CB7CRBDG.mjs +0 -48
- package/dist/chunk-CB7CRBDG.mjs.map +0 -1
- package/dist/chunk-DCHSCK62.mjs.map +0 -1
- package/dist/chunk-IUSKVYUI.mjs +0 -13
- package/dist/chunk-IUSKVYUI.mjs.map +0 -1
- package/dist/chunk-NG26QEGF.mjs.map +0 -1
- package/dist/chunk-NROJOTQP.mjs.map +0 -1
- package/dist/chunk-R4MR43UQ.mjs.map +0 -1
- package/dist/chunk-UJBV5GAG.mjs.map +0 -1
- package/dist/hooks/use-configure-chat-suggestions.js +0 -210
- package/dist/hooks/use-configure-chat-suggestions.js.map +0 -1
- package/dist/hooks/use-configure-chat-suggestions.mjs +0 -13
- package/src/hooks/use-configure-chat-suggestions.tsx +0 -85
- /package/dist/{chunk-3GURHDG7.mjs.map → chunk-4HRUQH6U.mjs.map} +0 -0
- /package/dist/{chunk-D3QSYDJR.mjs.map → chunk-7IBF6RBW.mjs.map} +0 -0
- /package/dist/{chunk-GMI4KO4X.mjs.map → chunk-7SHWECGN.mjs.map} +0 -0
- /package/dist/{chunk-OVYFRPSN.mjs.map → chunk-ABWT4DRT.mjs.map} +0 -0
- /package/dist/{chunk-JRT5BJF3.mjs.map → chunk-B5ELMVT7.mjs.map} +0 -0
- /package/dist/{chunk-TXI72QHK.mjs.map → chunk-EG56H77V.mjs.map} +0 -0
- /package/dist/{chunk-LHKZJ2ND.mjs.map → chunk-PMWUKW3Z.mjs.map} +0 -0
- /package/dist/{chunk-QU6NONOD.mjs.map → chunk-U2ZRVVKT.mjs.map} +0 -0
- /package/dist/{chunk-WMJVBMUX.mjs.map → chunk-YCG6SNAU.mjs.map} +0 -0
- /package/dist/{chunk-3R423LZT.mjs.map → chunk-YJGPIN3R.mjs.map} +0 -0
- /package/dist/{chunk-BR5YEYZJ.mjs.map → chunk-YTQHRJUA.mjs.map} +0 -0
- /package/dist/hooks/{use-configure-chat-suggestions.mjs.map → use-agent-nodename.mjs.map} +0 -0
- /package/src/v2/{styles.css → index.css} +0 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <Callout type="warning">
|
|
3
|
+
* useCopilotChatSuggestions is experimental. The interface is not final and
|
|
4
|
+
* can change without notice.
|
|
5
|
+
* </Callout>
|
|
6
|
+
*
|
|
7
|
+
* `useCopilotReadable` is a React hook that provides app-state and other information
|
|
8
|
+
* to the Copilot. Optionally, the hook can also handle hierarchical state within your
|
|
9
|
+
* application, passing these parent-child relationships to the Copilot.
|
|
10
|
+
*
|
|
11
|
+
* <br/>
|
|
12
|
+
* <img src="https://cdn.copilotkit.ai/docs/copilotkit/images/use-copilot-chat-suggestions/use-copilot-chat-suggestions.gif" width="500" />
|
|
13
|
+
*
|
|
14
|
+
* ## Usage
|
|
15
|
+
*
|
|
16
|
+
* ### Install Dependencies
|
|
17
|
+
*
|
|
18
|
+
* This component is part of the [@copilotkit/react-ui](https://npmjs.com/package/@copilotkit/react-ui) package.
|
|
19
|
+
*
|
|
20
|
+
* ```shell npm2yarn \"@copilotkit/react-ui"\
|
|
21
|
+
* npm install @copilotkit/react-core @copilotkit/react-ui
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ### Simple Usage
|
|
25
|
+
*
|
|
26
|
+
* ```tsx
|
|
27
|
+
* import { useCopilotChatSuggestions } from "@copilotkit/react-ui";
|
|
28
|
+
*
|
|
29
|
+
* export function MyComponent() {
|
|
30
|
+
* const [employees, setEmployees] = useState([]);
|
|
31
|
+
*
|
|
32
|
+
* useCopilotChatSuggestions({
|
|
33
|
+
* instructions: `The following employees are on duty: ${JSON.stringify(employees)}`,
|
|
34
|
+
* });
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* ### Dependency Management
|
|
39
|
+
*
|
|
40
|
+
* ```tsx
|
|
41
|
+
* import { useCopilotChatSuggestions } from "@copilotkit/react-ui";
|
|
42
|
+
*
|
|
43
|
+
* export function MyComponent() {
|
|
44
|
+
* useCopilotChatSuggestions(
|
|
45
|
+
* {
|
|
46
|
+
* instructions: "Suggest the most relevant next actions.",
|
|
47
|
+
* },
|
|
48
|
+
* [appState],
|
|
49
|
+
* );
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* In the example above, the suggestions are generated based on the given instructions.
|
|
54
|
+
* The hook monitors `appState`, and updates suggestions accordingly whenever it changes.
|
|
55
|
+
*
|
|
56
|
+
* ### Behavior and Lifecycle
|
|
57
|
+
*
|
|
58
|
+
* The hook registers the configuration with the chat context upon component mount and
|
|
59
|
+
* removes it on unmount, ensuring a clean and efficient lifecycle management.
|
|
60
|
+
*/
|
|
61
|
+
import {
|
|
62
|
+
useConfigureSuggestions,
|
|
63
|
+
useCopilotChatConfiguration,
|
|
64
|
+
useCopilotKit,
|
|
65
|
+
useSuggestions,
|
|
66
|
+
} from "@copilotkitnext/react";
|
|
67
|
+
import { useEffect } from "react";
|
|
68
|
+
import { StaticSuggestionsConfig, Suggestion } from "@copilotkitnext/core";
|
|
69
|
+
|
|
70
|
+
type StaticSuggestionInput = Omit<Suggestion, "isLoading"> & Partial<Pick<Suggestion, "isLoading">>;
|
|
71
|
+
|
|
72
|
+
type StaticSuggestionsConfigInput = Omit<StaticSuggestionsConfig, "suggestions"> & {
|
|
73
|
+
suggestions: StaticSuggestionInput[];
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
type DynamicSuggestionsConfigInput = {
|
|
77
|
+
/**
|
|
78
|
+
* A prompt or instructions for the GPT to generate suggestions.
|
|
79
|
+
*/
|
|
80
|
+
instructions: string;
|
|
81
|
+
/**
|
|
82
|
+
* The minimum number of suggestions to generate. Defaults to `1`.
|
|
83
|
+
* @default 1
|
|
84
|
+
*/
|
|
85
|
+
minSuggestions?: number;
|
|
86
|
+
/**
|
|
87
|
+
* The maximum number of suggestions to generate. Defaults to `3`.
|
|
88
|
+
* @default 1
|
|
89
|
+
*/
|
|
90
|
+
maxSuggestions?: number;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether the suggestions are available. Defaults to `enabled`.
|
|
94
|
+
* @default enabled
|
|
95
|
+
*/
|
|
96
|
+
available?: "enabled" | "disabled" | "always" | "before-first-message" | "after-first-message";
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* An optional class name to apply to the suggestions.
|
|
100
|
+
*/
|
|
101
|
+
className?: string;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type UseCopilotChatSuggestionsConfiguration =
|
|
105
|
+
| DynamicSuggestionsConfigInput
|
|
106
|
+
| StaticSuggestionsConfigInput;
|
|
107
|
+
|
|
108
|
+
export function useCopilotChatSuggestions(
|
|
109
|
+
config: UseCopilotChatSuggestionsConfiguration,
|
|
110
|
+
dependencies: any[] = [],
|
|
111
|
+
) {
|
|
112
|
+
const existingConfig = useCopilotChatConfiguration();
|
|
113
|
+
const resolvedAgentId = existingConfig?.agentId ?? "default";
|
|
114
|
+
|
|
115
|
+
const available =
|
|
116
|
+
(config.available === "enabled" ? "always" : config.available) ?? "before-first-message";
|
|
117
|
+
|
|
118
|
+
const finalSuggestionConfig = {
|
|
119
|
+
...config,
|
|
120
|
+
available,
|
|
121
|
+
consumerAgentId: resolvedAgentId, // Use chatConfig.agentId here
|
|
122
|
+
};
|
|
123
|
+
useConfigureSuggestions(finalSuggestionConfig, dependencies);
|
|
124
|
+
}
|
|
@@ -14,10 +14,6 @@ import {
|
|
|
14
14
|
} from "@copilotkitnext/react";
|
|
15
15
|
import { Suggestion } from "@copilotkitnext/core";
|
|
16
16
|
import { useLazyToolRenderer } from "./use-lazy-tool-renderer";
|
|
17
|
-
import {
|
|
18
|
-
useConfigureChatSuggestions,
|
|
19
|
-
UseCopilotChatSuggestionsConfiguration,
|
|
20
|
-
} from "./use-configure-chat-suggestions";
|
|
21
17
|
import { AbstractAgent, AGUIConnectNotImplementedError } from "@ag-ui/client";
|
|
22
18
|
import {
|
|
23
19
|
CoAgentStateRenderBridge,
|
|
@@ -71,7 +67,23 @@ export interface UseCopilotChatOptions {
|
|
|
71
67
|
* Disables inclusion of CopilotKit’s default system message. When true, no system message is sent (this also suppresses any custom message from <code>makeSystemMessage</code>).
|
|
72
68
|
*/
|
|
73
69
|
disableSystemMessage?: boolean;
|
|
74
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Controls the behavior of suggestions in the chat interface.
|
|
72
|
+
*
|
|
73
|
+
* `auto` (default) - Suggestions are generated automatically:
|
|
74
|
+
* - When the chat is first opened (empty state)
|
|
75
|
+
* - After each message exchange completes
|
|
76
|
+
* - Uses configuration from `useCopilotChatSuggestions` hooks
|
|
77
|
+
*
|
|
78
|
+
* `manual` - Suggestions are controlled programmatically:
|
|
79
|
+
* - Use `setSuggestions()` to set custom suggestions
|
|
80
|
+
* - Use `generateSuggestions()` to trigger AI generation
|
|
81
|
+
* - Access via `useCopilotChat` hook
|
|
82
|
+
*
|
|
83
|
+
* `SuggestionItem[]` - Static suggestions array:
|
|
84
|
+
* - Always shows the same suggestions
|
|
85
|
+
* - No AI generation involved
|
|
86
|
+
*/
|
|
75
87
|
suggestions?: ChatSuggestions;
|
|
76
88
|
}
|
|
77
89
|
|
|
@@ -227,7 +239,7 @@ export interface UseCopilotChatReturn {
|
|
|
227
239
|
* Manually set suggestions
|
|
228
240
|
* Useful for manual mode or custom suggestion workflows
|
|
229
241
|
*/
|
|
230
|
-
setSuggestions: (suggestions: Suggestion[]) => void;
|
|
242
|
+
setSuggestions: (suggestions: Omit<Suggestion, "isLoading">[]) => void;
|
|
231
243
|
|
|
232
244
|
/**
|
|
233
245
|
* Trigger AI-powered suggestion generation
|
|
@@ -258,27 +270,6 @@ export interface UseCopilotChatReturn {
|
|
|
258
270
|
threadId?: string;
|
|
259
271
|
}
|
|
260
272
|
|
|
261
|
-
function useConfigureSuggestions(suggestions?: UseCopilotChatOptions["suggestions"]) {
|
|
262
|
-
let suggestionsConfig: UseCopilotChatSuggestionsConfiguration;
|
|
263
|
-
|
|
264
|
-
if (Array.isArray(suggestions)) {
|
|
265
|
-
suggestionsConfig = {
|
|
266
|
-
suggestions,
|
|
267
|
-
available: "always",
|
|
268
|
-
};
|
|
269
|
-
} else if (suggestions === "auto") {
|
|
270
|
-
suggestionsConfig = {
|
|
271
|
-
available: suggestions === "auto" ? "always" : "disabled",
|
|
272
|
-
instructions:
|
|
273
|
-
"Suggest what the user could say next. Provide clear, highly relevant suggestions. Do not literally suggest function calls.",
|
|
274
|
-
};
|
|
275
|
-
} else {
|
|
276
|
-
suggestionsConfig = { available: "disabled" } as UseCopilotChatSuggestionsConfiguration;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
useConfigureChatSuggestions(suggestionsConfig);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
273
|
export function useCopilotChatInternal({
|
|
283
274
|
suggestions,
|
|
284
275
|
}: UseCopilotChatOptions = {}): UseCopilotChatReturn {
|
|
@@ -286,10 +277,9 @@ export function useCopilotChatInternal({
|
|
|
286
277
|
const { threadId, agentSession } = useCopilotContext();
|
|
287
278
|
const existingConfig = useCopilotChatConfiguration();
|
|
288
279
|
const [agentAvailable, setAgentAvailable] = useState(false);
|
|
289
|
-
useConfigureSuggestions(suggestions);
|
|
290
280
|
|
|
291
281
|
// Apply priority: props > existing config > defaults
|
|
292
|
-
const resolvedAgentId =
|
|
282
|
+
const resolvedAgentId = existingConfig?.agentId ?? "default";
|
|
293
283
|
const { agent } = useAgent({ agentId: resolvedAgentId });
|
|
294
284
|
|
|
295
285
|
useEffect(() => {
|
|
@@ -419,15 +409,14 @@ export function useCopilotChatInternal({
|
|
|
419
409
|
[latestSendMessageFunc],
|
|
420
410
|
);
|
|
421
411
|
|
|
422
|
-
const latestSetMessages = useUpdatedRef(agent?.setMessages);
|
|
423
412
|
const latestSetMessagesFunc = useCallback(
|
|
424
413
|
(messages: Message[] | DeprecatedGqlMessage[]) => {
|
|
425
414
|
if (messages.every((message) => message instanceof DeprecatedGqlMessage)) {
|
|
426
|
-
return
|
|
415
|
+
return agent?.setMessages?.(gqlToAGUI(messages));
|
|
427
416
|
}
|
|
428
|
-
return
|
|
417
|
+
return agent?.setMessages?.(messages);
|
|
429
418
|
},
|
|
430
|
-
[
|
|
419
|
+
[agent?.setMessages, agent],
|
|
431
420
|
);
|
|
432
421
|
|
|
433
422
|
const latestReload = useUpdatedRef(reload);
|
|
@@ -438,10 +427,9 @@ export function useCopilotChatInternal({
|
|
|
438
427
|
[latestReload],
|
|
439
428
|
);
|
|
440
429
|
|
|
441
|
-
const latestStop = useUpdatedRef(agent?.abortRun);
|
|
442
430
|
const latestStopFunc = useCallback(() => {
|
|
443
|
-
return
|
|
444
|
-
}, [
|
|
431
|
+
return agent?.abortRun?.();
|
|
432
|
+
}, [agent?.abortRun]);
|
|
445
433
|
|
|
446
434
|
const latestReset = useUpdatedRef(reset);
|
|
447
435
|
const latestResetFunc = useCallback(() => {
|
|
@@ -471,18 +459,19 @@ export function useCopilotChatInternal({
|
|
|
471
459
|
}
|
|
472
460
|
}
|
|
473
461
|
|
|
474
|
-
const bridgeRenderer =
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
462
|
+
const bridgeRenderer =
|
|
463
|
+
legacyCustomMessageRenderer || renderCustomMessage
|
|
464
|
+
? () => {
|
|
465
|
+
const customRender = renderCustomMessage?.({
|
|
466
|
+
message,
|
|
467
|
+
position: "before",
|
|
468
|
+
});
|
|
469
|
+
if (customRender) {
|
|
470
|
+
return customRender;
|
|
471
|
+
}
|
|
472
|
+
return legacyCustomMessageRenderer?.({ message, position: "before" });
|
|
482
473
|
}
|
|
483
|
-
|
|
484
|
-
}
|
|
485
|
-
: null;
|
|
474
|
+
: null;
|
|
486
475
|
|
|
487
476
|
if (bridgeRenderer) {
|
|
488
477
|
return { ...message, generativeUI: bridgeRenderer };
|
|
@@ -492,26 +481,27 @@ export function useCopilotChatInternal({
|
|
|
492
481
|
|
|
493
482
|
const hasAssistantMessages = processedMessages.some((msg) => msg.role === "assistant");
|
|
494
483
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
484
|
+
// TODO: what is this?
|
|
485
|
+
// if (legacyCustomMessageRenderer && !hasAssistantMessages) {
|
|
486
|
+
// const placeholderId = `coagent-state-render-${resolvedAgentId}`;
|
|
487
|
+
// const placeholderMessage: Message = {
|
|
488
|
+
// id: placeholderId,
|
|
489
|
+
// role: "assistant",
|
|
490
|
+
// content: "",
|
|
491
|
+
// name: "coagent-state-render",
|
|
492
|
+
// };
|
|
493
|
+
// processedMessages = [
|
|
494
|
+
// ...processedMessages,
|
|
495
|
+
// {
|
|
496
|
+
// ...placeholderMessage,
|
|
497
|
+
// generativeUI: () =>
|
|
498
|
+
// legacyCustomMessageRenderer({
|
|
499
|
+
// message: placeholderMessage,
|
|
500
|
+
// position: "before",
|
|
501
|
+
// }),
|
|
502
|
+
// } as Message,
|
|
503
|
+
// ];
|
|
504
|
+
// }
|
|
515
505
|
|
|
516
506
|
return processedMessages;
|
|
517
507
|
}, [
|
|
@@ -519,10 +509,20 @@ export function useCopilotChatInternal({
|
|
|
519
509
|
lazyToolRendered,
|
|
520
510
|
allMessages,
|
|
521
511
|
renderCustomMessage,
|
|
522
|
-
legacyCustomMessageRenderer,
|
|
512
|
+
// legacyCustomMessageRenderer,
|
|
523
513
|
resolvedAgentId,
|
|
524
514
|
]);
|
|
525
515
|
|
|
516
|
+
const renderedSuggestions = useMemo(() => {
|
|
517
|
+
if (Array.isArray(suggestions)) {
|
|
518
|
+
return {
|
|
519
|
+
suggestions: suggestions.map((s) => ({ ...s, isLoading: false })),
|
|
520
|
+
isLoading: false,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
return currentSuggestions;
|
|
524
|
+
}, [suggestions, currentSuggestions]);
|
|
525
|
+
|
|
526
526
|
// @ts-ignore
|
|
527
527
|
return {
|
|
528
528
|
messages: resolvedMessages,
|
|
@@ -533,15 +533,16 @@ export function useCopilotChatInternal({
|
|
|
533
533
|
stopGeneration: latestStopFunc,
|
|
534
534
|
reset: latestResetFunc,
|
|
535
535
|
deleteMessage: latestDeleteFunc,
|
|
536
|
-
isAvailable:
|
|
536
|
+
isAvailable: agentAvailable,
|
|
537
537
|
isLoading: Boolean(agent?.isRunning),
|
|
538
538
|
// mcpServers,
|
|
539
539
|
// setMcpServers,
|
|
540
|
-
suggestions:
|
|
541
|
-
setSuggestions: (suggestions: Suggestion[]) =>
|
|
540
|
+
suggestions: renderedSuggestions.suggestions,
|
|
541
|
+
setSuggestions: (suggestions: Omit<Suggestion, "isLoading">[]) =>
|
|
542
|
+
copilotkit.addSuggestionsConfig({ suggestions }),
|
|
542
543
|
generateSuggestions: async () => copilotkit.reloadSuggestions(resolvedAgentId),
|
|
543
544
|
resetSuggestions: () => copilotkit.clearSuggestions(resolvedAgentId),
|
|
544
|
-
isLoadingSuggestions:
|
|
545
|
+
isLoadingSuggestions: renderedSuggestions.isLoading,
|
|
545
546
|
interrupt,
|
|
546
547
|
agent,
|
|
547
548
|
threadId,
|
|
@@ -585,13 +586,12 @@ function useLegacyCoagentRenderer({
|
|
|
585
586
|
|
|
586
587
|
return ({ message, position }: LegacyRenderParams) => {
|
|
587
588
|
const effectiveThreadId = threadId ?? agent.threadId ?? "default";
|
|
588
|
-
const existingRunId = copilotkit.getRunIdForMessage(
|
|
589
|
-
agentId,
|
|
590
|
-
effectiveThreadId,
|
|
591
|
-
message.id,
|
|
592
|
-
);
|
|
589
|
+
const existingRunId = copilotkit.getRunIdForMessage(agentId, effectiveThreadId, message.id);
|
|
593
590
|
const runId = existingRunId || `pending:${message.id}`;
|
|
594
|
-
const messageIndex = Math.max(
|
|
591
|
+
const messageIndex = Math.max(
|
|
592
|
+
agent.messages.findIndex((msg) => msg.id === message.id),
|
|
593
|
+
0,
|
|
594
|
+
);
|
|
595
595
|
|
|
596
596
|
const bridgeProps: CoAgentStateRenderBridgeProps = {
|
|
597
597
|
message: message as any,
|
|
@@ -61,9 +61,8 @@
|
|
|
61
61
|
* }
|
|
62
62
|
* ```
|
|
63
63
|
*/
|
|
64
|
+
import { useCopilotKit } from "@copilotkitnext/react";
|
|
64
65
|
import { useEffect, useRef } from "react";
|
|
65
|
-
import { useCopilotContext } from "../context/copilot-context";
|
|
66
|
-
import { useAgentContext } from "@copilotkitnext/react";
|
|
67
66
|
|
|
68
67
|
/**
|
|
69
68
|
* Options for the useCopilotReadable hook.
|
|
@@ -99,19 +98,38 @@ export interface UseCopilotReadableOptions {
|
|
|
99
98
|
convert?: (description: string, value: any) => string;
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
function convertToJSON(description: string, value: any): string {
|
|
103
|
-
return `${description}: ${typeof value === "string" ? value : JSON.stringify(value)}`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
101
|
/**
|
|
107
102
|
* Adds the given information to the Copilot context to make it readable by Copilot.
|
|
108
103
|
*/
|
|
109
104
|
export function useCopilotReadable(
|
|
110
|
-
{ description, value }: UseCopilotReadableOptions,
|
|
105
|
+
{ description, value, convert, available }: UseCopilotReadableOptions,
|
|
111
106
|
dependencies?: any[],
|
|
112
|
-
):
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
): string | undefined {
|
|
108
|
+
const { copilotkit } = useCopilotKit();
|
|
109
|
+
const ctxIdRef = useRef<string | undefined>(undefined);
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
if (!copilotkit) return;
|
|
112
|
+
|
|
113
|
+
const found = Object.entries(copilotkit.context).find(([id, ctxItem]) => {
|
|
114
|
+
return JSON.stringify({ description, value }) == JSON.stringify(ctxItem);
|
|
115
|
+
});
|
|
116
|
+
if (found) {
|
|
117
|
+
ctxIdRef.current = found[0];
|
|
118
|
+
if (available === "disabled") copilotkit.removeContext(ctxIdRef.current);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (!found && available === "disabled") return;
|
|
122
|
+
|
|
123
|
+
ctxIdRef.current = copilotkit.addContext({
|
|
124
|
+
description,
|
|
125
|
+
value: (convert ?? JSON.stringify)(value),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return () => {
|
|
129
|
+
if (!ctxIdRef.current) return;
|
|
130
|
+
copilotkit.removeContext(ctxIdRef.current);
|
|
131
|
+
};
|
|
132
|
+
}, [description, value, convert]);
|
|
133
|
+
|
|
134
|
+
return ctxIdRef.current;
|
|
117
135
|
}
|
|
@@ -3,7 +3,10 @@ import { ActionRenderProps, FrontendAction } from "../types/frontend-action";
|
|
|
3
3
|
import { Parameter, getZodParameters, MappedParameterTypes } from "@copilotkit/shared";
|
|
4
4
|
import { parseJson } from "@copilotkit/shared";
|
|
5
5
|
import { ToolCallStatus } from "@copilotkitnext/core";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type ReactFrontendTool,
|
|
8
|
+
useFrontendTool as useFrontendToolVNext,
|
|
9
|
+
} from "@copilotkitnext/react";
|
|
7
10
|
|
|
8
11
|
type FrontendToolOptions<T extends Parameter[] | []> = ReactFrontendTool<MappedParameterTypes<T>>;
|
|
9
12
|
type FrontendToolRenderArgs<T extends Parameter[] | []> =
|
|
@@ -47,7 +50,12 @@ export function useFrontendTool<const T extends Parameter[] = []>(
|
|
|
47
50
|
|
|
48
51
|
if (typeof render === "string") {
|
|
49
52
|
const staticRender = render;
|
|
50
|
-
return (() =>
|
|
53
|
+
return (() =>
|
|
54
|
+
React.createElement(
|
|
55
|
+
React.Fragment,
|
|
56
|
+
null,
|
|
57
|
+
staticRender,
|
|
58
|
+
)) as FrontendToolOptions<T>["render"];
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
return ((args: FrontendToolRenderArgs<T>) => {
|
|
@@ -3,6 +3,8 @@ import React, { useCallback, useEffect, useMemo } from "react";
|
|
|
3
3
|
import type { AbstractAgent, AgentSubscriber } from "@ag-ui/client";
|
|
4
4
|
import { MetaEventName } from "@copilotkit/runtime-client-gql";
|
|
5
5
|
import { dataToUUID, parseJson } from "@copilotkit/shared";
|
|
6
|
+
import { useAgentNodeName } from "./use-agent-nodename";
|
|
7
|
+
import { useCopilotChatConfiguration } from "@copilotkitnext/react";
|
|
6
8
|
|
|
7
9
|
type InterruptProps = {
|
|
8
10
|
event: any;
|
|
@@ -28,11 +30,15 @@ export function useLangGraphInterruptRender(
|
|
|
28
30
|
threadId,
|
|
29
31
|
interruptEventQueue,
|
|
30
32
|
addInterruptEvent,
|
|
31
|
-
|
|
33
|
+
resolveInterruptEvent,
|
|
32
34
|
} = useCopilotContext();
|
|
35
|
+
const existingConfig = useCopilotChatConfiguration();
|
|
36
|
+
const resolvedAgentId = existingConfig?.agentId ?? "default";
|
|
37
|
+
const nodeName = useAgentNodeName(resolvedAgentId);
|
|
33
38
|
|
|
34
39
|
useEffect(() => {
|
|
35
40
|
if (!agent) return;
|
|
41
|
+
let localInterrupt: any = null;
|
|
36
42
|
const subscriber: AgentSubscriber = {
|
|
37
43
|
onCustomEvent: ({ event }) => {
|
|
38
44
|
if (event.name === "on_interrupt") {
|
|
@@ -41,12 +47,21 @@ export function useLangGraphInterruptRender(
|
|
|
41
47
|
type: event.type,
|
|
42
48
|
value: parseJson(event.value, event.value),
|
|
43
49
|
};
|
|
44
|
-
const eventId = dataToUUID(
|
|
45
|
-
|
|
50
|
+
const eventId = dataToUUID(eventData, "interruptEvents");
|
|
51
|
+
localInterrupt = {
|
|
46
52
|
eventId,
|
|
47
53
|
threadId,
|
|
48
54
|
event: eventData,
|
|
49
|
-
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
onRunStartedEvent: () => {
|
|
59
|
+
localInterrupt = null;
|
|
60
|
+
},
|
|
61
|
+
onRunFinalized: () => {
|
|
62
|
+
if (localInterrupt) {
|
|
63
|
+
addInterruptEvent(localInterrupt);
|
|
64
|
+
localInterrupt = null;
|
|
50
65
|
}
|
|
51
66
|
},
|
|
52
67
|
};
|
|
@@ -67,7 +82,7 @@ export function useLangGraphInterruptRender(
|
|
|
67
82
|
},
|
|
68
83
|
},
|
|
69
84
|
});
|
|
70
|
-
|
|
85
|
+
resolveInterruptEvent(threadId, eventId, response ?? "");
|
|
71
86
|
},
|
|
72
87
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
88
|
[agent, threadId],
|
|
@@ -78,7 +93,7 @@ export function useLangGraphInterruptRender(
|
|
|
78
93
|
const eventQueue = interruptEventQueue[threadId] || [];
|
|
79
94
|
const currentQueuedEvent = eventQueue.find((qe) => !qe.event.response);
|
|
80
95
|
|
|
81
|
-
if (!currentQueuedEvent) return null;
|
|
96
|
+
if (!currentQueuedEvent || !agentSession) return null;
|
|
82
97
|
|
|
83
98
|
// Find the first matching action from all registered actions
|
|
84
99
|
const allActions = Object.values(interruptActions);
|
|
@@ -86,7 +101,10 @@ export function useLangGraphInterruptRender(
|
|
|
86
101
|
if (!action.enabled) return true; // No filter = match all
|
|
87
102
|
return action.enabled({
|
|
88
103
|
eventValue: currentQueuedEvent.event.value,
|
|
89
|
-
agentMetadata:
|
|
104
|
+
agentMetadata: {
|
|
105
|
+
...agentSession,
|
|
106
|
+
nodeName,
|
|
107
|
+
},
|
|
90
108
|
});
|
|
91
109
|
});
|
|
92
110
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { useContext, useEffect, useMemo } from "react";
|
|
2
2
|
import { CopilotContext } from "../context/copilot-context";
|
|
3
3
|
import { LangGraphInterruptRender } from "../types/interrupt-action";
|
|
4
|
-
import { useCopilotChatInternal } from "./use-copilot-chat_internal";
|
|
5
4
|
import { useToast } from "../components/toast/toast-provider";
|
|
6
5
|
import { dataToUUID } from "@copilotkit/shared";
|
|
7
6
|
|
|
@@ -13,7 +12,7 @@ export function useLangGraphInterrupt<TEventValue = any>(
|
|
|
13
12
|
useContext(CopilotContext);
|
|
14
13
|
const { addToast } = useToast();
|
|
15
14
|
|
|
16
|
-
const actionId = dataToUUID(
|
|
15
|
+
const actionId = dataToUUID(action, "lgAction");
|
|
17
16
|
|
|
18
17
|
useEffect(() => {
|
|
19
18
|
if (!action) return;
|
|
@@ -27,7 +26,7 @@ export function useLangGraphInterrupt<TEventValue = any>(
|
|
|
27
26
|
// return;
|
|
28
27
|
// }
|
|
29
28
|
|
|
30
|
-
setInterruptAction(
|
|
29
|
+
setInterruptAction({ ...action, id: actionId });
|
|
31
30
|
|
|
32
31
|
// Cleanup: remove action on unmount
|
|
33
32
|
return () => {
|
|
@@ -26,7 +26,7 @@ export interface LangGraphInterruptRender<TEventValue = any> {
|
|
|
26
26
|
* Method that returns a boolean, indicating if the interrupt action should run
|
|
27
27
|
* Useful when using multiple interrupts
|
|
28
28
|
*/
|
|
29
|
-
enabled?: (args: { eventValue: TEventValue; agentMetadata: AgentSession
|
|
29
|
+
enabled?: (args: { eventValue: TEventValue; agentMetadata: AgentSession }) => boolean;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export type LangGraphInterruptAction = LangGraphInterruptRender & {
|
|
@@ -34,10 +34,7 @@ export type LangGraphInterruptAction = LangGraphInterruptRender & {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
export type LangGraphInterruptActionSetterArgs = Partial<LangGraphInterruptRender> | null;
|
|
37
|
-
export type LangGraphInterruptActionSetter = (
|
|
38
|
-
threadId: string,
|
|
39
|
-
action: LangGraphInterruptActionSetterArgs,
|
|
40
|
-
) => void;
|
|
37
|
+
export type LangGraphInterruptActionSetter = (action: LangGraphInterruptActionSetterArgs) => void;
|
|
41
38
|
|
|
42
39
|
export interface QueuedInterruptEvent {
|
|
43
40
|
eventId: string; // Generated unique ID for tracking
|
package/src/v2/index.ts
CHANGED
package/tsup.config.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/use-coagent.ts"],"sourcesContent":["/**\n * <Callout type=\"info\">\n * Usage of this hook assumes some additional setup in your application, for more information\n * on that see the CoAgents <span className=\"text-blue-500\">[getting started guide](/coagents/quickstart/langgraph)</span>.\n * </Callout>\n * <Frame className=\"my-12\">\n * <img\n * src=\"https://cdn.copilotkit.ai/docs/copilotkit/images/coagents/SharedStateCoAgents.gif\"\n * alt=\"CoAgents demonstration\"\n * className=\"w-auto\"\n * />\n * </Frame>\n *\n * This hook is used to integrate an agent into your application. With its use, you can\n * render and update the state of an agent, allowing for a dynamic and interactive experience.\n * We call these shared state experiences agentic copilots, or CoAgents for short.\n *\n * ## Usage\n *\n * ### Simple Usage\n *\n * ```tsx\n * import { useCoAgent } from \"@copilotkit/react-core\";\n *\n * type AgentState = {\n * count: number;\n * }\n *\n * const agent = useCoAgent<AgentState>({\n * name: \"my-agent\",\n * initialState: {\n * count: 0,\n * },\n * });\n *\n * ```\n *\n * `useCoAgent` returns an object with the following properties:\n *\n * ```tsx\n * const {\n * name, // The name of the agent currently being used.\n * nodeName, // The name of the current LangGraph node.\n * state, // The current state of the agent.\n * setState, // A function to update the state of the agent.\n * running, // A boolean indicating if the agent is currently running.\n * start, // A function to start the agent.\n * stop, // A function to stop the agent.\n * run, // A function to re-run the agent. Takes a HintFunction to inform the agent why it is being re-run.\n * } = agent;\n * ```\n *\n * Finally we can leverage these properties to create reactive experiences with the agent!\n *\n * ```tsx\n * const { state, setState } = useCoAgent<AgentState>({\n * name: \"my-agent\",\n * initialState: {\n * count: 0,\n * },\n * });\n *\n * return (\n * <div>\n * <p>Count: {state.count}</p>\n * <button onClick={() => setState({ count: state.count + 1 })}>Increment</button>\n * </div>\n * );\n * ```\n *\n * This reactivity is bidirectional, meaning that changes to the state from the agent will be reflected in the UI and vice versa.\n *\n * ## Parameters\n * <PropertyReference name=\"options\" type=\"UseCoagentOptions<T>\" required>\n * The options to use when creating the coagent.\n * <PropertyReference name=\"name\" type=\"string\" required>\n * The name of the agent to use.\n * </PropertyReference>\n * <PropertyReference name=\"initialState\" type=\"T | any\">\n * The initial state of the agent.\n * </PropertyReference>\n * <PropertyReference name=\"state\" type=\"T | any\">\n * State to manage externally if you are using this hook with external state management.\n * </PropertyReference>\n * <PropertyReference name=\"setState\" type=\"(newState: T | ((prevState: T | undefined) => T)) => void\">\n * A function to update the state of the agent if you are using this hook with external state management.\n * </PropertyReference>\n * </PropertyReference>\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { Message } from \"@copilotkit/shared\";\nimport { useAgent } from \"@copilotkitnext/react\";\nimport { type AgentSubscriber } from \"@ag-ui/client\";\n\ninterface UseCoagentOptionsBase {\n /**\n * The name of the agent being used.\n */\n name: string;\n /**\n * @deprecated - use \"config.configurable\"\n * Config to pass to a LangGraph Agent\n */\n configurable?: Record<string, any>;\n /**\n * Config to pass to a LangGraph Agent\n */\n config?: {\n configurable?: Record<string, any>;\n [key: string]: any;\n };\n}\n\ninterface WithInternalStateManagementAndInitial<T> extends UseCoagentOptionsBase {\n /**\n * The initial state of the agent.\n */\n initialState: T;\n}\n\ninterface WithInternalStateManagement extends UseCoagentOptionsBase {\n /**\n * Optional initialState with default type any\n */\n initialState?: any;\n}\n\ninterface WithExternalStateManagement<T> extends UseCoagentOptionsBase {\n /**\n * The current state of the agent.\n */\n state: T;\n /**\n * A function to update the state of the agent.\n */\n setState: (newState: T | ((prevState: T | undefined) => T)) => void;\n}\n\ntype UseCoagentOptions<T> =\n | WithInternalStateManagementAndInitial<T>\n | WithInternalStateManagement\n | WithExternalStateManagement<T>;\n\nexport interface UseCoagentReturnType<T> {\n /**\n * The name of the agent being used.\n */\n name: string;\n /**\n * The name of the current LangGraph node.\n */\n nodeName?: string;\n /**\n * The ID of the thread the agent is running in.\n */\n threadId?: string;\n /**\n * A boolean indicating if the agent is currently running.\n */\n running: boolean;\n /**\n * The current state of the agent.\n */\n state: T;\n /**\n * A function to update the state of the agent.\n */\n setState: (newState: T | ((prevState: T | undefined) => T)) => void;\n /**\n * A function to start the agent.\n */\n start: () => void;\n /**\n * A function to stop the agent.\n */\n stop: () => void;\n /**\n * A function to re-run the agent. The hint function can be used to provide a hint to the agent\n * about why it is being re-run again.\n */\n run: (...args: any[]) => Promise<any>;\n}\n\nexport interface HintFunctionParams {\n /**\n * The previous state of the agent.\n */\n previousState: any;\n /**\n * The current state of the agent.\n */\n currentState: any;\n}\n\nexport type HintFunction = (params: HintFunctionParams) => Message | undefined;\n\n/**\n * This hook is used to integrate an agent into your application. With its use, you can\n * render and update the state of the agent, allowing for a dynamic and interactive experience.\n * We call these shared state experiences \"agentic copilots\". To get started using agentic copilots, which\n * we refer to as CoAgents, checkout the documentation at https://docs.copilotkit.ai/coagents/quickstart/langgraph.\n */\nexport function useCoAgent<T = any>(options: UseCoagentOptions<T>): UseCoagentReturnType<T> {\n const { agent } = useAgent({ agentId: options.name });\n const nodeNameRef = useRef<string>(\"start\");\n\n const handleStateUpdate = useCallback(\n (newState: T | ((prevState: T | undefined) => T)) => {\n if (!agent) return;\n\n if (typeof newState === \"function\") {\n const updater = newState as (prevState: T | undefined) => T;\n agent.setState(updater(agent.state));\n } else {\n agent.setState({ ...agent.state, ...newState });\n }\n },\n [agent?.state, agent?.setState],\n );\n\n const externalStateStr = useMemo(\n () => (isExternalStateManagement(options) ? JSON.stringify(options.state) : undefined),\n [isExternalStateManagement(options) ? JSON.stringify(options.state) : undefined],\n );\n\n // Sync internal state with external state if state management is external\n useEffect(() => {\n if (\n agent?.state &&\n isExternalStateManagement(options) &&\n JSON.stringify(options.state) !== JSON.stringify(agent.state)\n ) {\n handleStateUpdate(options.state);\n }\n }, [agent, externalStateStr, handleStateUpdate]);\n\n const hasStateValues = useCallback((value?: Record<string, any>) => {\n return Boolean(value && Object.keys(value).length);\n }, []);\n\n const initialStateRef = useRef<any>(\n isExternalStateManagement(options)\n ? options.state\n : \"initialState\" in options\n ? options.initialState\n : undefined,\n );\n\n useEffect(() => {\n if (isExternalStateManagement(options)) {\n initialStateRef.current = options.state;\n } else if (\"initialState\" in options) {\n initialStateRef.current = options.initialState;\n }\n }, [\n isExternalStateManagement(options)\n ? JSON.stringify(options.state)\n : \"initialState\" in options\n ? JSON.stringify(options.initialState)\n : undefined,\n ]);\n\n useEffect(() => {\n if (!agent) return;\n const subscriber: AgentSubscriber = {\n onStateChanged: (args: any) => {\n if (isExternalStateManagement(options)) {\n options.setState(args.state);\n }\n },\n onRunInitialized: (args: any) => {\n const runHasState = hasStateValues(args.state);\n if (runHasState) {\n handleStateUpdate(args.state);\n return;\n }\n\n if (hasStateValues(agent.state)) {\n return;\n }\n\n if (initialStateRef.current !== undefined) {\n handleStateUpdate(initialStateRef.current);\n }\n },\n onStepStartedEvent: ({ event }) => {\n nodeNameRef.current = event.stepName;\n },\n onRunStartedEvent: () => {\n nodeNameRef.current = \"start\";\n },\n onRunFinishedEvent: () => {\n nodeNameRef.current = \"end\";\n },\n };\n\n const subscription = agent.subscribe(subscriber);\n return () => {\n subscription.unsubscribe();\n };\n }, [agent, handleStateUpdate, hasStateValues]);\n\n // Return a consistent shape whether or not the agent is available\n return useMemo<UseCoagentReturnType<T>>(() => {\n if (!agent) {\n const noop = () => {};\n const noopAsync = async () => {};\n const initialState =\n // prefer externally provided state if available\n (\"state\" in options && (options as any).state) ??\n // then initialState if provided\n (\"initialState\" in options && (options as any).initialState) ??\n ({} as T);\n return {\n name: options.name,\n nodeName: nodeNameRef.current,\n threadId: undefined,\n running: false,\n state: initialState as T,\n setState: noop,\n start: noop,\n stop: noop,\n run: noopAsync,\n };\n }\n\n return {\n name: agent?.agentId ?? options.name,\n nodeName: nodeNameRef.current,\n threadId: agent.threadId,\n running: agent.isRunning,\n state: agent.state,\n setState: handleStateUpdate,\n // TODO: start and run both have same thing. need to figure out\n start: agent.runAgent,\n stop: agent.abortRun,\n run: agent.runAgent,\n };\n }, [\n agent?.state,\n agent?.runAgent,\n agent?.abortRun,\n agent?.runAgent,\n agent?.threadId,\n agent?.isRunning,\n agent?.agentId,\n handleStateUpdate,\n options.name,\n ]);\n}\n\nconst isExternalStateManagement = <T>(\n options: UseCoagentOptions<T>,\n): options is WithExternalStateManagement<T> => {\n return \"state\" in options && \"setState\" in options;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/CopilotListeners.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useAgent, useCopilotChatConfiguration, useCopilotKit } from \"@copilotkitnext/react\";\nimport { CopilotKitError, parseJson } from \"@copilotkit/shared\";\nimport { useCopilotContext } from \"../context\";\nimport { AbstractAgent, AgentSubscriber, AGUIConnectNotImplementedError } from \"@ag-ui/client\";\nimport { useErrorToast } from \"./error-boundary/error-utils\";\nimport { CopilotKitCoreSubscriber } from \"@copilotkitnext/core\";\nimport { useToast } from \"./toast/toast-provider\";\nimport { CopilotKitLowLevelError } from \"@copilotkit/shared\";\n\nconst usePredictStateSubscription = (agent?: AbstractAgent) => {\n const predictStateToolsRef = useRef<\n {\n tool: string;\n state_key: string;\n tool_argument: string;\n }[]\n >([]);\n\n const getSubscriber = useCallback(\n (agent: AbstractAgent): AgentSubscriber => ({\n onCustomEvent: ({ event }) => {\n if (event.name === \"PredictState\") {\n predictStateToolsRef.current = event.value;\n }\n },\n onToolCallArgsEvent: ({ partialToolCallArgs, toolCallName }) => {\n predictStateToolsRef.current.forEach((t) => {\n if (t?.tool !== toolCallName) return;\n\n const emittedState =\n typeof partialToolCallArgs === \"string\"\n ? parseJson(partialToolCallArgs as unknown as string, partialToolCallArgs)\n : partialToolCallArgs;\n\n agent.setState({\n [t.state_key]: emittedState[t.state_key],\n });\n });\n },\n }),\n [],\n );\n\n useEffect(() => {\n if (!agent) return;\n\n const subscriber = getSubscriber(agent);\n const { unsubscribe } = agent.subscribe(subscriber);\n return () => {\n unsubscribe();\n };\n }, [agent, getSubscriber]);\n};\n\nexport function CopilotListeners() {\n const { copilotkit } = useCopilotKit();\n const { agentSession } = useCopilotContext();\n const existingConfig = useCopilotChatConfiguration();\n const resolvedAgentId = agentSession?.agentName ?? existingConfig?.agentId ?? \"default\";\n const { setBannerError } = useToast();\n\n const { agent } = useAgent({ agentId: resolvedAgentId });\n\n usePredictStateSubscription(agent);\n\n useEffect(() => {\n const subscriber: CopilotKitCoreSubscriber = {\n onError: ({ error }) => {\n // @ts-expect-error -- for now, choose a random CPK error type to display the error toast\n setBannerError(new CopilotKitLowLevelError({ error, message: error.message }));\n },\n };\n const subscription = copilotkit.subscribe(subscriber);\n\n return () => {\n subscription.unsubscribe();\n };\n }, [copilotkit?.subscribe]);\n\n return null;\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,aAAa,WAAoB,cAAc;AACxD,SAAS,UAAU,6BAA6B,qBAAqB;AACrE,SAA0B,iBAAiB;AAM3C,SAAS,+BAA+B;AAExC,IAAM,8BAA8B,CAAC,UAA0B;AAC7D,QAAM,uBAAuB,OAM3B,CAAC,CAAC;AAEJ,QAAM,gBAAgB;AAAA,IACpB,CAACA,YAA2C;AAAA,MAC1C,eAAe,CAAC,EAAE,MAAM,MAAM;AAC5B,YAAI,MAAM,SAAS,gBAAgB;AACjC,+BAAqB,UAAU,MAAM;AAAA,QACvC;AAAA,MACF;AAAA,MACA,qBAAqB,CAAC,EAAE,qBAAqB,aAAa,MAAM;AAC9D,6BAAqB,QAAQ,QAAQ,CAAC,MAAM;AAC1C,eAAI,uBAAG,UAAS;AAAc;AAE9B,gBAAM,eACJ,OAAO,wBAAwB,WAC3B,UAAU,qBAA0C,mBAAmB,IACvE;AAEN,UAAAA,OAAM,SAAS;AAAA,YACb,CAAC,EAAE,SAAS,GAAG,aAAa,EAAE,SAAS;AAAA,UACzC,CAAC;AAAA,QACH,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,YAAU,MAAM;AACd,QAAI,CAAC;AAAO;AAEZ,UAAM,aAAa,cAAc,KAAK;AACtC,UAAM,EAAE,YAAY,IAAI,MAAM,UAAU,UAAU;AAClD,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,OAAO,aAAa,CAAC;AAC3B;AAEO,SAAS,mBAAmB;AAvDnC;AAwDE,QAAM,EAAE,WAAW,IAAI,cAAc;AACrC,QAAM,EAAE,aAAa,IAAI,kBAAkB;AAC3C,QAAM,iBAAiB,4BAA4B;AACnD,QAAM,mBAAkB,wDAAc,cAAd,YAA2B,iDAAgB,YAA3C,YAAsD;AAC9E,QAAM,EAAE,eAAe,IAAI,SAAS;AAEpC,QAAM,EAAE,MAAM,IAAI,SAAS,EAAE,SAAS,gBAAgB,CAAC;AAEvD,8BAA4B,KAAK;AAEjC,YAAU,MAAM;AACd,UAAM,aAAuC;AAAA,MAC3C,SAAS,CAAC,EAAE,MAAM,MAAM;AAEtB,uBAAe,IAAI,wBAAwB,EAAE,OAAO,SAAS,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC/E;AAAA,IACF;AACA,UAAM,eAAe,WAAW,UAAU,UAAU;AAEpD,WAAO,MAAM;AACX,mBAAa,YAAY;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,yCAAY,SAAS,CAAC;AAE1B,SAAO;AACT;","names":["agent"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/use-langgraph-interrupt.ts"],"sourcesContent":["import { useContext, useEffect, useMemo } from \"react\";\nimport { CopilotContext } from \"../context/copilot-context\";\nimport { LangGraphInterruptRender } from \"../types/interrupt-action\";\nimport { useCopilotChatInternal } from \"./use-copilot-chat_internal\";\nimport { useToast } from \"../components/toast/toast-provider\";\nimport { dataToUUID } from \"@copilotkit/shared\";\n\nexport function useLangGraphInterrupt<TEventValue = any>(\n action: Omit<LangGraphInterruptRender<TEventValue>, \"id\">,\n dependencies?: any[],\n) {\n const { setInterruptAction, removeInterruptAction, interruptActions, threadId } =\n useContext(CopilotContext);\n const { addToast } = useToast();\n\n const actionId = dataToUUID(JSON.stringify(action), \"lgAction\");\n\n useEffect(() => {\n if (!action) return;\n\n // if (!action.enabled) {\n // TODO: if there are any other actions registered, we need to warn the user that a current action without \"enabled\" might render for everything\n // addToast({\n // type: \"warning\",\n // message: \"An action is already registered for the interrupt event\",\n // });\n // return;\n // }\n\n setInterruptAction(threadId, { ...action, id: actionId });\n\n // Cleanup: remove action on unmount\n return () => {\n removeInterruptAction(actionId);\n };\n }, [setInterruptAction, removeInterruptAction, threadId, actionId, ...(dependencies || [])]);\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,YAAY,iBAA0B;AAK/C,SAAS,kBAAkB;AAEpB,SAAS,sBACd,QACA,cACA;AACA,QAAM,EAAE,oBAAoB,uBAAuB,kBAAkB,SAAS,IAC5E,WAAW,cAAc;AAC3B,QAAM,EAAE,SAAS,IAAI,SAAS;AAE9B,QAAM,WAAW,WAAW,KAAK,UAAU,MAAM,GAAG,UAAU;AAE9D,YAAU,MAAM;AACd,QAAI,CAAC;AAAQ;AAWb,uBAAmB,UAAU,iCAAK,SAAL,EAAa,IAAI,SAAS,EAAC;AAGxD,WAAO,MAAM;AACX,4BAAsB,QAAQ;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,oBAAoB,uBAAuB,UAAU,UAAU,GAAI,gBAAgB,CAAC,CAAE,CAAC;AAC7F;","names":[]}
|