@copilotkit/runtime 1.3.12-feat-langgraph-cloud-release-alpha.0 → 1.3.12-fix-tool-call-dynamic-parameters.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 +4 -3
- package/dist/{chunk-7MQDBRXJ.mjs → chunk-24WEOOFX.mjs} +2 -2
- package/dist/{chunk-RKGJG3QX.mjs → chunk-AOYYOKTP.mjs} +133 -556
- package/dist/chunk-AOYYOKTP.mjs.map +1 -0
- package/dist/{chunk-6A7HQSQE.mjs → chunk-HKLL7TTP.mjs} +2 -2
- package/dist/{chunk-Z5LICW7Z.mjs → chunk-OSJXQNII.mjs} +9 -36
- package/dist/chunk-OSJXQNII.mjs.map +1 -0
- package/dist/{chunk-BPLF4QB2.mjs → chunk-SIMJ6TZU.mjs} +2 -2
- package/dist/{chunk-IPCABAGS.mjs → chunk-UYORVPCQ.mjs} +2 -2
- package/dist/{chunk-V7SK6QZN.mjs → chunk-ZEHCLFJ2.mjs} +9 -6
- package/dist/chunk-ZEHCLFJ2.mjs.map +1 -0
- package/dist/{copilot-runtime-aba7d4b4.d.ts → copilot-runtime-df3527ad.d.ts} +5 -27
- package/dist/index.d.ts +1 -1
- package/dist/index.js +186 -633
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9 -13
- package/dist/index.mjs.map +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +186 -633
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +9 -13
- package/dist/lib/integrations/index.d.ts +2 -2
- package/dist/lib/integrations/index.js +4 -5
- 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 +1 -1
- package/dist/lib/integrations/nest/index.js +4 -5
- 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 +1 -1
- package/dist/lib/integrations/node-express/index.js +4 -5
- 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 +1 -1
- package/dist/lib/integrations/node-http/index.js +4 -5
- 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.js +8 -5
- package/dist/service-adapters/index.js.map +1 -1
- package/dist/service-adapters/index.mjs +2 -2
- package/package.json +6 -7
- package/src/agents/langgraph/event-source.ts +67 -22
- package/src/lib/runtime/copilot-runtime.ts +11 -58
- package/src/lib/runtime/remote-actions.ts +159 -65
- package/src/service-adapters/events.ts +5 -1
- package/src/service-adapters/langchain/utils.test.ts +169 -0
- package/src/service-adapters/langchain/utils.ts +10 -5
- package/dist/chunk-RKGJG3QX.mjs.map +0 -1
- package/dist/chunk-V7SK6QZN.mjs.map +0 -1
- package/dist/chunk-Z5LICW7Z.mjs.map +0 -1
- package/src/lib/runtime/remote-action-constructors.ts +0 -281
- package/src/lib/runtime/remote-lg-cloud-action.ts +0 -438
- /package/dist/{chunk-7MQDBRXJ.mjs.map → chunk-24WEOOFX.mjs.map} +0 -0
- /package/dist/{chunk-6A7HQSQE.mjs.map → chunk-HKLL7TTP.mjs.map} +0 -0
- /package/dist/{chunk-BPLF4QB2.mjs.map → chunk-SIMJ6TZU.mjs.map} +0 -0
- /package/dist/{chunk-IPCABAGS.mjs.map → chunk-UYORVPCQ.mjs.map} +0 -0
|
@@ -15,7 +15,63 @@ interface LangGraphEventWithState {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export class RemoteLangGraphEventSource {
|
|
18
|
-
|
|
18
|
+
private eventStream$ = new ReplaySubject<LangGraphEvent>();
|
|
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
|
+
}
|
|
19
75
|
|
|
20
76
|
private shouldEmitToolCall(
|
|
21
77
|
shouldEmitToolCalls: string | string[] | boolean,
|
|
@@ -37,7 +93,7 @@ export class RemoteLangGraphEventSource {
|
|
|
37
93
|
scan(
|
|
38
94
|
(acc, event) => {
|
|
39
95
|
if (event.event === LangGraphEventTypes.OnChatModelStream) {
|
|
40
|
-
// @ts-
|
|
96
|
+
// @ts-ignore
|
|
41
97
|
const content = event.data?.chunk?.kwargs?.content ?? event.data?.chunk?.content;
|
|
42
98
|
|
|
43
99
|
if (typeof content === "string") {
|
|
@@ -48,28 +104,20 @@ export class RemoteLangGraphEventSource {
|
|
|
48
104
|
acc.content = null;
|
|
49
105
|
}
|
|
50
106
|
|
|
51
|
-
|
|
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) {
|
|
107
|
+
if (event.data?.chunk?.kwargs?.tool_call_chunks) {
|
|
60
108
|
acc.prevToolCallMessageId = acc.toolCallMessageId;
|
|
61
|
-
acc.toolCallMessageId =
|
|
62
|
-
if (
|
|
63
|
-
acc.toolCallName =
|
|
109
|
+
acc.toolCallMessageId = event.data.chunk.kwargs?.id;
|
|
110
|
+
if (event.data.chunk.kwargs.tool_call_chunks[0]?.name) {
|
|
111
|
+
acc.toolCallName = event.data.chunk.kwargs.tool_call_chunks[0].name;
|
|
64
112
|
}
|
|
65
|
-
if (
|
|
66
|
-
acc.toolCallId =
|
|
113
|
+
if (event.data.chunk.kwargs.tool_call_chunks[0]?.id) {
|
|
114
|
+
acc.toolCallId = event.data.chunk.kwargs.tool_call_chunks[0].id;
|
|
67
115
|
}
|
|
68
116
|
acc.prevMessageId = acc.messageId;
|
|
69
|
-
acc.messageId =
|
|
117
|
+
acc.messageId = event.data?.chunk?.kwargs?.id;
|
|
70
118
|
} else if (acc.content && acc.content != "") {
|
|
71
119
|
acc.prevMessageId = acc.messageId;
|
|
72
|
-
acc.messageId =
|
|
120
|
+
acc.messageId = event.data?.chunk?.kwargs?.id;
|
|
73
121
|
} else {
|
|
74
122
|
acc.prevToolCallMessageId = acc.toolCallMessageId;
|
|
75
123
|
acc.prevMessageId = acc.messageId;
|
|
@@ -218,10 +266,7 @@ export class RemoteLangGraphEventSource {
|
|
|
218
266
|
}
|
|
219
267
|
}
|
|
220
268
|
|
|
221
|
-
const args =
|
|
222
|
-
eventWithState.event.data?.chunk?.kwargs?.tool_call_chunks?.[0]?.args ??
|
|
223
|
-
// @ts-expect-error -- sdf
|
|
224
|
-
eventWithState.event.data?.chunk?.tool_call_chunks?.[0]?.args;
|
|
269
|
+
const args = eventWithState.event.data?.chunk?.kwargs?.tool_call_chunks?.[0]?.args;
|
|
225
270
|
const content = eventWithState.content;
|
|
226
271
|
|
|
227
272
|
// Tool call args: emit ActionExecutionArgs
|
|
@@ -12,22 +12,19 @@
|
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { Action, actionParametersToJsonSchema, Parameter } from "@copilotkit/shared";
|
|
16
|
-
import {
|
|
15
|
+
import { Action, actionParametersToJsonSchema, Parameter, randomId } from "@copilotkit/shared";
|
|
16
|
+
import { RemoteChain, RemoteChainParameters, CopilotServiceAdapter } 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 { Message } from "../../graphql/types/converted";
|
|
21
|
+
import { AgentStateMessage, Message } from "../../graphql/types/converted";
|
|
22
22
|
import { ForwardedParametersInput } from "../../graphql/inputs/forwarded-parameters.input";
|
|
23
23
|
import {
|
|
24
|
-
isLangGraphAgentAction,
|
|
25
|
-
LangGraphAgentAction,
|
|
26
|
-
EndpointType,
|
|
27
24
|
setupRemoteActions,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
RemoteActionDefinition,
|
|
26
|
+
LangGraphAgentAction,
|
|
27
|
+
isLangGraphAgentAction,
|
|
31
28
|
} from "./remote-actions";
|
|
32
29
|
import { GraphQLContext } from "../integrations/shared";
|
|
33
30
|
import { AgentSessionInput } from "../../graphql/inputs/agent-session.input";
|
|
@@ -124,15 +121,10 @@ export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []
|
|
|
124
121
|
*/
|
|
125
122
|
actions?: ActionsConfiguration<T>;
|
|
126
123
|
|
|
127
|
-
/*
|
|
128
|
-
* Deprecated: See `remoteEndpoints`.
|
|
129
|
-
*/
|
|
130
|
-
remoteActions?: EndpointDefinition[];
|
|
131
|
-
|
|
132
124
|
/*
|
|
133
125
|
* A list of remote actions that can be executed.
|
|
134
126
|
*/
|
|
135
|
-
|
|
127
|
+
remoteActions?: RemoteActionDefinition[];
|
|
136
128
|
|
|
137
129
|
/*
|
|
138
130
|
* An array of LangServer URLs.
|
|
@@ -142,7 +134,7 @@ export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []
|
|
|
142
134
|
|
|
143
135
|
export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
144
136
|
public actions: ActionsConfiguration<T>;
|
|
145
|
-
private
|
|
137
|
+
private remoteActionDefinitions: RemoteActionDefinition[];
|
|
146
138
|
private langserve: Promise<Action<any>>[] = [];
|
|
147
139
|
private onBeforeRequest?: OnBeforeRequestHandler;
|
|
148
140
|
private onAfterRequest?: OnAfterRequestHandler;
|
|
@@ -155,7 +147,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
155
147
|
this.langserve.push(remoteChain.toAction());
|
|
156
148
|
}
|
|
157
149
|
|
|
158
|
-
this.
|
|
150
|
+
this.remoteActionDefinitions = params?.remoteActions || [];
|
|
159
151
|
|
|
160
152
|
this.onBeforeRequest = params?.middleware?.onBeforeRequest;
|
|
161
153
|
this.onAfterRequest = params?.middleware?.onAfterRequest;
|
|
@@ -252,7 +244,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
252
244
|
request: CopilotRuntimeRequest,
|
|
253
245
|
): Promise<CopilotRuntimeResponse> {
|
|
254
246
|
const { messages: rawMessages, outputMessagesPromise, graphqlContext, agentSession } = request;
|
|
255
|
-
const { threadId, agentName, nodeName } = agentSession;
|
|
247
|
+
const { threadId = randomId(), agentName, nodeName } = agentSession;
|
|
256
248
|
const serverSideActions = await this.getServerSideActions(request);
|
|
257
249
|
|
|
258
250
|
const messages = convertGqlInputToMessages(rawMessages);
|
|
@@ -339,17 +331,8 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
339
331
|
console.error("Error loading langserve chain:", error);
|
|
340
332
|
}
|
|
341
333
|
}
|
|
342
|
-
|
|
343
|
-
const remoteEndpointDefinitions = this.remoteEndpointDefinitions.map(
|
|
344
|
-
(endpoint) =>
|
|
345
|
-
({
|
|
346
|
-
...endpoint,
|
|
347
|
-
type: this.resolveEndpointType(endpoint),
|
|
348
|
-
}) as EndpointDefinition,
|
|
349
|
-
);
|
|
350
|
-
|
|
351
334
|
const remoteActions = await setupRemoteActions({
|
|
352
|
-
|
|
335
|
+
remoteActionDefinitions: this.remoteActionDefinitions,
|
|
353
336
|
graphqlContext,
|
|
354
337
|
messages: inputMessages,
|
|
355
338
|
agentStates,
|
|
@@ -363,19 +346,6 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
363
346
|
|
|
364
347
|
return [...configuredActions, ...langserveFunctions, ...remoteActions];
|
|
365
348
|
}
|
|
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
|
-
}
|
|
379
349
|
}
|
|
380
350
|
|
|
381
351
|
export function flattenToolCallsNoDuplicates(toolsByPriority: ActionInput[]): ActionInput[] {
|
|
@@ -389,20 +359,3 @@ export function flattenToolCallsNoDuplicates(toolsByPriority: ActionInput[]): Ac
|
|
|
389
359
|
}
|
|
390
360
|
return allTools;
|
|
391
361
|
}
|
|
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
|
-
}
|
|
@@ -1,47 +1,20 @@
|
|
|
1
1
|
import { Action } from "@copilotkit/shared";
|
|
2
2
|
import { GraphQLContext } from "../integrations/shared";
|
|
3
3
|
import { Logger } from "pino";
|
|
4
|
+
import telemetry from "../../lib/telemetry-client";
|
|
4
5
|
import { Message } from "../../graphql/types/converted";
|
|
5
|
-
import { RuntimeEvent } from "../../service-adapters/events";
|
|
6
|
+
import { RuntimeEvent, RuntimeEventSubject } from "../../service-adapters/events";
|
|
7
|
+
import { RemoteLangGraphEventSource } from "../../agents/langgraph/event-source";
|
|
6
8
|
import { Observable } from "rxjs";
|
|
7
9
|
import { ActionInput } from "../../graphql/inputs/action.input";
|
|
8
10
|
import { AgentStateInput } from "../../graphql/inputs/agent-state.input";
|
|
9
|
-
import {
|
|
10
|
-
constructLGCRemoteAction,
|
|
11
|
-
constructRemoteActions,
|
|
12
|
-
createHeaders,
|
|
13
|
-
} from "./remote-action-constructors";
|
|
14
11
|
|
|
15
|
-
export type
|
|
16
|
-
|
|
17
|
-
export enum EndpointType {
|
|
18
|
-
CopilotKit = "copilotKit",
|
|
19
|
-
LangGraphCloud = "langgraph-cloud",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface BaseEndpointDefinition<TActionType extends EndpointType> {
|
|
23
|
-
type?: TActionType;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface CopilotKitEndpoint extends BaseEndpointDefinition<EndpointType.CopilotKit> {
|
|
12
|
+
export type RemoteActionDefinition = {
|
|
27
13
|
url: string;
|
|
28
14
|
onBeforeRequest?: ({ ctx }: { ctx: GraphQLContext }) => {
|
|
29
15
|
headers?: Record<string, string> | undefined;
|
|
30
16
|
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface LangGraphCloudAgent {
|
|
34
|
-
name: string;
|
|
35
|
-
description: string;
|
|
36
|
-
assistantId?: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface LangGraphCloudEndpoint
|
|
40
|
-
extends BaseEndpointDefinition<EndpointType.LangGraphCloud> {
|
|
41
|
-
deploymentUrl: string;
|
|
42
|
-
langsmithApiKey: string;
|
|
43
|
-
agents: LangGraphCloudAgent[];
|
|
44
|
-
}
|
|
17
|
+
};
|
|
45
18
|
|
|
46
19
|
export type RemoteActionInfoResponse = {
|
|
47
20
|
actions: any[];
|
|
@@ -66,6 +39,24 @@ export function isLangGraphAgentAction(action: Action<any>): action is LangGraph
|
|
|
66
39
|
return typeof (action as LangGraphAgentAction).langGraphAgentHandler === "function";
|
|
67
40
|
}
|
|
68
41
|
|
|
42
|
+
function createHeaders(
|
|
43
|
+
onBeforeRequest: RemoteActionDefinition["onBeforeRequest"],
|
|
44
|
+
graphqlContext: GraphQLContext,
|
|
45
|
+
) {
|
|
46
|
+
const headers = {
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (onBeforeRequest) {
|
|
51
|
+
const { headers: additionalHeaders } = onBeforeRequest({ ctx: graphqlContext });
|
|
52
|
+
if (additionalHeaders) {
|
|
53
|
+
Object.assign(headers, additionalHeaders);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return headers;
|
|
58
|
+
}
|
|
59
|
+
|
|
69
60
|
async function fetchRemoteInfo({
|
|
70
61
|
url,
|
|
71
62
|
onBeforeRequest,
|
|
@@ -74,7 +65,7 @@ async function fetchRemoteInfo({
|
|
|
74
65
|
frontendUrl,
|
|
75
66
|
}: {
|
|
76
67
|
url: string;
|
|
77
|
-
onBeforeRequest?:
|
|
68
|
+
onBeforeRequest?: RemoteActionDefinition["onBeforeRequest"];
|
|
78
69
|
graphqlContext: GraphQLContext;
|
|
79
70
|
logger: Logger;
|
|
80
71
|
frontendUrl?: string;
|
|
@@ -109,61 +100,164 @@ async function fetchRemoteInfo({
|
|
|
109
100
|
}
|
|
110
101
|
}
|
|
111
102
|
|
|
103
|
+
function constructRemoteActions({
|
|
104
|
+
json,
|
|
105
|
+
url,
|
|
106
|
+
onBeforeRequest,
|
|
107
|
+
graphqlContext,
|
|
108
|
+
logger,
|
|
109
|
+
messages,
|
|
110
|
+
agentStates,
|
|
111
|
+
}: {
|
|
112
|
+
json: RemoteActionInfoResponse;
|
|
113
|
+
url: string;
|
|
114
|
+
onBeforeRequest?: RemoteActionDefinition["onBeforeRequest"];
|
|
115
|
+
graphqlContext: GraphQLContext;
|
|
116
|
+
logger: Logger;
|
|
117
|
+
messages: Message[];
|
|
118
|
+
agentStates?: AgentStateInput[];
|
|
119
|
+
}): Action<any>[] {
|
|
120
|
+
const actions = json["actions"].map((action) => ({
|
|
121
|
+
name: action.name,
|
|
122
|
+
description: action.description,
|
|
123
|
+
parameters: action.parameters,
|
|
124
|
+
handler: async (args: any) => {
|
|
125
|
+
logger.debug({ actionName: action.name, args }, "Executing remote action");
|
|
126
|
+
|
|
127
|
+
const headers = createHeaders(onBeforeRequest, graphqlContext);
|
|
128
|
+
telemetry.capture("oss.runtime.remote_action_executed", {});
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const response = await fetch(`${url}/actions/execute`, {
|
|
132
|
+
method: "POST",
|
|
133
|
+
headers,
|
|
134
|
+
body: JSON.stringify({
|
|
135
|
+
name: action.name,
|
|
136
|
+
arguments: args,
|
|
137
|
+
properties: graphqlContext.properties,
|
|
138
|
+
}),
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
if (!response.ok) {
|
|
142
|
+
logger.error(
|
|
143
|
+
{ url, status: response.status, body: await response.text() },
|
|
144
|
+
"Failed to execute remote action",
|
|
145
|
+
);
|
|
146
|
+
return "Failed to execute remote action";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const requestResult = await response.json();
|
|
150
|
+
|
|
151
|
+
const result = requestResult["result"];
|
|
152
|
+
logger.debug({ actionName: action.name, result }, "Executed remote action");
|
|
153
|
+
return result;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
logger.error(
|
|
156
|
+
{ error: error.message ? error.message : error + "" },
|
|
157
|
+
"Failed to execute remote action",
|
|
158
|
+
);
|
|
159
|
+
return "Failed to execute remote action";
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
}));
|
|
163
|
+
|
|
164
|
+
const agents = json["agents"].map((agent) => ({
|
|
165
|
+
name: agent.name,
|
|
166
|
+
description: agent.description,
|
|
167
|
+
parameters: [],
|
|
168
|
+
handler: async (_args: any) => {},
|
|
169
|
+
|
|
170
|
+
langGraphAgentHandler: async ({
|
|
171
|
+
name,
|
|
172
|
+
actionInputsWithoutAgents,
|
|
173
|
+
threadId,
|
|
174
|
+
nodeName,
|
|
175
|
+
}: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
|
|
176
|
+
logger.debug({ actionName: agent.name }, "Executing remote agent");
|
|
177
|
+
|
|
178
|
+
const headers = createHeaders(onBeforeRequest, graphqlContext);
|
|
179
|
+
telemetry.capture("oss.runtime.remote_action_executed", {});
|
|
180
|
+
|
|
181
|
+
let state = {};
|
|
182
|
+
if (agentStates) {
|
|
183
|
+
const jsonState = agentStates.find((state) => state.agentName === name)?.state;
|
|
184
|
+
if (jsonState) {
|
|
185
|
+
state = JSON.parse(jsonState);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const response = await fetch(`${url}/agents/execute`, {
|
|
190
|
+
method: "POST",
|
|
191
|
+
headers,
|
|
192
|
+
body: JSON.stringify({
|
|
193
|
+
name,
|
|
194
|
+
threadId,
|
|
195
|
+
nodeName,
|
|
196
|
+
messages,
|
|
197
|
+
state,
|
|
198
|
+
properties: graphqlContext.properties,
|
|
199
|
+
actions: actionInputsWithoutAgents.map((action) => ({
|
|
200
|
+
name: action.name,
|
|
201
|
+
description: action.description,
|
|
202
|
+
parameters: JSON.parse(action.jsonSchema),
|
|
203
|
+
})),
|
|
204
|
+
}),
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
if (!response.ok) {
|
|
208
|
+
logger.error(
|
|
209
|
+
{ url, status: response.status, body: await response.text() },
|
|
210
|
+
"Failed to execute remote agent",
|
|
211
|
+
);
|
|
212
|
+
throw new Error("Failed to execute remote agent");
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const eventSource = new RemoteLangGraphEventSource();
|
|
216
|
+
eventSource.streamResponse(response);
|
|
217
|
+
return eventSource.processLangGraphEvents();
|
|
218
|
+
},
|
|
219
|
+
}));
|
|
220
|
+
|
|
221
|
+
return [...actions, ...agents];
|
|
222
|
+
}
|
|
223
|
+
|
|
112
224
|
export async function setupRemoteActions({
|
|
113
|
-
|
|
225
|
+
remoteActionDefinitions,
|
|
114
226
|
graphqlContext,
|
|
115
227
|
messages,
|
|
116
228
|
agentStates,
|
|
117
229
|
frontendUrl,
|
|
118
230
|
}: {
|
|
119
|
-
|
|
231
|
+
remoteActionDefinitions: RemoteActionDefinition[];
|
|
120
232
|
graphqlContext: GraphQLContext;
|
|
121
233
|
messages: Message[];
|
|
122
234
|
agentStates?: AgentStateInput[];
|
|
123
235
|
frontendUrl?: string;
|
|
124
236
|
}): Promise<Action[]> {
|
|
125
237
|
const logger = graphqlContext.logger.child({ component: "remote-actions.fetchRemoteActions" });
|
|
126
|
-
logger.debug({
|
|
238
|
+
logger.debug({ remoteActionDefinitions }, "Fetching remote actions");
|
|
127
239
|
|
|
128
|
-
// Remove duplicates of
|
|
129
|
-
const filtered =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
return index === self.findIndex((t: CopilotKitEndpoint) => t.url === value.url);
|
|
134
|
-
});
|
|
240
|
+
// Remove duplicates of remoteActionDefinitions.url
|
|
241
|
+
const filtered = remoteActionDefinitions.filter(
|
|
242
|
+
(value, index, self) => index === self.findIndex((t) => t.url === value.url),
|
|
243
|
+
);
|
|
135
244
|
|
|
136
245
|
const result = await Promise.all(
|
|
137
|
-
filtered.map(async (
|
|
138
|
-
// Check for properties that can distinguish LG cloud from other actions
|
|
139
|
-
if (endpoint.type === EndpointType.LangGraphCloud) {
|
|
140
|
-
return constructLGCRemoteAction({
|
|
141
|
-
endpoint,
|
|
142
|
-
messages,
|
|
143
|
-
graphqlContext,
|
|
144
|
-
logger: logger.child({
|
|
145
|
-
component: "remote-actions.constructLGCRemoteAction",
|
|
146
|
-
endpoint,
|
|
147
|
-
}),
|
|
148
|
-
agentStates,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
246
|
+
filtered.map(async (actionDefinition) => {
|
|
152
247
|
const json = await fetchRemoteInfo({
|
|
153
|
-
url:
|
|
154
|
-
onBeforeRequest:
|
|
248
|
+
url: actionDefinition.url,
|
|
249
|
+
onBeforeRequest: actionDefinition.onBeforeRequest,
|
|
155
250
|
graphqlContext,
|
|
156
|
-
logger: logger.child({ component: "remote-actions.fetchActionsFromUrl",
|
|
251
|
+
logger: logger.child({ component: "remote-actions.fetchActionsFromUrl", actionDefinition }),
|
|
157
252
|
frontendUrl,
|
|
158
253
|
});
|
|
159
|
-
|
|
160
254
|
return constructRemoteActions({
|
|
161
255
|
json,
|
|
162
256
|
messages,
|
|
163
|
-
url:
|
|
164
|
-
onBeforeRequest:
|
|
257
|
+
url: actionDefinition.url,
|
|
258
|
+
onBeforeRequest: actionDefinition.onBeforeRequest,
|
|
165
259
|
graphqlContext,
|
|
166
|
-
logger: logger.child({ component: "remote-actions.constructActions",
|
|
260
|
+
logger: logger.child({ component: "remote-actions.constructActions", actionDefinition }),
|
|
167
261
|
agentStates,
|
|
168
262
|
});
|
|
169
263
|
}),
|
|
@@ -260,7 +260,11 @@ async function executeAction(
|
|
|
260
260
|
// Prepare arguments for function calling
|
|
261
261
|
let args: Record<string, any>[] = [];
|
|
262
262
|
if (actionArguments) {
|
|
263
|
-
|
|
263
|
+
try {
|
|
264
|
+
args = JSON.parse(actionArguments);
|
|
265
|
+
} catch (e) {
|
|
266
|
+
console.warn("Action argument unparsable", { actionArguments });
|
|
267
|
+
}
|
|
264
268
|
}
|
|
265
269
|
|
|
266
270
|
// handle LangGraph agents
|