@copilotkit/runtime 0.0.0-test-custom-tag-prerelease-1-20250108200215
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/.eslintrc.js +7 -0
- package/CHANGELOG.md +729 -0
- package/README.md +46 -0
- package/__snapshots__/schema/schema.graphql +262 -0
- package/dist/chunk-2WXVJKUZ.mjs +25 -0
- package/dist/chunk-2WXVJKUZ.mjs.map +1 -0
- package/dist/chunk-44O2JGUY.mjs +12 -0
- package/dist/chunk-44O2JGUY.mjs.map +1 -0
- package/dist/chunk-CLGKEUOA.mjs +1408 -0
- package/dist/chunk-CLGKEUOA.mjs.map +1 -0
- package/dist/chunk-D2WLFQS6.mjs +43 -0
- package/dist/chunk-D2WLFQS6.mjs.map +1 -0
- package/dist/chunk-DFOKBSIS.mjs +1 -0
- package/dist/chunk-DFOKBSIS.mjs.map +1 -0
- package/dist/chunk-RFF5IIZJ.mjs +66 -0
- package/dist/chunk-RFF5IIZJ.mjs.map +1 -0
- package/dist/chunk-U3V2BCGI.mjs +152 -0
- package/dist/chunk-U3V2BCGI.mjs.map +1 -0
- package/dist/chunk-UYX3NHOI.mjs +25 -0
- package/dist/chunk-UYX3NHOI.mjs.map +1 -0
- package/dist/chunk-W3GSZTZR.mjs +3281 -0
- package/dist/chunk-W3GSZTZR.mjs.map +1 -0
- package/dist/chunk-WPNQ4AMN.mjs +80 -0
- package/dist/chunk-WPNQ4AMN.mjs.map +1 -0
- package/dist/copilot-runtime-6285d897.d.ts +189 -0
- package/dist/graphql/types/base/index.d.ts +6 -0
- package/dist/graphql/types/base/index.js +63 -0
- package/dist/graphql/types/base/index.js.map +1 -0
- package/dist/graphql/types/base/index.mjs +8 -0
- package/dist/graphql/types/base/index.mjs.map +1 -0
- package/dist/graphql/types/converted/index.d.ts +2 -0
- package/dist/graphql/types/converted/index.js +124 -0
- package/dist/graphql/types/converted/index.js.map +1 -0
- package/dist/graphql/types/converted/index.mjs +17 -0
- package/dist/graphql/types/converted/index.mjs.map +1 -0
- package/dist/groq-adapter-15d41154.d.ts +281 -0
- package/dist/index-ff3fbc33.d.ts +87 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +5039 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +76 -0
- package/dist/index.mjs.map +1 -0
- package/dist/langserve-48e976ac.d.ts +176 -0
- package/dist/lib/cloud/index.d.ts +6 -0
- package/dist/lib/cloud/index.js +18 -0
- package/dist/lib/cloud/index.js.map +1 -0
- package/dist/lib/cloud/index.mjs +1 -0
- package/dist/lib/cloud/index.mjs.map +1 -0
- package/dist/lib/index.d.ts +20 -0
- package/dist/lib/index.js +4687 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/index.mjs +58 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/integrations/index.d.ts +33 -0
- package/dist/lib/integrations/index.js +2091 -0
- package/dist/lib/integrations/index.js.map +1 -0
- package/dist/lib/integrations/index.mjs +34 -0
- package/dist/lib/integrations/index.mjs.map +1 -0
- package/dist/lib/integrations/nest/index.d.ts +14 -0
- package/dist/lib/integrations/nest/index.js +2000 -0
- package/dist/lib/integrations/nest/index.js.map +1 -0
- package/dist/lib/integrations/nest/index.mjs +13 -0
- package/dist/lib/integrations/nest/index.mjs.map +1 -0
- package/dist/lib/integrations/node-express/index.d.ts +14 -0
- package/dist/lib/integrations/node-express/index.js +2000 -0
- package/dist/lib/integrations/node-express/index.js.map +1 -0
- package/dist/lib/integrations/node-express/index.mjs +13 -0
- package/dist/lib/integrations/node-express/index.mjs.map +1 -0
- package/dist/lib/integrations/node-http/index.d.ts +14 -0
- package/dist/lib/integrations/node-http/index.js +1986 -0
- package/dist/lib/integrations/node-http/index.js.map +1 -0
- package/dist/lib/integrations/node-http/index.mjs +12 -0
- package/dist/lib/integrations/node-http/index.mjs.map +1 -0
- package/dist/service-adapters/index.d.ts +84 -0
- package/dist/service-adapters/index.js +1448 -0
- package/dist/service-adapters/index.js.map +1 -0
- package/dist/service-adapters/index.mjs +26 -0
- package/dist/service-adapters/index.mjs.map +1 -0
- package/dist/utils/index.d.ts +49 -0
- package/dist/utils/index.js +174 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +12 -0
- package/dist/utils/index.mjs.map +1 -0
- package/jest.config.js +5 -0
- package/package.json +85 -0
- package/scripts/generate-gql-schema.ts +13 -0
- package/src/agents/langgraph/event-source.ts +287 -0
- package/src/agents/langgraph/events.ts +338 -0
- package/src/graphql/inputs/action.input.ts +16 -0
- package/src/graphql/inputs/agent-session.input.ts +13 -0
- package/src/graphql/inputs/agent-state.input.ts +10 -0
- package/src/graphql/inputs/cloud-guardrails.input.ts +16 -0
- package/src/graphql/inputs/cloud.input.ts +8 -0
- package/src/graphql/inputs/context-property.input.ts +10 -0
- package/src/graphql/inputs/custom-property.input.ts +15 -0
- package/src/graphql/inputs/forwarded-parameters.input.ts +22 -0
- package/src/graphql/inputs/frontend.input.ts +14 -0
- package/src/graphql/inputs/generate-copilot-response.input.ts +47 -0
- package/src/graphql/inputs/message.input.ts +92 -0
- package/src/graphql/resolvers/copilot.resolver.ts +540 -0
- package/src/graphql/types/base/index.ts +10 -0
- package/src/graphql/types/converted/index.ts +70 -0
- package/src/graphql/types/copilot-response.type.ts +113 -0
- package/src/graphql/types/enums.ts +37 -0
- package/src/graphql/types/guardrails-result.type.ts +20 -0
- package/src/graphql/types/message-status.type.ts +40 -0
- package/src/graphql/types/response-status.type.ts +66 -0
- package/src/index.ts +4 -0
- package/src/lib/cloud/index.ts +4 -0
- package/src/lib/index.ts +8 -0
- package/src/lib/integrations/index.ts +6 -0
- package/src/lib/integrations/nest/index.ts +17 -0
- package/src/lib/integrations/nextjs/app-router.ts +40 -0
- package/src/lib/integrations/nextjs/pages-router.ts +49 -0
- package/src/lib/integrations/node-express/index.ts +17 -0
- package/src/lib/integrations/node-http/index.ts +34 -0
- package/src/lib/integrations/shared.ts +109 -0
- package/src/lib/logger.ts +28 -0
- package/src/lib/runtime/copilot-runtime.ts +412 -0
- package/src/lib/runtime/remote-action-constructors.ts +304 -0
- package/src/lib/runtime/remote-actions.ts +174 -0
- package/src/lib/runtime/remote-lg-action.ts +657 -0
- package/src/lib/telemetry-client.ts +52 -0
- package/src/service-adapters/anthropic/anthropic-adapter.ts +205 -0
- package/src/service-adapters/anthropic/utils.ts +144 -0
- package/src/service-adapters/conversion.ts +64 -0
- package/src/service-adapters/events.ts +377 -0
- package/src/service-adapters/experimental/empty/empty-adapter.ts +33 -0
- package/src/service-adapters/experimental/ollama/ollama-adapter.ts +79 -0
- package/src/service-adapters/google/google-genai-adapter.ts +39 -0
- package/src/service-adapters/groq/groq-adapter.ts +173 -0
- package/src/service-adapters/index.ts +16 -0
- package/src/service-adapters/langchain/langchain-adapter.ts +99 -0
- package/src/service-adapters/langchain/langserve.ts +87 -0
- package/src/service-adapters/langchain/types.ts +14 -0
- package/src/service-adapters/langchain/utils.ts +306 -0
- package/src/service-adapters/openai/openai-adapter.ts +210 -0
- package/src/service-adapters/openai/openai-assistant-adapter.ts +304 -0
- package/src/service-adapters/openai/utils.ts +161 -0
- package/src/service-adapters/service-adapter.ts +30 -0
- package/src/service-adapters/unify/unify-adapter.ts +145 -0
- package/src/utils/failed-response-status-reasons.ts +48 -0
- package/src/utils/index.ts +1 -0
- package/tsconfig.json +11 -0
- package/tsup.config.ts +16 -0
- package/typedoc.json +4 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <Callout type="info">
|
|
3
|
+
* This is the reference for the `CopilotRuntime` class. For more information and example code snippets, please see [Concept: Copilot Runtime](/concepts/copilot-runtime).
|
|
4
|
+
* </Callout>
|
|
5
|
+
*
|
|
6
|
+
* ## Usage
|
|
7
|
+
*
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { CopilotRuntime } from "@copilotkit/runtime";
|
|
10
|
+
*
|
|
11
|
+
* const copilotKit = new CopilotRuntime();
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Action, actionParametersToJsonSchema, Parameter, randomId } from "@copilotkit/shared";
|
|
16
|
+
import { CopilotServiceAdapter, RemoteChain, RemoteChainParameters } from "../../service-adapters";
|
|
17
|
+
import { MessageInput } from "../../graphql/inputs/message.input";
|
|
18
|
+
import { ActionInput } from "../../graphql/inputs/action.input";
|
|
19
|
+
import { RuntimeEventSource } from "../../service-adapters/events";
|
|
20
|
+
import { convertGqlInputToMessages } from "../../service-adapters/conversion";
|
|
21
|
+
import { Message } from "../../graphql/types/converted";
|
|
22
|
+
import { ForwardedParametersInput } from "../../graphql/inputs/forwarded-parameters.input";
|
|
23
|
+
import {
|
|
24
|
+
isLangGraphAgentAction,
|
|
25
|
+
LangGraphAgentAction,
|
|
26
|
+
EndpointType,
|
|
27
|
+
setupRemoteActions,
|
|
28
|
+
EndpointDefinition,
|
|
29
|
+
CopilotKitEndpoint,
|
|
30
|
+
LangGraphPlatformEndpoint,
|
|
31
|
+
} from "./remote-actions";
|
|
32
|
+
import { GraphQLContext } from "../integrations/shared";
|
|
33
|
+
import { AgentSessionInput } from "../../graphql/inputs/agent-session.input";
|
|
34
|
+
import { from } from "rxjs";
|
|
35
|
+
import { AgentStateInput } from "../../graphql/inputs/agent-state.input";
|
|
36
|
+
import { ActionInputAvailability } from "../../graphql/types/enums";
|
|
37
|
+
|
|
38
|
+
interface CopilotRuntimeRequest {
|
|
39
|
+
serviceAdapter: CopilotServiceAdapter;
|
|
40
|
+
messages: MessageInput[];
|
|
41
|
+
actions: ActionInput[];
|
|
42
|
+
agentSession?: AgentSessionInput;
|
|
43
|
+
agentStates?: AgentStateInput[];
|
|
44
|
+
outputMessagesPromise: Promise<Message[]>;
|
|
45
|
+
threadId?: string;
|
|
46
|
+
runId?: string;
|
|
47
|
+
publicApiKey?: string;
|
|
48
|
+
graphqlContext: GraphQLContext;
|
|
49
|
+
forwardedParameters?: ForwardedParametersInput;
|
|
50
|
+
url?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface CopilotRuntimeResponse {
|
|
54
|
+
threadId: string;
|
|
55
|
+
runId?: string;
|
|
56
|
+
eventSource: RuntimeEventSource;
|
|
57
|
+
serverSideActions: Action<any>[];
|
|
58
|
+
actionInputsWithoutAgents: ActionInput[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
type ActionsConfiguration<T extends Parameter[] | [] = []> =
|
|
62
|
+
| Action<T>[]
|
|
63
|
+
| ((ctx: { properties: any; url?: string }) => Action<T>[]);
|
|
64
|
+
|
|
65
|
+
interface OnBeforeRequestOptions {
|
|
66
|
+
threadId?: string;
|
|
67
|
+
runId?: string;
|
|
68
|
+
inputMessages: Message[];
|
|
69
|
+
properties: any;
|
|
70
|
+
url?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
type OnBeforeRequestHandler = (options: OnBeforeRequestOptions) => void | Promise<void>;
|
|
74
|
+
|
|
75
|
+
interface OnAfterRequestOptions {
|
|
76
|
+
threadId: string;
|
|
77
|
+
runId?: string;
|
|
78
|
+
inputMessages: Message[];
|
|
79
|
+
outputMessages: Message[];
|
|
80
|
+
properties: any;
|
|
81
|
+
url?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
type OnAfterRequestHandler = (options: OnAfterRequestOptions) => void | Promise<void>;
|
|
85
|
+
|
|
86
|
+
interface Middleware {
|
|
87
|
+
/**
|
|
88
|
+
* A function that is called before the request is processed.
|
|
89
|
+
*/
|
|
90
|
+
onBeforeRequest?: OnBeforeRequestHandler;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A function that is called after the request is processed.
|
|
94
|
+
*/
|
|
95
|
+
onAfterRequest?: OnAfterRequestHandler;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []> {
|
|
99
|
+
/**
|
|
100
|
+
* Middleware to be used by the runtime.
|
|
101
|
+
*
|
|
102
|
+
* ```ts
|
|
103
|
+
* onBeforeRequest: (options: {
|
|
104
|
+
* threadId?: string;
|
|
105
|
+
* runId?: string;
|
|
106
|
+
* inputMessages: Message[];
|
|
107
|
+
* properties: any;
|
|
108
|
+
* }) => void | Promise<void>;
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* ```ts
|
|
112
|
+
* onAfterRequest: (options: {
|
|
113
|
+
* threadId?: string;
|
|
114
|
+
* runId?: string;
|
|
115
|
+
* inputMessages: Message[];
|
|
116
|
+
* outputMessages: Message[];
|
|
117
|
+
* properties: any;
|
|
118
|
+
* }) => void | Promise<void>;
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
middleware?: Middleware;
|
|
122
|
+
|
|
123
|
+
/*
|
|
124
|
+
* A list of server side actions that can be executed.
|
|
125
|
+
*/
|
|
126
|
+
actions?: ActionsConfiguration<T>;
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
* Deprecated: Use `remoteEndpoints`.
|
|
130
|
+
*/
|
|
131
|
+
remoteActions?: CopilotKitEndpoint[];
|
|
132
|
+
|
|
133
|
+
/*
|
|
134
|
+
* A list of remote actions that can be executed.
|
|
135
|
+
*/
|
|
136
|
+
remoteEndpoints?: EndpointDefinition[];
|
|
137
|
+
|
|
138
|
+
/*
|
|
139
|
+
* An array of LangServer URLs.
|
|
140
|
+
*/
|
|
141
|
+
langserve?: RemoteChainParameters[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
145
|
+
public actions: ActionsConfiguration<T>;
|
|
146
|
+
public remoteEndpointDefinitions: EndpointDefinition[];
|
|
147
|
+
private langserve: Promise<Action<any>>[] = [];
|
|
148
|
+
private onBeforeRequest?: OnBeforeRequestHandler;
|
|
149
|
+
private onAfterRequest?: OnAfterRequestHandler;
|
|
150
|
+
|
|
151
|
+
constructor(params?: CopilotRuntimeConstructorParams<T>) {
|
|
152
|
+
this.actions = params?.actions || [];
|
|
153
|
+
|
|
154
|
+
for (const chain of params?.langserve || []) {
|
|
155
|
+
const remoteChain = new RemoteChain(chain);
|
|
156
|
+
this.langserve.push(remoteChain.toAction());
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.remoteEndpointDefinitions = params?.remoteEndpoints ?? params?.remoteActions ?? [];
|
|
160
|
+
|
|
161
|
+
this.onBeforeRequest = params?.middleware?.onBeforeRequest;
|
|
162
|
+
this.onAfterRequest = params?.middleware?.onAfterRequest;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async processRuntimeRequest(request: CopilotRuntimeRequest): Promise<CopilotRuntimeResponse> {
|
|
166
|
+
const {
|
|
167
|
+
serviceAdapter,
|
|
168
|
+
messages: rawMessages,
|
|
169
|
+
actions: clientSideActionsInput,
|
|
170
|
+
threadId,
|
|
171
|
+
runId,
|
|
172
|
+
outputMessagesPromise,
|
|
173
|
+
graphqlContext,
|
|
174
|
+
forwardedParameters,
|
|
175
|
+
agentSession,
|
|
176
|
+
url,
|
|
177
|
+
} = request;
|
|
178
|
+
|
|
179
|
+
const eventSource = new RuntimeEventSource();
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
if (agentSession) {
|
|
183
|
+
return await this.processAgentRequest(request);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const messages = rawMessages.filter((message) => !message.agentStateMessage);
|
|
187
|
+
|
|
188
|
+
const inputMessages = convertGqlInputToMessages(messages);
|
|
189
|
+
const serverSideActions = await this.getServerSideActions(request);
|
|
190
|
+
|
|
191
|
+
const serverSideActionsInput: ActionInput[] = serverSideActions.map((action) => ({
|
|
192
|
+
name: action.name,
|
|
193
|
+
description: action.description,
|
|
194
|
+
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters)),
|
|
195
|
+
}));
|
|
196
|
+
|
|
197
|
+
const actionInputs = flattenToolCallsNoDuplicates([
|
|
198
|
+
...serverSideActionsInput,
|
|
199
|
+
...clientSideActionsInput.filter(
|
|
200
|
+
// Filter remote actions from CopilotKit core loop
|
|
201
|
+
(action) => action.available !== ActionInputAvailability.remote,
|
|
202
|
+
),
|
|
203
|
+
]);
|
|
204
|
+
|
|
205
|
+
await this.onBeforeRequest?.({
|
|
206
|
+
threadId,
|
|
207
|
+
runId,
|
|
208
|
+
inputMessages,
|
|
209
|
+
properties: graphqlContext.properties,
|
|
210
|
+
url,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const result = await serviceAdapter.process({
|
|
214
|
+
messages: inputMessages,
|
|
215
|
+
actions: actionInputs,
|
|
216
|
+
threadId,
|
|
217
|
+
runId,
|
|
218
|
+
eventSource,
|
|
219
|
+
forwardedParameters,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
outputMessagesPromise
|
|
223
|
+
.then((outputMessages) => {
|
|
224
|
+
this.onAfterRequest?.({
|
|
225
|
+
threadId: result.threadId,
|
|
226
|
+
runId: result.runId,
|
|
227
|
+
inputMessages,
|
|
228
|
+
outputMessages,
|
|
229
|
+
properties: graphqlContext.properties,
|
|
230
|
+
url,
|
|
231
|
+
});
|
|
232
|
+
})
|
|
233
|
+
.catch((_error) => {});
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
threadId: result.threadId,
|
|
237
|
+
runId: result.runId,
|
|
238
|
+
eventSource,
|
|
239
|
+
serverSideActions,
|
|
240
|
+
actionInputsWithoutAgents: actionInputs.filter(
|
|
241
|
+
(action) =>
|
|
242
|
+
// TODO-AGENTS: do not exclude ALL server side actions
|
|
243
|
+
!serverSideActions.find((serverSideAction) => serverSideAction.name == action.name),
|
|
244
|
+
// !isLangGraphAgentAction(
|
|
245
|
+
// serverSideActions.find((serverSideAction) => serverSideAction.name == action.name),
|
|
246
|
+
// ),
|
|
247
|
+
),
|
|
248
|
+
};
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error("Error getting response:", error);
|
|
251
|
+
eventSource.sendErrorMessageToChat();
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private async processAgentRequest(
|
|
257
|
+
request: CopilotRuntimeRequest,
|
|
258
|
+
): Promise<CopilotRuntimeResponse> {
|
|
259
|
+
const { messages: rawMessages, outputMessagesPromise, graphqlContext, agentSession } = request;
|
|
260
|
+
const { threadId, agentName, nodeName } = agentSession;
|
|
261
|
+
const serverSideActions = await this.getServerSideActions(request);
|
|
262
|
+
|
|
263
|
+
const messages = convertGqlInputToMessages(rawMessages);
|
|
264
|
+
|
|
265
|
+
const agent = serverSideActions.find(
|
|
266
|
+
(action) => action.name === agentName && isLangGraphAgentAction(action),
|
|
267
|
+
) as LangGraphAgentAction;
|
|
268
|
+
|
|
269
|
+
if (!agent) {
|
|
270
|
+
throw new Error(`Agent ${agentName} not found`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const serverSideActionsInput: ActionInput[] = serverSideActions
|
|
274
|
+
.filter((action) => !isLangGraphAgentAction(action))
|
|
275
|
+
.map((action) => ({
|
|
276
|
+
name: action.name,
|
|
277
|
+
description: action.description,
|
|
278
|
+
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters)),
|
|
279
|
+
}));
|
|
280
|
+
|
|
281
|
+
const actionInputsWithoutAgents = flattenToolCallsNoDuplicates([
|
|
282
|
+
...serverSideActionsInput,
|
|
283
|
+
...request.actions,
|
|
284
|
+
]);
|
|
285
|
+
|
|
286
|
+
await this.onBeforeRequest?.({
|
|
287
|
+
threadId,
|
|
288
|
+
runId: undefined,
|
|
289
|
+
inputMessages: messages,
|
|
290
|
+
properties: graphqlContext.properties,
|
|
291
|
+
});
|
|
292
|
+
try {
|
|
293
|
+
const eventSource = new RuntimeEventSource();
|
|
294
|
+
const stream = await agent.langGraphAgentHandler({
|
|
295
|
+
name: agentName,
|
|
296
|
+
threadId,
|
|
297
|
+
nodeName,
|
|
298
|
+
actionInputsWithoutAgents,
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
eventSource.stream(async (eventStream$) => {
|
|
302
|
+
from(stream).subscribe({
|
|
303
|
+
next: (event) => eventStream$.next(event),
|
|
304
|
+
error: (err) => console.error("Error in stream", err),
|
|
305
|
+
complete: () => eventStream$.complete(),
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
outputMessagesPromise
|
|
310
|
+
.then((outputMessages) => {
|
|
311
|
+
this.onAfterRequest?.({
|
|
312
|
+
threadId,
|
|
313
|
+
runId: undefined,
|
|
314
|
+
inputMessages: messages,
|
|
315
|
+
outputMessages,
|
|
316
|
+
properties: graphqlContext.properties,
|
|
317
|
+
});
|
|
318
|
+
})
|
|
319
|
+
.catch((_error) => {});
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
threadId,
|
|
323
|
+
runId: undefined,
|
|
324
|
+
eventSource,
|
|
325
|
+
serverSideActions: [],
|
|
326
|
+
actionInputsWithoutAgents,
|
|
327
|
+
};
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error("Error getting response:", error);
|
|
330
|
+
throw error;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private async getServerSideActions(request: CopilotRuntimeRequest): Promise<Action<any>[]> {
|
|
335
|
+
const { messages: rawMessages, graphqlContext, agentStates, url } = request;
|
|
336
|
+
const inputMessages = convertGqlInputToMessages(rawMessages);
|
|
337
|
+
const langserveFunctions: Action<any>[] = [];
|
|
338
|
+
|
|
339
|
+
for (const chainPromise of this.langserve) {
|
|
340
|
+
try {
|
|
341
|
+
const chain = await chainPromise;
|
|
342
|
+
langserveFunctions.push(chain);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
console.error("Error loading langserve chain:", error);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const remoteEndpointDefinitions = this.remoteEndpointDefinitions.map(
|
|
349
|
+
(endpoint) =>
|
|
350
|
+
({
|
|
351
|
+
...endpoint,
|
|
352
|
+
type: resolveEndpointType(endpoint),
|
|
353
|
+
}) as EndpointDefinition,
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
const remoteActions = await setupRemoteActions({
|
|
357
|
+
remoteEndpointDefinitions,
|
|
358
|
+
graphqlContext,
|
|
359
|
+
messages: inputMessages,
|
|
360
|
+
agentStates,
|
|
361
|
+
frontendUrl: url,
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const configuredActions =
|
|
365
|
+
typeof this.actions === "function"
|
|
366
|
+
? this.actions({ properties: graphqlContext.properties, url })
|
|
367
|
+
: this.actions;
|
|
368
|
+
|
|
369
|
+
return [...configuredActions, ...langserveFunctions, ...remoteActions];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export function flattenToolCallsNoDuplicates(toolsByPriority: ActionInput[]): ActionInput[] {
|
|
374
|
+
let allTools: ActionInput[] = [];
|
|
375
|
+
const allToolNames: string[] = [];
|
|
376
|
+
for (const tool of toolsByPriority) {
|
|
377
|
+
if (!allToolNames.includes(tool.name)) {
|
|
378
|
+
allTools.push(tool);
|
|
379
|
+
allToolNames.push(tool.name);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return allTools;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// The two functions below are "factory functions", meant to create the action objects that adhere to the expected interfaces
|
|
386
|
+
export function copilotKitEndpoint(config: Omit<CopilotKitEndpoint, "type">): CopilotKitEndpoint {
|
|
387
|
+
return {
|
|
388
|
+
...config,
|
|
389
|
+
type: EndpointType.CopilotKit,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export function langGraphPlatformEndpoint(
|
|
394
|
+
config: Omit<LangGraphPlatformEndpoint, "type">,
|
|
395
|
+
): LangGraphPlatformEndpoint {
|
|
396
|
+
return {
|
|
397
|
+
...config,
|
|
398
|
+
type: EndpointType.LangGraphPlatform,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export function resolveEndpointType(endpoint: EndpointDefinition) {
|
|
403
|
+
if (!endpoint.type) {
|
|
404
|
+
if ("langsmithApiKey" in endpoint && "deploymentUrl" in endpoint && "agents" in endpoint) {
|
|
405
|
+
return EndpointType.LangGraphPlatform;
|
|
406
|
+
} else {
|
|
407
|
+
return EndpointType.CopilotKit;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return endpoint.type;
|
|
412
|
+
}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import {
|
|
3
|
+
CopilotKitEndpoint,
|
|
4
|
+
LangGraphAgentHandlerParams,
|
|
5
|
+
RemoteActionInfoResponse,
|
|
6
|
+
LangGraphPlatformEndpoint,
|
|
7
|
+
} from "./remote-actions";
|
|
8
|
+
import { GraphQLContext } from "../integrations";
|
|
9
|
+
import { Logger } from "pino";
|
|
10
|
+
import { Message } from "../../graphql/types/converted";
|
|
11
|
+
import { AgentStateInput } from "../../graphql/inputs/agent-state.input";
|
|
12
|
+
import { Observable, ReplaySubject } from "rxjs";
|
|
13
|
+
import { RuntimeEvent } from "../../service-adapters/events";
|
|
14
|
+
import telemetry from "../telemetry-client";
|
|
15
|
+
import { RemoteLangGraphEventSource } from "../../agents/langgraph/event-source";
|
|
16
|
+
import { Action } from "@copilotkit/shared";
|
|
17
|
+
import { LangGraphEvent } from "../../agents/langgraph/events";
|
|
18
|
+
import { execute } from "./remote-lg-action";
|
|
19
|
+
|
|
20
|
+
export function constructLGCRemoteAction({
|
|
21
|
+
endpoint,
|
|
22
|
+
graphqlContext,
|
|
23
|
+
logger,
|
|
24
|
+
messages,
|
|
25
|
+
agentStates,
|
|
26
|
+
}: {
|
|
27
|
+
endpoint: LangGraphPlatformEndpoint;
|
|
28
|
+
graphqlContext: GraphQLContext;
|
|
29
|
+
logger: Logger;
|
|
30
|
+
messages: Message[];
|
|
31
|
+
agentStates?: AgentStateInput[];
|
|
32
|
+
}) {
|
|
33
|
+
const agents = endpoint.agents.map((agent) => ({
|
|
34
|
+
name: agent.name,
|
|
35
|
+
description: agent.description,
|
|
36
|
+
parameters: [],
|
|
37
|
+
handler: async (_args: any) => {},
|
|
38
|
+
langGraphAgentHandler: async ({
|
|
39
|
+
name,
|
|
40
|
+
actionInputsWithoutAgents,
|
|
41
|
+
threadId,
|
|
42
|
+
nodeName,
|
|
43
|
+
additionalMessages = [],
|
|
44
|
+
}: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
|
|
45
|
+
logger.debug({ actionName: agent.name }, "Executing LangGraph Platform agent");
|
|
46
|
+
|
|
47
|
+
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
48
|
+
agentExecution: true,
|
|
49
|
+
type: "langgraph-platform",
|
|
50
|
+
agentsAmount: endpoint.agents.length,
|
|
51
|
+
hashedLgcKey: createHash("sha256").update(endpoint.langsmithApiKey).digest("hex"),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
let state = {};
|
|
55
|
+
if (agentStates) {
|
|
56
|
+
const jsonState = agentStates.find((state) => state.agentName === name)?.state;
|
|
57
|
+
if (jsonState) {
|
|
58
|
+
state = JSON.parse(jsonState);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const response = await execute({
|
|
64
|
+
logger,
|
|
65
|
+
deploymentUrl: endpoint.deploymentUrl,
|
|
66
|
+
langsmithApiKey: endpoint.langsmithApiKey,
|
|
67
|
+
agent,
|
|
68
|
+
threadId,
|
|
69
|
+
nodeName,
|
|
70
|
+
messages: [...messages, ...additionalMessages],
|
|
71
|
+
state,
|
|
72
|
+
properties: graphqlContext.properties,
|
|
73
|
+
actions: actionInputsWithoutAgents.map((action) => ({
|
|
74
|
+
name: action.name,
|
|
75
|
+
description: action.description,
|
|
76
|
+
parameters: JSON.parse(action.jsonSchema) as string,
|
|
77
|
+
})),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const eventSource = new RemoteLangGraphEventSource();
|
|
81
|
+
streamResponse(response, eventSource.eventStream$);
|
|
82
|
+
return eventSource.processLangGraphEvents();
|
|
83
|
+
} catch (error) {
|
|
84
|
+
logger.error(
|
|
85
|
+
{ url: endpoint.deploymentUrl, status: 500, body: error.message },
|
|
86
|
+
"Failed to execute LangGraph Platform agent",
|
|
87
|
+
);
|
|
88
|
+
throw new Error("Failed to execute LangGraph Platform agent");
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
return [...agents];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function constructRemoteActions({
|
|
97
|
+
json,
|
|
98
|
+
url,
|
|
99
|
+
onBeforeRequest,
|
|
100
|
+
graphqlContext,
|
|
101
|
+
logger,
|
|
102
|
+
messages,
|
|
103
|
+
agentStates,
|
|
104
|
+
}: {
|
|
105
|
+
json: RemoteActionInfoResponse;
|
|
106
|
+
url: string;
|
|
107
|
+
onBeforeRequest?: CopilotKitEndpoint["onBeforeRequest"];
|
|
108
|
+
graphqlContext: GraphQLContext;
|
|
109
|
+
logger: Logger;
|
|
110
|
+
messages: Message[];
|
|
111
|
+
agentStates?: AgentStateInput[];
|
|
112
|
+
}): Action<any>[] {
|
|
113
|
+
const totalAgents = Array.isArray(json["agents"]) ? json["agents"].length : 0;
|
|
114
|
+
|
|
115
|
+
const actions = json["actions"].map((action) => ({
|
|
116
|
+
name: action.name,
|
|
117
|
+
description: action.description,
|
|
118
|
+
parameters: action.parameters,
|
|
119
|
+
handler: async (args: any) => {
|
|
120
|
+
logger.debug({ actionName: action.name, args }, "Executing remote action");
|
|
121
|
+
|
|
122
|
+
const headers = createHeaders(onBeforeRequest, graphqlContext);
|
|
123
|
+
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
124
|
+
agentExecution: false,
|
|
125
|
+
type: "self-hosted",
|
|
126
|
+
agentsAmount: totalAgents,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
const response = await fetch(`${url}/actions/execute`, {
|
|
131
|
+
method: "POST",
|
|
132
|
+
headers,
|
|
133
|
+
body: JSON.stringify({
|
|
134
|
+
name: action.name,
|
|
135
|
+
arguments: args,
|
|
136
|
+
properties: graphqlContext.properties,
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (!response.ok) {
|
|
141
|
+
logger.error(
|
|
142
|
+
{ url, status: response.status, body: await response.text() },
|
|
143
|
+
"Failed to execute remote action",
|
|
144
|
+
);
|
|
145
|
+
return "Failed to execute remote action";
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const requestResult = await response.json();
|
|
149
|
+
|
|
150
|
+
const result = requestResult["result"];
|
|
151
|
+
logger.debug({ actionName: action.name, result }, "Executed remote action");
|
|
152
|
+
return result;
|
|
153
|
+
} catch (error) {
|
|
154
|
+
logger.error(
|
|
155
|
+
{ error: error.message ? error.message : error + "" },
|
|
156
|
+
"Failed to execute remote action",
|
|
157
|
+
);
|
|
158
|
+
return "Failed to execute remote action";
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
}));
|
|
162
|
+
|
|
163
|
+
const agents = totalAgents
|
|
164
|
+
? 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
|
+
additionalMessages = [],
|
|
176
|
+
}: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
|
|
177
|
+
logger.debug({ actionName: agent.name }, "Executing remote agent");
|
|
178
|
+
|
|
179
|
+
const headers = createHeaders(onBeforeRequest, graphqlContext);
|
|
180
|
+
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
181
|
+
agentExecution: true,
|
|
182
|
+
type: "self-hosted",
|
|
183
|
+
agentsAmount: json["agents"].length,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
let state = {};
|
|
187
|
+
if (agentStates) {
|
|
188
|
+
const jsonState = agentStates.find((state) => state.agentName === name)?.state;
|
|
189
|
+
if (jsonState) {
|
|
190
|
+
state = JSON.parse(jsonState);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const response = await fetch(`${url}/agents/execute`, {
|
|
195
|
+
method: "POST",
|
|
196
|
+
headers,
|
|
197
|
+
body: JSON.stringify({
|
|
198
|
+
name,
|
|
199
|
+
threadId,
|
|
200
|
+
nodeName,
|
|
201
|
+
messages: [...messages, ...additionalMessages],
|
|
202
|
+
state,
|
|
203
|
+
properties: graphqlContext.properties,
|
|
204
|
+
actions: actionInputsWithoutAgents.map((action) => ({
|
|
205
|
+
name: action.name,
|
|
206
|
+
description: action.description,
|
|
207
|
+
parameters: JSON.parse(action.jsonSchema),
|
|
208
|
+
})),
|
|
209
|
+
}),
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
if (!response.ok) {
|
|
213
|
+
logger.error(
|
|
214
|
+
{ url, status: response.status, body: await response.text() },
|
|
215
|
+
"Failed to execute remote agent",
|
|
216
|
+
);
|
|
217
|
+
throw new Error("Failed to execute remote agent");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const eventSource = new RemoteLangGraphEventSource();
|
|
221
|
+
streamResponse(response.body!, eventSource.eventStream$);
|
|
222
|
+
return eventSource.processLangGraphEvents();
|
|
223
|
+
},
|
|
224
|
+
}))
|
|
225
|
+
: [];
|
|
226
|
+
|
|
227
|
+
return [...actions, ...agents];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async function streamResponse(
|
|
231
|
+
response: ReadableStream<Uint8Array>,
|
|
232
|
+
eventStream$: ReplaySubject<LangGraphEvent>,
|
|
233
|
+
) {
|
|
234
|
+
const reader = response.getReader();
|
|
235
|
+
const decoder = new TextDecoder();
|
|
236
|
+
let buffer = [];
|
|
237
|
+
|
|
238
|
+
function flushBuffer() {
|
|
239
|
+
const currentBuffer = buffer.join("");
|
|
240
|
+
if (currentBuffer.trim().length === 0) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const parts = currentBuffer.split("\n");
|
|
244
|
+
if (parts.length === 0) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const lastPartIsComplete = currentBuffer.endsWith("\n");
|
|
249
|
+
|
|
250
|
+
// truncate buffer
|
|
251
|
+
buffer = [];
|
|
252
|
+
|
|
253
|
+
if (!lastPartIsComplete) {
|
|
254
|
+
// put back the last part
|
|
255
|
+
buffer.push(parts.pop());
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
parts
|
|
259
|
+
.map((part) => part.trim())
|
|
260
|
+
.filter((part) => part != "")
|
|
261
|
+
.forEach((part) => {
|
|
262
|
+
eventStream$.next(JSON.parse(part));
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
try {
|
|
267
|
+
while (true) {
|
|
268
|
+
const { done, value } = await reader.read();
|
|
269
|
+
|
|
270
|
+
if (!done) {
|
|
271
|
+
buffer.push(decoder.decode(value, { stream: true }));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
flushBuffer();
|
|
275
|
+
|
|
276
|
+
if (done) {
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} catch (error) {
|
|
281
|
+
console.error("Error in stream", error);
|
|
282
|
+
eventStream$.error(error);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
eventStream$.complete();
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function createHeaders(
|
|
289
|
+
onBeforeRequest: CopilotKitEndpoint["onBeforeRequest"],
|
|
290
|
+
graphqlContext: GraphQLContext,
|
|
291
|
+
) {
|
|
292
|
+
const headers = {
|
|
293
|
+
"Content-Type": "application/json",
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
if (onBeforeRequest) {
|
|
297
|
+
const { headers: additionalHeaders } = onBeforeRequest({ ctx: graphqlContext });
|
|
298
|
+
if (additionalHeaders) {
|
|
299
|
+
Object.assign(headers, additionalHeaders);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return headers;
|
|
304
|
+
}
|