Skip to content

Commit d7af8cf

Browse files
authored
Merge branch 'main' into mme/discover-actions
2 parents 30232c0 + 57e58fc commit d7af8cf

91 files changed

Lines changed: 1562 additions & 2435 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CopilotKit/examples/next-openai/src/app/presentation/components/main/Presentation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"use client";
2-
import { useCopilotReadable } from "@copilotkit/react-core";
2+
import { useCoAgent, useCopilotAction, useCopilotReadable } from "@copilotkit/react-core";
33
import { useCopilotChatSuggestions } from "@copilotkit/react-ui";
44
import { useCallback, useMemo, useState } from "react";
55
import { Slide } from "./Slide";

CopilotKit/packages/react-core/src/hooks/use-chat.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,15 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
140140
const threadIdRef = useRef<string | null>(null);
141141
const runIdRef = useRef<string | null>(null);
142142

143+
143144
const runChatCompletionRef = useRef<(previousMessages: Message[]) => Promise<Message[]>>();
145+
// We need to keep a ref of coagent states because of renderAndWait - making sure
146+
// the latest state is sent to the API
147+
// This is a workaround and needs to be addressed in the future
148+
const coagentStatesRef = useRef<Record<string, CoagentState>>(coagentStates);
149+
coagentStatesRef.current = coagentStates;
150+
const agentSessionRef = useRef<AgentSession | null>(agentSession);
151+
agentSessionRef.current = agentSession;
144152

145153
const publicApiKey = copilotConfig.publicApiKey;
146154

