@copilotkit/runtime 1.3.15 → 1.4.0-pre-1-4-0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/{chunk-WYB2Z6SM.mjs → chunk-3SXVSM2J.mjs} +2 -2
- package/dist/{chunk-FH4SPOAG.mjs → chunk-5DFP5VJV.mjs} +2 -2
- package/dist/{chunk-3RAQGSAI.mjs → chunk-5LEQEQFA.mjs} +689 -151
- package/dist/chunk-5LEQEQFA.mjs.map +1 -0
- package/dist/{chunk-MYZHUCL6.mjs → chunk-B74M7FXG.mjs} +1 -1
- package/dist/chunk-B74M7FXG.mjs.map +1 -0
- package/dist/{chunk-CUN5GXCO.mjs → chunk-KDT43TMW.mjs} +37 -10
- package/dist/chunk-KDT43TMW.mjs.map +1 -0
- package/dist/{chunk-R3IJK6GR.mjs → chunk-SBNW3ABC.mjs} +2 -2
- package/dist/{chunk-NMV7A7VP.mjs → chunk-VGYN7TGZ.mjs} +1 -1
- package/dist/chunk-VGYN7TGZ.mjs.map +1 -0
- package/dist/{copilot-runtime-df3527ad.d.ts → copilot-runtime-68acb673.d.ts} +29 -7
- package/dist/graphql/types/converted/index.d.ts +1 -1
- package/dist/graphql/types/converted/index.js.map +1 -1
- package/dist/graphql/types/converted/index.mjs +1 -1
- package/dist/{groq-adapter-b122e71f.d.ts → groq-adapter-c30654bd.d.ts} +4 -2
- package/dist/{index-cff31380.d.ts → index-439dfa2a.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +761 -196
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -9
- package/dist/index.mjs.map +1 -1
- package/dist/{langserve-a14a6849.d.ts → langserve-0d844922.d.ts} +1 -1
- package/dist/lib/index.d.ts +4 -4
- package/dist/lib/index.js +761 -196
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +13 -9
- package/dist/lib/integrations/index.d.ts +4 -4
- package/dist/lib/integrations/index.js +3 -1
- package/dist/lib/integrations/index.js.map +1 -1
- package/dist/lib/integrations/index.mjs +5 -5
- package/dist/lib/integrations/nest/index.d.ts +3 -3
- package/dist/lib/integrations/nest/index.js +3 -1
- package/dist/lib/integrations/nest/index.js.map +1 -1
- package/dist/lib/integrations/nest/index.mjs +3 -3
- package/dist/lib/integrations/node-express/index.d.ts +3 -3
- package/dist/lib/integrations/node-express/index.js +3 -1
- package/dist/lib/integrations/node-express/index.js.map +1 -1
- package/dist/lib/integrations/node-express/index.mjs +3 -3
- package/dist/lib/integrations/node-http/index.d.ts +3 -3
- package/dist/lib/integrations/node-http/index.js +3 -1
- package/dist/lib/integrations/node-http/index.js.map +1 -1
- package/dist/lib/integrations/node-http/index.mjs +2 -2
- package/dist/service-adapters/index.d.ts +4 -4
- package/dist/service-adapters/index.js.map +1 -1
- package/dist/service-adapters/index.mjs +1 -1
- package/package.json +6 -4
- package/src/agents/langgraph/event-source.ts +62 -94
- package/src/agents/langgraph/events.ts +26 -17
- package/src/graphql/types/converted/index.ts +5 -1
- package/src/lib/runtime/copilot-runtime.ts +58 -11
- package/src/lib/runtime/remote-action-constructors.ts +284 -0
- package/src/lib/runtime/remote-actions.ts +65 -159
- package/src/lib/runtime/remote-lg-cloud-action.ts +624 -0
- package/src/service-adapters/langchain/langchain-adapter.ts +3 -1
- package/dist/chunk-3RAQGSAI.mjs.map +0 -1
- package/dist/chunk-CUN5GXCO.mjs.map +0 -1
- package/dist/chunk-MYZHUCL6.mjs.map +0 -1
- package/dist/chunk-NMV7A7VP.mjs.map +0 -1
- /package/dist/{chunk-WYB2Z6SM.mjs.map → chunk-3SXVSM2J.mjs.map} +0 -0
- /package/dist/{chunk-FH4SPOAG.mjs.map → chunk-5DFP5VJV.mjs.map} +0 -0
- /package/dist/{chunk-R3IJK6GR.mjs.map → chunk-SBNW3ABC.mjs.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReplaySubject, scan, mergeMap, catchError } from "rxjs";
|
|
2
|
-
import { LangGraphEvent, LangGraphEventTypes } from "./events";
|
|
2
|
+
import { CustomEventNames, LangGraphEvent, LangGraphEventTypes } from "./events";
|
|
3
3
|
import { RuntimeEvent, RuntimeEventTypes } from "../../service-adapters/events";
|
|
4
4
|
import { randomId } from "@copilotkit/shared";
|
|
5
5
|
|
|
@@ -15,63 +15,7 @@ interface LangGraphEventWithState {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export class RemoteLangGraphEventSource {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
async streamResponse(response: Response) {
|
|
21
|
-
const reader = response.body!.getReader();
|
|
22
|
-
const decoder = new TextDecoder();
|
|
23
|
-
let buffer = [];
|
|
24
|
-
const eventStream$ = this.eventStream$;
|
|
25
|
-
|
|
26
|
-
function flushBuffer() {
|
|
27
|
-
const currentBuffer = buffer.join("");
|
|
28
|
-
if (currentBuffer.trim().length === 0) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const parts = currentBuffer.split("\n");
|
|
32
|
-
if (parts.length === 0) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const lastPartIsComplete = currentBuffer.endsWith("\n");
|
|
37
|
-
|
|
38
|
-
// truncate buffer
|
|
39
|
-
buffer = [];
|
|
40
|
-
|
|
41
|
-
if (!lastPartIsComplete) {
|
|
42
|
-
// put back the last part
|
|
43
|
-
buffer.push(parts.pop());
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
parts
|
|
47
|
-
.map((part) => part.trim())
|
|
48
|
-
.filter((part) => part != "")
|
|
49
|
-
.forEach((part) => {
|
|
50
|
-
eventStream$.next(JSON.parse(part));
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
while (true) {
|
|
56
|
-
const { done, value } = await reader.read();
|
|
57
|
-
|
|
58
|
-
if (!done) {
|
|
59
|
-
buffer.push(decoder.decode(value, { stream: true }));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
flushBuffer();
|
|
63
|
-
|
|
64
|
-
if (done) {
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error("Error in stream", error);
|
|
70
|
-
eventStream$.error(error);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
eventStream$.complete();
|
|
74
|
-
}
|
|
18
|
+
public eventStream$ = new ReplaySubject<LangGraphEvent>();
|
|
75
19
|
|
|
76
20
|
private shouldEmitToolCall(
|
|
77
21
|
shouldEmitToolCalls: string | string[] | boolean,
|
|
@@ -93,7 +37,7 @@ export class RemoteLangGraphEventSource {
|
|
|
93
37
|
scan(
|
|
94
38
|
(acc, event) => {
|
|
95
39
|
if (event.event === LangGraphEventTypes.OnChatModelStream) {
|
|
96
|
-
// @ts-
|
|
40
|
+
// @ts-expect-error -- LangGraph Cloud implementation stores data outside of kwargs
|
|
97
41
|
const content = event.data?.chunk?.kwargs?.content ?? event.data?.chunk?.content;
|
|
98
42
|
|
|
99
43
|
if (typeof content === "string") {
|
|
@@ -104,20 +48,28 @@ export class RemoteLangGraphEventSource {
|
|
|
104
48
|
acc.content = null;
|
|
105
49
|
}
|
|
106
50
|
|
|
107
|
-
|
|
51
|
+
const toolCallChunks =
|
|
52
|
+
// @ts-expect-error -- LangGraph Cloud implementation stores data outside of kwargs
|
|
53
|
+
event.data?.chunk?.kwargs?.tool_call_chunks ?? event.data?.chunk?.tool_call_chunks;
|
|
54
|
+
|
|
55
|
+
const toolCallMessageId =
|
|
56
|
+
event.data?.chunk?.kwargs?.id ??
|
|
57
|
+
(event.data?.chunk?.id as unknown as string | undefined);
|
|
58
|
+
|
|
59
|
+
if (toolCallChunks && toolCallChunks.length > 0) {
|
|
108
60
|
acc.prevToolCallMessageId = acc.toolCallMessageId;
|
|
109
|
-
acc.toolCallMessageId =
|
|
110
|
-
if (
|
|
111
|
-
acc.toolCallName =
|
|
61
|
+
acc.toolCallMessageId = toolCallMessageId;
|
|
62
|
+
if (toolCallChunks[0]?.name) {
|
|
63
|
+
acc.toolCallName = toolCallChunks[0].name;
|
|
112
64
|
}
|
|
113
|
-
if (
|
|
114
|
-
acc.toolCallId =
|
|
65
|
+
if (toolCallChunks[0]?.id) {
|
|
66
|
+
acc.toolCallId = toolCallChunks[0].id;
|
|
115
67
|
}
|
|
116
68
|
acc.prevMessageId = acc.messageId;
|
|
117
|
-
acc.messageId =
|
|
69
|
+
acc.messageId = toolCallMessageId;
|
|
118
70
|
} else if (acc.content && acc.content != "") {
|
|
119
71
|
acc.prevMessageId = acc.messageId;
|
|
120
|
-
acc.messageId =
|
|
72
|
+
acc.messageId = toolCallMessageId;
|
|
121
73
|
} else {
|
|
122
74
|
acc.prevToolCallMessageId = acc.toolCallMessageId;
|
|
123
75
|
acc.prevMessageId = acc.messageId;
|
|
@@ -183,32 +135,45 @@ export class RemoteLangGraphEventSource {
|
|
|
183
135
|
}
|
|
184
136
|
|
|
185
137
|
switch (eventWithState.event!.event) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
138
|
+
//
|
|
139
|
+
// Custom events
|
|
140
|
+
//
|
|
141
|
+
case LangGraphEventTypes.OnCustomEvent:
|
|
142
|
+
//
|
|
143
|
+
// Manually emit a message
|
|
144
|
+
//
|
|
145
|
+
if (eventWithState.event.name === CustomEventNames.CopilotKitManuallyEmitMessage) {
|
|
146
|
+
events.push({
|
|
147
|
+
type: RuntimeEventTypes.TextMessageStart,
|
|
148
|
+
messageId: eventWithState.event.data.message_id,
|
|
149
|
+
});
|
|
150
|
+
events.push({
|
|
151
|
+
type: RuntimeEventTypes.TextMessageContent,
|
|
152
|
+
content: eventWithState.event.data.message,
|
|
153
|
+
});
|
|
154
|
+
events.push({
|
|
155
|
+
type: RuntimeEventTypes.TextMessageEnd,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
//
|
|
159
|
+
// Manually emit a tool call
|
|
160
|
+
//
|
|
161
|
+
else if (
|
|
162
|
+
eventWithState.event.name === CustomEventNames.CopilotKitManuallyEmitToolCall
|
|
163
|
+
) {
|
|
164
|
+
events.push({
|
|
165
|
+
type: RuntimeEventTypes.ActionExecutionStart,
|
|
166
|
+
actionExecutionId: eventWithState.event.data.id,
|
|
167
|
+
actionName: eventWithState.event.data.name,
|
|
168
|
+
});
|
|
169
|
+
events.push({
|
|
170
|
+
type: RuntimeEventTypes.ActionExecutionArgs,
|
|
171
|
+
args: JSON.stringify(eventWithState.event.data.args),
|
|
172
|
+
});
|
|
173
|
+
events.push({
|
|
174
|
+
type: RuntimeEventTypes.ActionExecutionEnd,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
212
177
|
break;
|
|
213
178
|
case LangGraphEventTypes.OnCopilotKitStateSync:
|
|
214
179
|
events.push({
|
|
@@ -266,7 +231,10 @@ export class RemoteLangGraphEventSource {
|
|
|
266
231
|
}
|
|
267
232
|
}
|
|
268
233
|
|
|
269
|
-
const args =
|
|
234
|
+
const args =
|
|
235
|
+
eventWithState.event.data?.chunk?.kwargs?.tool_call_chunks?.[0]?.args ??
|
|
236
|
+
// @ts-expect-error -- sdf
|
|
237
|
+
eventWithState.event.data?.chunk?.tool_call_chunks?.[0]?.args;
|
|
270
238
|
const content = eventWithState.content;
|
|
271
239
|
|
|
272
240
|
// Tool call args: emit ActionExecutionArgs
|
|
@@ -8,8 +8,13 @@ export enum LangGraphEventTypes {
|
|
|
8
8
|
OnToolStart = "on_tool_start",
|
|
9
9
|
OnToolEnd = "on_tool_end",
|
|
10
10
|
OnCopilotKitStateSync = "on_copilotkit_state_sync",
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
OnCustomEvent = "on_custom_event",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export enum CustomEventNames {
|
|
15
|
+
CopilotKitManuallyEmitMessage = "copilotkit_manually_emit_message",
|
|
16
|
+
CopilotKitManuallyEmitToolCall = "copilotkit_manually_emit_tool_call",
|
|
17
|
+
CopilotKitManuallyEmitIntermediateState = "copilotkit_manually_emit_intermediate_state",
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
type LangGraphOnCopilotKitStateSyncEvent = {
|
|
@@ -24,19 +29,6 @@ type LangGraphOnCopilotKitStateSyncEvent = {
|
|
|
24
29
|
running: boolean;
|
|
25
30
|
};
|
|
26
31
|
|
|
27
|
-
type LangGraphOnCopilotKitManualMessageEvent = {
|
|
28
|
-
event: LangGraphEventTypes.OnCopilotKitEmitMessage;
|
|
29
|
-
message: string;
|
|
30
|
-
message_id: string;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
type LangGraphOnCopilotKitEmitToolCallEvent = {
|
|
34
|
-
event: LangGraphEventTypes.OnCopilotKitEmitToolCall;
|
|
35
|
-
name: string;
|
|
36
|
-
args: any;
|
|
37
|
-
id: string;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
32
|
type LangGraphOnChainStartEvent = {
|
|
41
33
|
event: LangGraphEventTypes.OnChainStart;
|
|
42
34
|
run_id: string;
|
|
@@ -312,6 +304,24 @@ type LangGraphOnToolEndEvent = {
|
|
|
312
304
|
parent_ids: string[];
|
|
313
305
|
};
|
|
314
306
|
|
|
307
|
+
type LangGraphOnCustomEvent = {
|
|
308
|
+
event: LangGraphEventTypes.OnCustomEvent;
|
|
309
|
+
run_id: string;
|
|
310
|
+
name: string;
|
|
311
|
+
tags: string[];
|
|
312
|
+
metadata: {
|
|
313
|
+
thread_id: string;
|
|
314
|
+
langgraph_step: number;
|
|
315
|
+
langgraph_node: string;
|
|
316
|
+
langgraph_triggers: string[];
|
|
317
|
+
langgraph_path: [string, string];
|
|
318
|
+
langgraph_checkpoint_ns: string;
|
|
319
|
+
checkpoint_ns: string;
|
|
320
|
+
};
|
|
321
|
+
data: any;
|
|
322
|
+
parent_ids: string[];
|
|
323
|
+
};
|
|
324
|
+
|
|
315
325
|
export type LangGraphEvent =
|
|
316
326
|
| LangGraphOnChainStartEvent
|
|
317
327
|
| LangGraphOnChainStreamEvent
|
|
@@ -322,5 +332,4 @@ export type LangGraphEvent =
|
|
|
322
332
|
| LangGraphOnToolStartEvent
|
|
323
333
|
| LangGraphOnToolEndEvent
|
|
324
334
|
| LangGraphOnCopilotKitStateSyncEvent
|
|
325
|
-
|
|
|
326
|
-
| LangGraphOnCopilotKitEmitToolCallEvent;
|
|
335
|
+
| LangGraphOnCustomEvent;
|
|
@@ -7,7 +7,11 @@ import {
|
|
|
7
7
|
import { BaseMessageInput } from "../base";
|
|
8
8
|
import { ActionExecutionScope, MessageRole } from "../enums";
|
|
9
9
|
|
|
10
|
-
type MessageType =
|
|
10
|
+
export type MessageType =
|
|
11
|
+
| "TextMessage"
|
|
12
|
+
| "ActionExecutionMessage"
|
|
13
|
+
| "ResultMessage"
|
|
14
|
+
| "AgentStateMessage";
|
|
11
15
|
|
|
12
16
|
export class Message extends BaseMessageInput {
|
|
13
17
|
type: MessageType;
|
|
@@ -12,19 +12,22 @@
|
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { Action, actionParametersToJsonSchema, Parameter
|
|
16
|
-
import { RemoteChain, RemoteChainParameters
|
|
15
|
+
import { Action, actionParametersToJsonSchema, Parameter } from "@copilotkit/shared";
|
|
16
|
+
import { CopilotServiceAdapter, RemoteChain, RemoteChainParameters } from "../../service-adapters";
|
|
17
17
|
import { MessageInput } from "../../graphql/inputs/message.input";
|
|
18
18
|
import { ActionInput } from "../../graphql/inputs/action.input";
|
|
19
19
|
import { RuntimeEventSource } from "../../service-adapters/events";
|
|
20
20
|
import { convertGqlInputToMessages } from "../../service-adapters/conversion";
|
|
21
|
-
import {
|
|
21
|
+
import { Message } from "../../graphql/types/converted";
|
|
22
22
|
import { ForwardedParametersInput } from "../../graphql/inputs/forwarded-parameters.input";
|
|
23
23
|
import {
|
|
24
|
-
setupRemoteActions,
|
|
25
|
-
RemoteActionDefinition,
|
|
26
|
-
LangGraphAgentAction,
|
|
27
24
|
isLangGraphAgentAction,
|
|
25
|
+
LangGraphAgentAction,
|
|
26
|
+
EndpointType,
|
|
27
|
+
setupRemoteActions,
|
|
28
|
+
EndpointDefinition,
|
|
29
|
+
CopilotKitEndpoint,
|
|
30
|
+
LangGraphCloudEndpoint,
|
|
28
31
|
} from "./remote-actions";
|
|
29
32
|
import { GraphQLContext } from "../integrations/shared";
|
|
30
33
|
import { AgentSessionInput } from "../../graphql/inputs/agent-session.input";
|
|
@@ -121,10 +124,15 @@ export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []
|
|
|
121
124
|
*/
|
|
122
125
|
actions?: ActionsConfiguration<T>;
|
|
123
126
|
|
|
127
|
+
/*
|
|
128
|
+
* Deprecated: See `remoteEndpoints`.
|
|
129
|
+
*/
|
|
130
|
+
remoteActions?: EndpointDefinition[];
|
|
131
|
+
|
|
124
132
|
/*
|
|
125
133
|
* A list of remote actions that can be executed.
|
|
126
134
|
*/
|
|
127
|
-
|
|
135
|
+
remoteEndpoints?: EndpointDefinition[];
|
|
128
136
|
|
|
129
137
|
/*
|
|
130
138
|
* An array of LangServer URLs.
|
|
@@ -134,7 +142,7 @@ export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []
|
|
|
134
142
|
|
|
135
143
|
export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
136
144
|
public actions: ActionsConfiguration<T>;
|
|
137
|
-
private
|
|
145
|
+
private remoteEndpointDefinitions: EndpointDefinition[];
|
|
138
146
|
private langserve: Promise<Action<any>>[] = [];
|
|
139
147
|
private onBeforeRequest?: OnBeforeRequestHandler;
|
|
140
148
|
private onAfterRequest?: OnAfterRequestHandler;
|
|
@@ -147,7 +155,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
147
155
|
this.langserve.push(remoteChain.toAction());
|
|
148
156
|
}
|
|
149
157
|
|
|
150
|
-
this.
|
|
158
|
+
this.remoteEndpointDefinitions = params?.remoteEndpoints || [];
|
|
151
159
|
|
|
152
160
|
this.onBeforeRequest = params?.middleware?.onBeforeRequest;
|
|
153
161
|
this.onAfterRequest = params?.middleware?.onAfterRequest;
|
|
@@ -244,7 +252,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
244
252
|
request: CopilotRuntimeRequest,
|
|
245
253
|
): Promise<CopilotRuntimeResponse> {
|
|
246
254
|
const { messages: rawMessages, outputMessagesPromise, graphqlContext, agentSession } = request;
|
|
247
|
-
const { threadId
|
|
255
|
+
const { threadId, agentName, nodeName } = agentSession;
|
|
248
256
|
const serverSideActions = await this.getServerSideActions(request);
|
|
249
257
|
|
|
250
258
|
const messages = convertGqlInputToMessages(rawMessages);
|
|
@@ -331,8 +339,17 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
331
339
|
console.error("Error loading langserve chain:", error);
|
|
332
340
|
}
|
|
333
341
|
}
|
|
342
|
+
|
|
343
|
+
const remoteEndpointDefinitions = this.remoteEndpointDefinitions.map(
|
|
344
|
+
(endpoint) =>
|
|
345
|
+
({
|
|
346
|
+
...endpoint,
|
|
347
|
+
type: this.resolveEndpointType(endpoint),
|
|
348
|
+
}) as EndpointDefinition,
|
|
349
|
+
);
|
|
350
|
+
|
|
334
351
|
const remoteActions = await setupRemoteActions({
|
|
335
|
-
|
|
352
|
+
remoteEndpointDefinitions,
|
|
336
353
|
graphqlContext,
|
|
337
354
|
messages: inputMessages,
|
|
338
355
|
agentStates,
|
|
@@ -346,6 +363,19 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
346
363
|
|
|
347
364
|
return [...configuredActions, ...langserveFunctions, ...remoteActions];
|
|
348
365
|
}
|
|
366
|
+
|
|
367
|
+
private resolveEndpointType(endpoint: EndpointDefinition) {
|
|
368
|
+
if (
|
|
369
|
+
!endpoint.type &&
|
|
370
|
+
"langsmithApiKey" in endpoint &&
|
|
371
|
+
"deploymentUrl" in endpoint &&
|
|
372
|
+
"agents" in endpoint
|
|
373
|
+
) {
|
|
374
|
+
return EndpointType.LangGraphCloud;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return endpoint.type;
|
|
378
|
+
}
|
|
349
379
|
}
|
|
350
380
|
|
|
351
381
|
export function flattenToolCallsNoDuplicates(toolsByPriority: ActionInput[]): ActionInput[] {
|
|
@@ -359,3 +389,20 @@ export function flattenToolCallsNoDuplicates(toolsByPriority: ActionInput[]): Ac
|
|
|
359
389
|
}
|
|
360
390
|
return allTools;
|
|
361
391
|
}
|
|
392
|
+
|
|
393
|
+
// The two functions below are "factory functions", meant to create the action objects that adhere to the expected interfaces
|
|
394
|
+
export function copilotKitEndpoint(config: Omit<CopilotKitEndpoint, "type">): CopilotKitEndpoint {
|
|
395
|
+
return {
|
|
396
|
+
...config,
|
|
397
|
+
type: EndpointType.CopilotKit,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export function langGraphCloudEndpoint(
|
|
402
|
+
config: Omit<LangGraphCloudEndpoint, "type">,
|
|
403
|
+
): LangGraphCloudEndpoint {
|
|
404
|
+
return {
|
|
405
|
+
...config,
|
|
406
|
+
type: EndpointType.LangGraphCloud,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CopilotKitEndpoint,
|
|
3
|
+
LangGraphAgentHandlerParams,
|
|
4
|
+
RemoteActionInfoResponse,
|
|
5
|
+
LangGraphCloudEndpoint,
|
|
6
|
+
} from "./remote-actions";
|
|
7
|
+
import { GraphQLContext } from "../integrations";
|
|
8
|
+
import { Logger } from "pino";
|
|
9
|
+
import { Message } from "../../graphql/types/converted";
|
|
10
|
+
import { AgentStateInput } from "../../graphql/inputs/agent-state.input";
|
|
11
|
+
import { Observable, ReplaySubject } from "rxjs";
|
|
12
|
+
import { RuntimeEvent } from "../../service-adapters/events";
|
|
13
|
+
import telemetry from "../telemetry-client";
|
|
14
|
+
import { RemoteLangGraphEventSource } from "../../agents/langgraph/event-source";
|
|
15
|
+
import { Action } from "@copilotkit/shared";
|
|
16
|
+
import { LangGraphEvent } from "../../agents/langgraph/events";
|
|
17
|
+
import { execute } from "./remote-lg-cloud-action";
|
|
18
|
+
|
|
19
|
+
export function constructLGCRemoteAction({
|
|
20
|
+
endpoint,
|
|
21
|
+
graphqlContext,
|
|
22
|
+
logger,
|
|
23
|
+
messages,
|
|
24
|
+
agentStates,
|
|
25
|
+
}: {
|
|
26
|
+
endpoint: LangGraphCloudEndpoint;
|
|
27
|
+
graphqlContext: GraphQLContext;
|
|
28
|
+
logger: Logger;
|
|
29
|
+
messages: Message[];
|
|
30
|
+
agentStates?: AgentStateInput[];
|
|
31
|
+
}) {
|
|
32
|
+
const agents = endpoint.agents.map((agent) => ({
|
|
33
|
+
name: agent.name,
|
|
34
|
+
description: agent.description,
|
|
35
|
+
parameters: [],
|
|
36
|
+
handler: async (_args: any) => {},
|
|
37
|
+
langGraphAgentHandler: async ({
|
|
38
|
+
name,
|
|
39
|
+
actionInputsWithoutAgents,
|
|
40
|
+
threadId,
|
|
41
|
+
nodeName,
|
|
42
|
+
}: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
|
|
43
|
+
logger.debug({ actionName: agent.name }, "Executing LangGraph Cloud agent");
|
|
44
|
+
|
|
45
|
+
telemetry.capture("oss.runtime.remote_action_executed", {});
|
|
46
|
+
|
|
47
|
+
let state = {};
|
|
48
|
+
if (agentStates) {
|
|
49
|
+
const jsonState = agentStates.find((state) => state.agentName === name)?.state;
|
|
50
|
+
if (jsonState) {
|
|
51
|
+
state = JSON.parse(jsonState);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const response = await execute({
|
|
57
|
+
logger,
|
|
58
|
+
deploymentUrl: endpoint.deploymentUrl,
|
|
59
|
+
langsmithApiKey: endpoint.langsmithApiKey,
|
|
60
|
+
agent,
|
|
61
|
+
threadId,
|
|
62
|
+
nodeName,
|
|
63
|
+
messages,
|
|
64
|
+
state,
|
|
65
|
+
properties: graphqlContext.properties,
|
|
66
|
+
actions: actionInputsWithoutAgents.map((action) => ({
|
|
67
|
+
name: action.name,
|
|
68
|
+
description: action.description,
|
|
69
|
+
parameters: JSON.parse(action.jsonSchema) as string,
|
|
70
|
+
})),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const eventSource = new RemoteLangGraphEventSource();
|
|
74
|
+
streamResponse(response, eventSource.eventStream$);
|
|
75
|
+
return eventSource.processLangGraphEvents();
|
|
76
|
+
} catch (error) {
|
|
77
|
+
logger.error(
|
|
78
|
+
{ url: endpoint.deploymentUrl, status: 500, body: error.message },
|
|
79
|
+
"Failed to execute LangGraph Cloud agent",
|
|
80
|
+
);
|
|
81
|
+
throw new Error("Failed to execute LangGraph Cloud agent");
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
return [...agents];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function constructRemoteActions({
|
|
90
|
+
json,
|
|
91
|
+
url,
|
|
92
|
+
onBeforeRequest,
|
|
93
|
+
graphqlContext,
|
|
94
|
+
logger,
|
|
95
|
+
messages,
|
|
96
|
+
agentStates,
|
|
97
|
+
}: {
|
|
98
|
+
json: RemoteActionInfoResponse;
|
|
99
|
+
url: string;
|
|
100
|
+
onBeforeRequest?: CopilotKitEndpoint["onBeforeRequest"];
|
|
101
|
+
graphqlContext: GraphQLContext;
|
|
102
|
+
logger: Logger;
|
|
103
|
+
messages: Message[];
|
|
104
|
+
agentStates?: AgentStateInput[];
|
|
105
|
+
}): Action<any>[] {
|
|
106
|
+
const actions = json["actions"].map((action) => ({
|
|
107
|
+
name: action.name,
|
|
108
|
+
description: action.description,
|
|
109
|
+
parameters: action.parameters,
|
|
110
|
+
handler: async (args: any) => {
|
|
111
|
+
logger.debug({ actionName: action.name, args }, "Executing remote action");
|
|
112
|
+
|
|
113
|
+
const headers = createHeaders(onBeforeRequest, graphqlContext);
|
|
114
|
+
telemetry.capture("oss.runtime.remote_action_executed", {});
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const response = await fetch(`${url}/actions/execute`, {
|
|
118
|
+
method: "POST",
|
|
119
|
+
headers,
|
|
120
|
+
body: JSON.stringify({
|
|
121
|
+
name: action.name,
|
|
122
|
+
arguments: args,
|
|
123
|
+
properties: graphqlContext.properties,
|
|
124
|
+
}),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if (!response.ok) {
|
|
128
|
+
logger.error(
|
|
129
|
+
{ url, status: response.status, body: await response.text() },
|
|
130
|
+
"Failed to execute remote action",
|
|
131
|
+
);
|
|
132
|
+
return "Failed to execute remote action";
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const requestResult = await response.json();
|
|
136
|
+
|
|
137
|
+
const result = requestResult["result"];
|
|
138
|
+
logger.debug({ actionName: action.name, result }, "Executed remote action");
|
|
139
|
+
return result;
|
|
140
|
+
} catch (error) {
|
|
141
|
+
logger.error(
|
|
142
|
+
{ error: error.message ? error.message : error + "" },
|
|
143
|
+
"Failed to execute remote action",
|
|
144
|
+
);
|
|
145
|
+
return "Failed to execute remote action";
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
}));
|
|
149
|
+
|
|
150
|
+
const agents = json["agents"].map((agent) => ({
|
|
151
|
+
name: agent.name,
|
|
152
|
+
description: agent.description,
|
|
153
|
+
parameters: [],
|
|
154
|
+
handler: async (_args: any) => {},
|
|
155
|
+
|
|
156
|
+
langGraphAgentHandler: async ({
|
|
157
|
+
name,
|
|
158
|
+
actionInputsWithoutAgents,
|
|
159
|
+
threadId,
|
|
160
|
+
nodeName,
|
|
161
|
+
}: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
|
|
162
|
+
logger.debug({ actionName: agent.name }, "Executing remote agent");
|
|
163
|
+
|
|
164
|
+
const headers = createHeaders(onBeforeRequest, graphqlContext);
|
|
165
|
+
telemetry.capture("oss.runtime.remote_action_executed", {});
|
|
166
|
+
|
|
167
|
+
let state = {};
|
|
168
|
+
if (agentStates) {
|
|
169
|
+
const jsonState = agentStates.find((state) => state.agentName === name)?.state;
|
|
170
|
+
if (jsonState) {
|
|
171
|
+
state = JSON.parse(jsonState);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const response = await fetch(`${url}/agents/execute`, {
|
|
176
|
+
method: "POST",
|
|
177
|
+
headers,
|
|
178
|
+
body: JSON.stringify({
|
|
179
|
+
name,
|
|
180
|
+
threadId,
|
|
181
|
+
nodeName,
|
|
182
|
+
messages,
|
|
183
|
+
state,
|
|
184
|
+
properties: graphqlContext.properties,
|
|
185
|
+
actions: actionInputsWithoutAgents.map((action) => ({
|
|
186
|
+
name: action.name,
|
|
187
|
+
description: action.description,
|
|
188
|
+
parameters: JSON.parse(action.jsonSchema),
|
|
189
|
+
})),
|
|
190
|
+
}),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
logger.error(
|
|
195
|
+
{ url, status: response.status, body: await response.text() },
|
|
196
|
+
"Failed to execute remote agent",
|
|
197
|
+
);
|
|
198
|
+
throw new Error("Failed to execute remote agent");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const eventSource = new RemoteLangGraphEventSource();
|
|
202
|
+
streamResponse(response.body!, eventSource.eventStream$);
|
|
203
|
+
return eventSource.processLangGraphEvents();
|
|
204
|
+
},
|
|
205
|
+
}));
|
|
206
|
+
|
|
207
|
+
return [...actions, ...agents];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async function streamResponse(
|
|
211
|
+
response: ReadableStream<Uint8Array>,
|
|
212
|
+
eventStream$: ReplaySubject<LangGraphEvent>,
|
|
213
|
+
) {
|
|
214
|
+
const reader = response.getReader();
|
|
215
|
+
const decoder = new TextDecoder();
|
|
216
|
+
let buffer = [];
|
|
217
|
+
|
|
218
|
+
function flushBuffer() {
|
|
219
|
+
const currentBuffer = buffer.join("");
|
|
220
|
+
if (currentBuffer.trim().length === 0) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const parts = currentBuffer.split("\n");
|
|
224
|
+
if (parts.length === 0) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const lastPartIsComplete = currentBuffer.endsWith("\n");
|
|
229
|
+
|
|
230
|
+
// truncate buffer
|
|
231
|
+
buffer = [];
|
|
232
|
+
|
|
233
|
+
if (!lastPartIsComplete) {
|
|
234
|
+
// put back the last part
|
|
235
|
+
buffer.push(parts.pop());
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
parts
|
|
239
|
+
.map((part) => part.trim())
|
|
240
|
+
.filter((part) => part != "")
|
|
241
|
+
.forEach((part) => {
|
|
242
|
+
eventStream$.next(JSON.parse(part));
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
while (true) {
|
|
248
|
+
const { done, value } = await reader.read();
|
|
249
|
+
|
|
250
|
+
if (!done) {
|
|
251
|
+
buffer.push(decoder.decode(value, { stream: true }));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
flushBuffer();
|
|
255
|
+
|
|
256
|
+
if (done) {
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error("Error in stream", error);
|
|
262
|
+
eventStream$.error(error);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
eventStream$.complete();
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function createHeaders(
|
|
269
|
+
onBeforeRequest: CopilotKitEndpoint["onBeforeRequest"],
|
|
270
|
+
graphqlContext: GraphQLContext,
|
|
271
|
+
) {
|
|
272
|
+
const headers = {
|
|
273
|
+
"Content-Type": "application/json",
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
if (onBeforeRequest) {
|
|
277
|
+
const { headers: additionalHeaders } = onBeforeRequest({ ctx: graphqlContext });
|
|
278
|
+
if (additionalHeaders) {
|
|
279
|
+
Object.assign(headers, additionalHeaders);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return headers;
|
|
284
|
+
}
|