@@ -180,11 +188,13 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
180188
runtimeClient.generateCopilotResponse({
181189
data: {
182190
frontend: {
183-
actions: actions.map((action) => ({
184-
name: action.name,
185-
description: action.description || "",
186-
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters || [])),
187-
})),
191+
actions: actions
192+
.filter((action) => !action.disabled)
193+
.map((action) => ({
194+
name: action.name,
195+
description: action.description || "",
196+
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters || [])),
197+
})),
188198
url: window.location.href,
189199
},
190200
threadId: threadIdRef.current,
@@ -211,12 +221,12 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
211221
metadata: {
212222
requestType: CopilotRequestType.Chat,
213223
},
214-
...(agentSession
224+
...(agentSessionRef.current
215225
? {
216-
agentSession,
226+
agentSession: agentSessionRef.current,
217227
}
218228
: {}),
219-
agentStates: Object.values(coagentStates).map((state) => ({
229+
agentStates: Object.values(coagentStatesRef.current).map((state) => ({
220230
agentName: state.name,
221231
state: JSON.stringify(state.state),
222232
})),
@@ -290,6 +300,10 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
290300
}
291301
// execute action
292302
try {
303+
// We update the message state before calling the handler so that the render
304+
// function can be called with `executing` state
305+
setMessages([...previousMessages, ...newMessages]);
306+
293307
const result = await onFunctionCall({
294308
messages: previousMessages,
295309
name: message.name,
@@ -336,6 +350,7 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
336350
.find((message) => message instanceof AgentStateMessage);
337351

338352
if (lastAgentStateMessage) {
353+
console.log(lastAgentStateMessage);
339354
if (lastAgentStateMessage.running) {
340355
setCoagentStates((prevAgentStates) => ({
341356
...prevAgentStates,

CopilotKit/packages/react-core/src/hooks/use-copilot-action.ts

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useRef, useEffect } from "react";
2-
import { FrontendAction } from "../types/frontend-action";
2+
import { FrontendAction, ActionRenderProps, ActionRenderPropsWait } from "../types/frontend-action";
33
import { useCopilotContext } from "../context/copilot-context";
44
import { Parameter, randomId } from "@copilotkit/shared";
55

@@ -18,6 +18,44 @@ export function useCopilotAction<const T extends Parameter[] | [] = []>(
1818
): void {
1919
const { setAction, removeAction, actions, chatComponentsCache } = useCopilotContext();
2020
const idRef = useRef<string>(randomId());
21+
const renderAndWaitRef = useRef<RenderAndWait | null>(null);
22+
23+
// clone the action to avoid mutating the original object
24+
action = { ...action };
25+
26+
// If the developer provides a renderAndWait function, we transform the action
27+
// to use a promise internally, so that we can treat it like a normal action.
28+
if (action.renderAndWait) {
29+
const renderAndWait = action.renderAndWait!;
30+
31+
// remove the renderAndWait function from the action
32+
action.renderAndWait = undefined;
33+
34+
// add a handler that will be called when the action is executed
35+
action.handler = (async () => {
36+
// we create a new promise when the handler is called
37+
let resolve: (result: any) => void;
38+
let reject: (error: any) => void;
39+
const promise = new Promise<any>((resolvePromise, rejectPromise) => {
40+
resolve = resolvePromise;
41+
reject = rejectPromise;
42+
});
43+
renderAndWaitRef.current = { promise, resolve: resolve!, reject: reject! };
44+
// then we await the promise (it will be resolved in the original renderAndWait function)
45+
return await promise;
46+
}) as any;
47+
48+
// add a render function that will be called when the action is rendered
49+
action.render = ((props: ActionRenderProps<any>): React.ReactElement => {
50+
const waitProps: ActionRenderPropsWait<any> = {
51+
status: props.status as any,
52+
args: props.args,
53+
result: props.result,
54+
handler: props.status === "executing" ? renderAndWaitRef.current!.resolve : undefined,
55+
};
56+
return renderAndWait(waitProps);
57+
}) as any;
58+
}
2159

2260
// If the developer doesn't provide dependencies, we assume they want to
2361
// update handler and render function when the action object changes.
@@ -34,9 +72,6 @@ export function useCopilotAction<const T extends Parameter[] | [] = []>(
3472
}
3573

3674
useEffect(() => {
37-
if (action.disabled) {
38-
return;
39-
}
4075
setAction(idRef.current, action as any);
4176
if (chatComponentsCache.current !== null && action.render !== undefined) {
4277
chatComponentsCache.current.actions[action.name] = action.render;
@@ -62,6 +97,12 @@ export function useCopilotAction<const T extends Parameter[] | [] = []>(
6297
]);
6398
}
6499

100+
interface RenderAndWait {
101+
promise: Promise<any>;
102+
resolve: (result: any) => void;
103+
reject: (error: any) => void;
104+
}
105+
65106
// Usage Example:
66107
// useCopilotAction({
67108
// name: "myAction",

CopilotKit/packages/react-core/src/types/frontend-action.ts

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,48 @@ interface CompleteStateNoArgs<T extends Parameter[] | [] = []> {
3737
result: any;
3838
}
3939

40+
interface InProgressStateWait<T extends Parameter[] | [] = []> {
41+
status: "inProgress";
42+
args: Partial<MappedParameterTypes<T>>;
43+
handler: undefined;
44+
result: undefined;
45+
}
46+
47+
interface ExecutingStateWait<T extends Parameter[] | [] = []> {
48+
status: "executing";
49+
args: MappedParameterTypes<T>;
50+
handler: (result: any) => void;
51+
result: undefined;
52+
}
53+
54+
interface CompleteStateWait<T extends Parameter[] | [] = []> {
55+
status: "complete";
56+
args: MappedParameterTypes<T>;
57+
handler: undefined;
58+
result: any;
59+
}
60+
61+
interface InProgressStateNoArgsWait<T extends Parameter[] | [] = []> {
62+
status: "inProgress";
63+
args: Partial<MappedParameterTypes<T>>;
64+
handler: undefined;
65+
result: undefined;
66+
}
67+
68+
interface ExecutingStateNoArgsWait<T extends Parameter[] | [] = []> {
69+
status: "executing";
70+
args: MappedParameterTypes<T>;
71+
handler: (result: any) => void;
72+
result: undefined;
73+
}
74+
75+
interface CompleteStateNoArgsWait<T extends Parameter[] | [] = []> {
76+
status: "complete";
77+
args: MappedParameterTypes<T>;
78+
handler: undefined;
79+
result: any;
80+
}
81+
4082
export type ActionRenderProps<T extends Parameter[] | [] = []> =
4183
| CompleteState<T>
4284
| ExecutingState<T>
@@ -47,13 +89,34 @@ export type ActionRenderPropsNoArgs<T extends Parameter[] | [] = []> =
4789
| ExecutingStateNoArgs<T>
4890
| InProgressStateNoArgs<T>;
4991

92+
export type ActionRenderPropsWait<T extends Parameter[] | [] = []> =
93+
| CompleteStateWait<T>
94+
| ExecutingStateWait<T>
95+
| InProgressStateWait<T>;
96+
97+
export type ActionRenderPropsNoArgsWait<T extends Parameter[] | [] = []> =
98+
| CompleteStateNoArgsWait<T>
99+
| ExecutingStateNoArgsWait<T>
100+
| InProgressStateNoArgsWait<T>;
101+
50102
export type FrontendAction<T extends Parameter[] | [] = []> = Action<T> & {
51103
disabled?: boolean;
52-
render?:
53-
| string
54-
| (T extends []
55-
? (props: ActionRenderPropsNoArgs<T>) => string | React.ReactElement
56-
: (props: ActionRenderProps<T>) => string | React.ReactElement);
57-
};
104+
} & (
105+
| {
106+
render?:
107+
| string
108+
| (T extends []
109+
? (props: ActionRenderPropsNoArgs<T>) => string | React.ReactElement
110+
: (props: ActionRenderProps<T>) => string | React.ReactElement);
111+
renderAndWait?: never;
112+
}
113+
| {
114+
render?: never;
115+
renderAndWait: T extends []
116+
? (props: ActionRenderPropsNoArgsWait<T>) => React.ReactElement
117+
: (props: ActionRenderPropsWait<T>) => React.ReactElement;
118+
handler?: never;
119+
}
120+
);
58121

59122
export type RenderFunctionStatus = ActionRenderProps<any>["status"];

docs/pages/_meta.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,35 @@ export default {
1717
"what-is-copilotkit": {
1818
title: "What is CopilotKit?",
1919
},
20-
"quickstart-chatbot": {
21-
title: "Quickstart: Chatbot",
20+
"quickstart": {
21+
title: "Quickstart",
2222
theme: {
2323
toc: false,
2424
},
2525
},
26+
"___guides": {
27+
type: "separator",
28+
title: "Guides",
29+
},
30+
"quickstart-leftover": {
31+
title: "Quickstart Leftover",
32+
theme: {
33+
toc: false,
34+
},
35+
},
36+
"___other": {
37+
type: "separator",
38+
title: "Other",
39+
},
2640
"coagents": {
2741
title: "CoAgents (Early Access)",
2842
},
43+
44+
"___tutorials": {
45+
type: "separator",
46+
title: "Tutorials",
47+
},
48+
2949
"tutorial-ai-todo-list-copilot": {
3050
title: "Tutorial: Todo List Copilot",
3151
},

docs/pages/concepts/_meta.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export default {
1212
"self-hosting": {
1313
title: <SideNavTitleWithIcon title="Self Hosting" icon={HiOutlineServerStack} />,
1414
},
15-
"different-llm-providers": {
16-
title: <SideNavTitleWithIcon title="LLM Providers" icon={HiOutlineServerStack} />,
15+
"different-llm-adapters": {
16+
title: <SideNavTitleWithIcon title="LLM Adapters" icon={HiOutlineServerStack} />,
1717
},
1818
"agents": {
1919
title: <SideNavTitleWithIcon title="Agents (LangChain)" icon={PiGraphDuotone} />,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import LlmServiceAdapters from "@/snippets/llm-adapters.mdx";
2+
3+
# LLM Adapters
4+
<LlmServiceAdapters />

docs/pages/concepts/different-llm-providers.mdx

Lines changed: 0 additions & 4 deletions
This file was deleted.

docs/pages/concepts/self-hosting.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Frame } from "@/components";
33
import { Steps } from 'nextra/components'
44
import SelfHostingCopilotRuntimeCreateEndpoint from "@/snippets/self-hosting-copilot-runtime-create-endpoint.mdx";
55
import SelfHostingCopilotRuntimeConfigureCopilotKitProvider from "@/snippets/self-hosting-copilot-runtime-configure-copilotkit-provider.mdx";
6-
import LlmServiceAdapters from "@/snippets/llm-service-adapters.mdx";
6+
import LlmServiceAdapters from "@/snippets/llm-adapters.mdx";
77

88
# Self Hosting (Copilot Runtime)
99

@@ -25,14 +25,14 @@ You may choose to self-host the Copilot Runtime, or [use Copilot Cloud](https://
2525

2626
</Steps>
2727

28-
## LLM Provider Service Adapters
28+
## LLM Adapters
2929
<LlmServiceAdapters />
3030

3131

3232
## Further Reading
3333

3434
- [`CopilotRuntime` Class Reference](/reference/classes/copilot-runtime/CopilotRuntime)
35-
- [Service Adapters](/reference/classes/CopilotRuntime/service-adapters/OpenAIAdapter)
35+
- [LLM Adapters](/reference/classes/CopilotRuntime/llm-adapters/OpenAIAdapter)
3636

3737
<Frame>
3838
<div className="w-full pb-4">

0 commit comments

Comments
 (0)