@copilotkit/runtime 1.5.15-next.2 → 1.5.15-next.4
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 +17 -0
- package/__snapshots__/schema/schema.graphql +26 -0
- package/dist/{chunk-C2HNOETE.mjs → chunk-6Z3DFNOC.mjs} +2 -2
- package/dist/{chunk-OTB2F27M.mjs → chunk-EC2ZHPRU.mjs} +2 -2
- package/dist/{chunk-I33ESKDS.mjs → chunk-QDK4OP2Y.mjs} +2 -2
- package/dist/{chunk-4KT3HMC3.mjs → chunk-W4G47FRC.mjs} +539 -303
- package/dist/chunk-W4G47FRC.mjs.map +1 -0
- package/dist/{copilot-runtime-e6c34790.d.ts → copilot-runtime-a113045f.d.ts} +13 -1
- package/dist/{groq-adapter-acb6ed0b.d.ts → groq-adapter-248058e8.d.ts} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +808 -574
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/{langserve-9614171f.d.ts → langserve-9580bd66.d.ts} +16 -2
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.js +808 -574
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +4 -4
- package/dist/lib/integrations/index.d.ts +3 -3
- package/dist/lib/integrations/index.js +500 -319
- package/dist/lib/integrations/index.js.map +1 -1
- package/dist/lib/integrations/index.mjs +4 -4
- package/dist/lib/integrations/nest/index.d.ts +2 -2
- package/dist/lib/integrations/nest/index.js +500 -319
- package/dist/lib/integrations/nest/index.js.map +1 -1
- package/dist/lib/integrations/nest/index.mjs +2 -2
- package/dist/lib/integrations/node-express/index.d.ts +2 -2
- package/dist/lib/integrations/node-express/index.js +500 -319
- package/dist/lib/integrations/node-express/index.js.map +1 -1
- package/dist/lib/integrations/node-express/index.mjs +2 -2
- package/dist/lib/integrations/node-http/index.d.ts +2 -2
- package/dist/lib/integrations/node-http/index.js +500 -319
- package/dist/lib/integrations/node-http/index.js.map +1 -1
- package/dist/lib/integrations/node-http/index.mjs +1 -1
- package/dist/service-adapters/index.d.ts +3 -3
- package/package.json +3 -3
- package/src/agents/langgraph/event-source.ts +14 -2
- package/src/agents/langgraph/events.ts +12 -1
- package/src/graphql/inputs/generate-copilot-response.input.ts +4 -0
- package/src/graphql/inputs/meta-event.input.ts +17 -0
- package/src/graphql/resolvers/copilot.resolver.ts +67 -22
- package/src/graphql/types/copilot-response.type.ts +6 -0
- package/src/graphql/types/meta-events.type.ts +31 -0
- package/src/lib/runtime/copilot-runtime.ts +14 -0
- package/src/lib/runtime/remote-action-constructors.ts +5 -1
- package/src/lib/runtime/remote-actions.ts +2 -0
- package/src/lib/runtime/remote-lg-action.ts +46 -10
- package/src/service-adapters/events.ts +20 -1
- package/dist/chunk-4KT3HMC3.mjs.map +0 -1
- /package/dist/{chunk-C2HNOETE.mjs.map → chunk-6Z3DFNOC.mjs.map} +0 -0
- /package/dist/{chunk-OTB2F27M.mjs.map → chunk-EC2ZHPRU.mjs.map} +0 -0
- /package/dist/{chunk-I33ESKDS.mjs.map → chunk-QDK4OP2Y.mjs.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { b as CopilotServiceAdapter, C as CopilotRuntimeChatCompletionRequest, a as CopilotRuntimeChatCompletionResponse } from '../langserve-
|
|
2
|
-
export { c as RemoteChain, R as RemoteChainParameters } from '../langserve-
|
|
3
|
-
export { G as GoogleGenerativeAIAdapter, f as GroqAdapter, e as GroqAdapterParams, L as LangChainAdapter, a as OpenAIAdapter, O as OpenAIAdapterParams, c as OpenAIAssistantAdapter, b as OpenAIAssistantAdapterParams, d as UnifyAdapter, U as UnifyAdapterParams } from '../groq-adapter-
|
|
1
|
+
import { b as CopilotServiceAdapter, C as CopilotRuntimeChatCompletionRequest, a as CopilotRuntimeChatCompletionResponse } from '../langserve-9580bd66.js';
|
|
2
|
+
export { c as RemoteChain, R as RemoteChainParameters } from '../langserve-9580bd66.js';
|
|
3
|
+
export { G as GoogleGenerativeAIAdapter, f as GroqAdapter, e as GroqAdapterParams, L as LangChainAdapter, a as OpenAIAdapter, O as OpenAIAdapterParams, c as OpenAIAssistantAdapter, b as OpenAIAssistantAdapterParams, d as UnifyAdapter, U as UnifyAdapterParams } from '../groq-adapter-248058e8.js';
|
|
4
4
|
import Anthropic from '@anthropic-ai/sdk';
|
|
5
5
|
import '../index-a7f37670.js';
|
|
6
6
|
import '../graphql/types/base/index.js';
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public"
|
|
11
11
|
},
|
|
12
|
-
"version": "1.5.15-next.
|
|
12
|
+
"version": "1.5.15-next.4",
|
|
13
13
|
"sideEffects": false,
|
|
14
14
|
"main": "./dist/index.js",
|
|
15
15
|
"module": "./dist/index.mjs",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@langchain/community": "^0.0.53",
|
|
42
42
|
"@langchain/core": "^0.3.13",
|
|
43
43
|
"@langchain/google-gauth": "^0.1.0",
|
|
44
|
-
"@langchain/langgraph-sdk": "^0.0.
|
|
44
|
+
"@langchain/langgraph-sdk": "^0.0.36",
|
|
45
45
|
"@langchain/openai": "^0.0.28",
|
|
46
46
|
"class-transformer": "^0.5.1",
|
|
47
47
|
"express": "^4.19.2",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"rxjs": "^7.8.1",
|
|
59
59
|
"type-graphql": "2.0.0-rc.1",
|
|
60
60
|
"zod": "^3.23.3",
|
|
61
|
-
"@copilotkit/shared": "1.5.15-next.
|
|
61
|
+
"@copilotkit/shared": "1.5.15-next.4"
|
|
62
62
|
},
|
|
63
63
|
"keywords": [
|
|
64
64
|
"copilotkit",
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { catchError, mergeMap, ReplaySubject, scan } from "rxjs";
|
|
2
2
|
import { CustomEventNames, LangGraphEvent, LangGraphEventTypes } from "./events";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
RuntimeEvent,
|
|
5
|
+
RuntimeEventTypes,
|
|
6
|
+
RuntimeMetaEventName,
|
|
7
|
+
} from "../../service-adapters/events";
|
|
4
8
|
import { randomId } from "@copilotkit/shared";
|
|
5
9
|
|
|
6
10
|
interface LangGraphEventWithState {
|
|
@@ -125,6 +129,14 @@ export class RemoteLangGraphEventSource {
|
|
|
125
129
|
}
|
|
126
130
|
}
|
|
127
131
|
|
|
132
|
+
if (acc.event.event === LangGraphEventTypes.OnInterrupt) {
|
|
133
|
+
events.push({
|
|
134
|
+
type: RuntimeEventTypes.MetaEvent,
|
|
135
|
+
name: RuntimeMetaEventName.LangGraphInterruptEvent,
|
|
136
|
+
value: acc.event.value,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
128
140
|
const responseMetadata = this.getResponseMetadata(acc.event);
|
|
129
141
|
|
|
130
142
|
// Tool call ended: emit ActionExecutionEnd
|
|
@@ -11,6 +11,11 @@ export enum LangGraphEventTypes {
|
|
|
11
11
|
OnCopilotKitEmitMessage = "on_copilotkit_emit_message",
|
|
12
12
|
OnCopilotKitEmitToolCall = "on_copilotkit_emit_tool_call",
|
|
13
13
|
OnCustomEvent = "on_custom_event",
|
|
14
|
+
OnInterrupt = "on_interrupt",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export enum MetaEventNames {
|
|
18
|
+
LangGraphInterruptEvent = "LangGraphInterruptEvent",
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
export enum CustomEventNames {
|
|
@@ -325,6 +330,11 @@ type LangGraphOnCustomEvent = {
|
|
|
325
330
|
parent_ids: string[];
|
|
326
331
|
};
|
|
327
332
|
|
|
333
|
+
interface LangGraphInterruptEvent {
|
|
334
|
+
event: LangGraphEventTypes.OnInterrupt;
|
|
335
|
+
value: string;
|
|
336
|
+
}
|
|
337
|
+
|
|
328
338
|
export type LangGraphEvent =
|
|
329
339
|
| LangGraphOnChainStartEvent
|
|
330
340
|
| LangGraphOnChainStreamEvent
|
|
@@ -335,4 +345,5 @@ export type LangGraphEvent =
|
|
|
335
345
|
| LangGraphOnToolStartEvent
|
|
336
346
|
| LangGraphOnToolEndEvent
|
|
337
347
|
| LangGraphOnCopilotKitStateSyncEvent
|
|
338
|
-
| LangGraphOnCustomEvent
|
|
348
|
+
| LangGraphOnCustomEvent
|
|
349
|
+
| LangGraphInterruptEvent;
|
|
@@ -7,6 +7,7 @@ import { ForwardedParametersInput } from "./forwarded-parameters.input";
|
|
|
7
7
|
import { AgentSessionInput } from "./agent-session.input";
|
|
8
8
|
import { AgentStateInput } from "./agent-state.input";
|
|
9
9
|
import { ExtensionsInput } from "./extensions.input";
|
|
10
|
+
import { MetaEventInput } from "./meta-event.input";
|
|
10
11
|
|
|
11
12
|
@InputType()
|
|
12
13
|
export class GenerateCopilotResponseMetadataInput {
|
|
@@ -48,4 +49,7 @@ export class GenerateCopilotResponseInput {
|
|
|
48
49
|
|
|
49
50
|
@Field(() => ExtensionsInput, { nullable: true })
|
|
50
51
|
extensions?: ExtensionsInput;
|
|
52
|
+
|
|
53
|
+
@Field(() => [MetaEventInput], { nullable: true })
|
|
54
|
+
metaEvents?: MetaEventInput[];
|
|
51
55
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Field, InputType } from "type-graphql";
|
|
2
|
+
import { MetaEventName } from "../types/meta-events.type";
|
|
3
|
+
|
|
4
|
+
@InputType()
|
|
5
|
+
export class MetaEventInput {
|
|
6
|
+
@Field(() => String)
|
|
7
|
+
type: "MetaEvent" = "MetaEvent";
|
|
8
|
+
|
|
9
|
+
@Field(() => MetaEventName)
|
|
10
|
+
name: MetaEventName;
|
|
11
|
+
|
|
12
|
+
@Field(() => String)
|
|
13
|
+
value?: string;
|
|
14
|
+
|
|
15
|
+
@Field(() => String, { nullable: true })
|
|
16
|
+
response?: string;
|
|
17
|
+
}
|
|
@@ -14,10 +14,15 @@ import {
|
|
|
14
14
|
} from "rxjs";
|
|
15
15
|
import { GenerateCopilotResponseInput } from "../inputs/generate-copilot-response.input";
|
|
16
16
|
import { CopilotResponse } from "../types/copilot-response.type";
|
|
17
|
+
import { LangGraphInterruptEvent } from "../types/meta-events.type";
|
|
17
18
|
import { ActionInputAvailability, MessageRole } from "../types/enums";
|
|
18
19
|
import { Repeater } from "graphql-yoga";
|
|
19
20
|
import type { CopilotRequestContextProperties, GraphQLContext } from "../../lib/integrations";
|
|
20
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
RuntimeEvent,
|
|
23
|
+
RuntimeEventTypes,
|
|
24
|
+
RuntimeMetaEventName,
|
|
25
|
+
} from "../../service-adapters/events";
|
|
21
26
|
import {
|
|
22
27
|
FailedMessageStatus,
|
|
23
28
|
MessageStatusUnion,
|
|
@@ -210,15 +215,74 @@ export class CopilotResolver {
|
|
|
210
215
|
agentStates: data.agentStates,
|
|
211
216
|
url: data.frontend.url,
|
|
212
217
|
extensions: data.extensions,
|
|
218
|
+
metaEvents: data.metaEvents,
|
|
213
219
|
});
|
|
214
220
|
|
|
215
221
|
logger.debug("Event source created, creating response");
|
|
222
|
+
// run and process the event stream
|
|
223
|
+
const eventStream = eventSource
|
|
224
|
+
.processRuntimeEvents({
|
|
225
|
+
serverSideActions,
|
|
226
|
+
guardrailsResult$: data.cloud?.guardrails ? guardrailsResult$ : null,
|
|
227
|
+
actionInputsWithoutAgents: actionInputsWithoutAgents.filter(
|
|
228
|
+
// TODO-AGENTS: do not exclude ALL server side actions
|
|
229
|
+
(action) =>
|
|
230
|
+
!serverSideActions.find((serverSideAction) => serverSideAction.name == action.name),
|
|
231
|
+
),
|
|
232
|
+
threadId,
|
|
233
|
+
})
|
|
234
|
+
.pipe(
|
|
235
|
+
// shareReplay() ensures that later subscribers will see the whole stream instead of
|
|
236
|
+
// just the events that were emitted after the subscriber was added.
|
|
237
|
+
shareReplay(),
|
|
238
|
+
finalize(() => {
|
|
239
|
+
logger.debug("Event stream finalized");
|
|
240
|
+
}),
|
|
241
|
+
);
|
|
216
242
|
|
|
217
243
|
const response = {
|
|
218
244
|
threadId,
|
|
219
245
|
runId,
|
|
220
246
|
status: firstValueFrom(responseStatus$),
|
|
221
247
|
extensions,
|
|
248
|
+
metaEvents: new Repeater(async (push, stop) => {
|
|
249
|
+
let eventStreamSubscription: Subscription;
|
|
250
|
+
|
|
251
|
+
eventStreamSubscription = eventStream.subscribe({
|
|
252
|
+
next: async (event) => {
|
|
253
|
+
if (event.type != RuntimeEventTypes.MetaEvent) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
switch (event.name) {
|
|
257
|
+
case RuntimeMetaEventName.LangGraphInterruptEvent:
|
|
258
|
+
push(
|
|
259
|
+
plainToInstance(LangGraphInterruptEvent, {
|
|
260
|
+
type: event.type,
|
|
261
|
+
name: event.name,
|
|
262
|
+
value: event.value,
|
|
263
|
+
}),
|
|
264
|
+
);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
error: (err) => {
|
|
269
|
+
logger.error({ err }, "Error in meta events stream");
|
|
270
|
+
responseStatus$.next(
|
|
271
|
+
new UnknownErrorResponse({
|
|
272
|
+
description: `An unknown error has occurred in the event stream`,
|
|
273
|
+
}),
|
|
274
|
+
);
|
|
275
|
+
eventStreamSubscription?.unsubscribe();
|
|
276
|
+
stop();
|
|
277
|
+
},
|
|
278
|
+
complete: async () => {
|
|
279
|
+
logger.debug("Meta events stream completed");
|
|
280
|
+
responseStatus$.next(new SuccessResponseStatus());
|
|
281
|
+
eventStreamSubscription?.unsubscribe();
|
|
282
|
+
stop();
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
}),
|
|
222
286
|
messages: new Repeater(async (pushMessage, stopStreamingMessages) => {
|
|
223
287
|
logger.debug("Messages repeater created");
|
|
224
288
|
|
|
@@ -275,32 +339,13 @@ export class CopilotResolver {
|
|
|
275
339
|
|
|
276
340
|
let eventStreamSubscription: Subscription;
|
|
277
341
|
|
|
278
|
-
// run and process the event stream
|
|
279
|
-
const eventStream = eventSource
|
|
280
|
-
.processRuntimeEvents({
|
|
281
|
-
serverSideActions,
|
|
282
|
-
guardrailsResult$: data.cloud?.guardrails ? guardrailsResult$ : null,
|
|
283
|
-
actionInputsWithoutAgents: actionInputsWithoutAgents.filter(
|
|
284
|
-
// TODO-AGENTS: do not exclude ALL server side actions
|
|
285
|
-
(action) =>
|
|
286
|
-
!serverSideActions.find((serverSideAction) => serverSideAction.name == action.name),
|
|
287
|
-
),
|
|
288
|
-
threadId,
|
|
289
|
-
})
|
|
290
|
-
.pipe(
|
|
291
|
-
// shareReplay() ensures that later subscribers will see the whole stream instead of
|
|
292
|
-
// just the events that were emitted after the subscriber was added.
|
|
293
|
-
shareReplay(),
|
|
294
|
-
finalize(() => {
|
|
295
|
-
logger.debug("Event stream finalized");
|
|
296
|
-
}),
|
|
297
|
-
);
|
|
298
|
-
|
|
299
342
|
logger.debug("Event stream created, subscribing to event stream");
|
|
300
343
|
|
|
301
344
|
eventStreamSubscription = eventStream.subscribe({
|
|
302
345
|
next: async (event) => {
|
|
303
346
|
switch (event.type) {
|
|
347
|
+
case RuntimeEventTypes.MetaEvent:
|
|
348
|
+
break;
|
|
304
349
|
////////////////////////////////
|
|
305
350
|
// TextMessageStart
|
|
306
351
|
////////////////////////////////
|
|
@@ -3,6 +3,7 @@ import { MessageRole } from "./enums";
|
|
|
3
3
|
import { MessageStatusUnion } from "./message-status.type";
|
|
4
4
|
import { ResponseStatusUnion } from "./response-status.type";
|
|
5
5
|
import { ExtensionsResponse } from "./extensions-response.type";
|
|
6
|
+
import { BaseMetaEvent, LangGraphInterruptEvent, MetaEventName } from "./meta-events.type";
|
|
6
7
|
|
|
7
8
|
@InterfaceType({
|
|
8
9
|
resolveType(value) {
|
|
@@ -14,6 +15,8 @@ import { ExtensionsResponse } from "./extensions-response.type";
|
|
|
14
15
|
return ResultMessageOutput;
|
|
15
16
|
} else if (value.hasOwnProperty("state")) {
|
|
16
17
|
return AgentStateMessageOutput;
|
|
18
|
+
} else if (value.name === MetaEventName.LangGraphInterruptEvent) {
|
|
19
|
+
return LangGraphInterruptEvent;
|
|
17
20
|
}
|
|
18
21
|
return undefined;
|
|
19
22
|
},
|
|
@@ -114,4 +117,7 @@ export class CopilotResponse {
|
|
|
114
117
|
|
|
115
118
|
@Field(() => ExtensionsResponse, { nullable: true })
|
|
116
119
|
extensions?: ExtensionsResponse;
|
|
120
|
+
|
|
121
|
+
@Field(() => [BaseMetaEvent], { nullable: true })
|
|
122
|
+
metaEvents?: (typeof BaseMetaEvent)[];
|
|
117
123
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Field, InterfaceType, ObjectType, registerEnumType } from "type-graphql";
|
|
2
|
+
|
|
3
|
+
export enum MetaEventName {
|
|
4
|
+
LangGraphInterruptEvent = "LangGraphInterruptEvent",
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
registerEnumType(MetaEventName, {
|
|
8
|
+
name: "MetaEventName",
|
|
9
|
+
description: "Meta event types",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
@InterfaceType()
|
|
13
|
+
export abstract class BaseMetaEvent {
|
|
14
|
+
@Field(() => String)
|
|
15
|
+
type: "MetaEvent" = "MetaEvent";
|
|
16
|
+
|
|
17
|
+
@Field(() => MetaEventName)
|
|
18
|
+
name: MetaEventName;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@ObjectType({ implements: BaseMetaEvent })
|
|
22
|
+
export class LangGraphInterruptEvent {
|
|
23
|
+
@Field(() => MetaEventName)
|
|
24
|
+
name: MetaEventName.LangGraphInterruptEvent = MetaEventName.LangGraphInterruptEvent;
|
|
25
|
+
|
|
26
|
+
@Field(() => String)
|
|
27
|
+
value: string;
|
|
28
|
+
|
|
29
|
+
@Field(() => String, { nullable: true })
|
|
30
|
+
response?: string;
|
|
31
|
+
}
|
|
@@ -60,6 +60,7 @@ import { ExtensionsResponse } from "../../graphql/types/extensions-response.type
|
|
|
60
60
|
import { LoadAgentStateResponse } from "../../graphql/types/load-agent-state-response.type";
|
|
61
61
|
import { Client as LangGraphClient } from "@langchain/langgraph-sdk";
|
|
62
62
|
import { langchainMessagesToCopilotKit } from "./remote-lg-action";
|
|
63
|
+
import { MetaEventInput } from "../../graphql/inputs/meta-event.input";
|
|
63
64
|
|
|
64
65
|
interface CopilotRuntimeRequest {
|
|
65
66
|
serviceAdapter: CopilotServiceAdapter;
|
|
@@ -75,6 +76,7 @@ interface CopilotRuntimeRequest {
|
|
|
75
76
|
forwardedParameters?: ForwardedParametersInput;
|
|
76
77
|
url?: string;
|
|
77
78
|
extensions?: ExtensionsInput;
|
|
79
|
+
metaEvents?: MetaEventInput[];
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
interface CopilotRuntimeResponse {
|
|
@@ -319,9 +321,14 @@ please use an LLM adapter instead.`,
|
|
|
319
321
|
async (acc: Promise<Agent[]>, endpoint) => {
|
|
320
322
|
const agents = await acc;
|
|
321
323
|
if (endpoint.type === EndpointType.LangGraphPlatform) {
|
|
324
|
+
const propertyHeaders = graphqlContext.properties.authorization
|
|
325
|
+
? { authorization: `Bearer ${graphqlContext.properties.authorization}` }
|
|
326
|
+
: null;
|
|
327
|
+
|
|
322
328
|
const client = new LangGraphClient({
|
|
323
329
|
apiUrl: endpoint.deploymentUrl,
|
|
324
330
|
apiKey: endpoint.langsmithApiKey,
|
|
331
|
+
defaultHeaders: { ...propertyHeaders },
|
|
325
332
|
});
|
|
326
333
|
|
|
327
334
|
const data: Array<{ assistant_id: string; graph_id: string }> =
|
|
@@ -392,9 +399,14 @@ please use an LLM adapter instead.`,
|
|
|
392
399
|
const headers = createHeaders(null, graphqlContext);
|
|
393
400
|
|
|
394
401
|
if (agentWithEndpoint.endpoint.type === EndpointType.LangGraphPlatform) {
|
|
402
|
+
const propertyHeaders = graphqlContext.properties.authorization
|
|
403
|
+
? { authorization: `Bearer ${graphqlContext.properties.authorization}` }
|
|
404
|
+
: null;
|
|
405
|
+
|
|
395
406
|
const client = new LangGraphClient({
|
|
396
407
|
apiUrl: agentWithEndpoint.endpoint.deploymentUrl,
|
|
397
408
|
apiKey: agentWithEndpoint.endpoint.langsmithApiKey,
|
|
409
|
+
defaultHeaders: { ...propertyHeaders },
|
|
398
410
|
});
|
|
399
411
|
let state: any = {};
|
|
400
412
|
try {
|
|
@@ -455,6 +467,7 @@ please use an LLM adapter instead.`,
|
|
|
455
467
|
graphqlContext,
|
|
456
468
|
agentSession,
|
|
457
469
|
threadId: threadIdFromRequest,
|
|
470
|
+
metaEvents,
|
|
458
471
|
} = request;
|
|
459
472
|
const { agentName, nodeName } = agentSession;
|
|
460
473
|
|
|
@@ -499,6 +512,7 @@ please use an LLM adapter instead.`,
|
|
|
499
512
|
threadId,
|
|
500
513
|
nodeName,
|
|
501
514
|
actionInputsWithoutAgents,
|
|
515
|
+
metaEvents,
|
|
502
516
|
});
|
|
503
517
|
|
|
504
518
|
eventSource.stream(async (eventStream$) => {
|
|
@@ -42,6 +42,7 @@ export function constructLGCRemoteAction({
|
|
|
42
42
|
threadId,
|
|
43
43
|
nodeName,
|
|
44
44
|
additionalMessages = [],
|
|
45
|
+
metaEvents,
|
|
45
46
|
}: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
|
|
46
47
|
logger.debug({ actionName: agent.name }, "Executing LangGraph Platform agent");
|
|
47
48
|
|
|
@@ -62,7 +63,7 @@ export function constructLGCRemoteAction({
|
|
|
62
63
|
|
|
63
64
|
try {
|
|
64
65
|
const response = await execute({
|
|
65
|
-
logger,
|
|
66
|
+
logger: logger.child({ component: "remote-actions.remote-lg-action.streamEvents" }),
|
|
66
67
|
deploymentUrl: endpoint.deploymentUrl,
|
|
67
68
|
langsmithApiKey: endpoint.langsmithApiKey,
|
|
68
69
|
agent,
|
|
@@ -76,6 +77,7 @@ export function constructLGCRemoteAction({
|
|
|
76
77
|
description: action.description,
|
|
77
78
|
parameters: JSON.parse(action.jsonSchema) as string,
|
|
78
79
|
})),
|
|
80
|
+
metaEvents,
|
|
79
81
|
});
|
|
80
82
|
|
|
81
83
|
const eventSource = new RemoteLangGraphEventSource();
|
|
@@ -174,6 +176,7 @@ export function constructRemoteActions({
|
|
|
174
176
|
threadId,
|
|
175
177
|
nodeName,
|
|
176
178
|
additionalMessages = [],
|
|
179
|
+
metaEvents,
|
|
177
180
|
}: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
|
|
178
181
|
logger.debug({ actionName: agent.name }, "Executing remote agent");
|
|
179
182
|
|
|
@@ -209,6 +212,7 @@ export function constructRemoteActions({
|
|
|
209
212
|
description: action.description,
|
|
210
213
|
parameters: JSON.parse(action.jsonSchema),
|
|
211
214
|
})),
|
|
215
|
+
metaEvents,
|
|
212
216
|
}),
|
|
213
217
|
});
|
|
214
218
|
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
ResolvedCopilotKitError,
|
|
17
17
|
CopilotKitError,
|
|
18
18
|
} from "@copilotkit/shared";
|
|
19
|
+
import { MetaEventInput } from "../../graphql/inputs/meta-event.input";
|
|
19
20
|
|
|
20
21
|
export type EndpointDefinition = CopilotKitEndpoint | LangGraphPlatformEndpoint;
|
|
21
22
|
|
|
@@ -59,6 +60,7 @@ export type LangGraphAgentHandlerParams = {
|
|
|
59
60
|
threadId?: string;
|
|
60
61
|
nodeName?: string;
|
|
61
62
|
additionalMessages?: Message[];
|
|
63
|
+
metaEvents?: MetaEventInput[];
|
|
62
64
|
};
|
|
63
65
|
|
|
64
66
|
export type LangGraphAgentAction = Action<any> & {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Client } from "@langchain/langgraph-sdk";
|
|
1
|
+
import { Client as LangGraphClient } from "@langchain/langgraph-sdk";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import {
|
|
3
|
+
import { isValidUUID, randomUUID } from "@copilotkit/shared";
|
|
4
4
|
import { parse as parsePartialJson } from "partial-json";
|
|
5
5
|
import { Logger } from "pino";
|
|
6
6
|
import { ActionInput } from "../../graphql/inputs/action.input";
|
|
@@ -10,6 +10,9 @@ import { ActionExecutionMessage, Message, MessageType } from "../../graphql/type
|
|
|
10
10
|
import { MessageRole } from "../../graphql/types/enums";
|
|
11
11
|
import { CustomEventNames, LangGraphEventTypes } from "../../agents/langgraph/events";
|
|
12
12
|
import telemetry from "../telemetry-client";
|
|
13
|
+
import { MetaEventInput } from "../../graphql/inputs/meta-event.input";
|
|
14
|
+
import { MetaEventName } from "../../graphql/types/meta-events.type";
|
|
15
|
+
import { RunsStreamPayload } from "@langchain/langgraph-sdk/dist/types";
|
|
13
16
|
|
|
14
17
|
type State = Record<string, any>;
|
|
15
18
|
|
|
@@ -24,6 +27,7 @@ interface ExecutionArgs extends Omit<LangGraphPlatformEndpoint, "agents"> {
|
|
|
24
27
|
properties: CopilotRequestContextProperties;
|
|
25
28
|
actions: ExecutionAction[];
|
|
26
29
|
logger: Logger;
|
|
30
|
+
metaEvents?: MetaEventInput[];
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
// The following types are our own definition to the messages accepted by LangGraph Platform, enhanced with some of our extra data.
|
|
@@ -84,13 +88,23 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
84
88
|
messages,
|
|
85
89
|
actions,
|
|
86
90
|
logger,
|
|
91
|
+
properties,
|
|
92
|
+
metaEvents,
|
|
87
93
|
} = args;
|
|
88
94
|
|
|
89
95
|
let nodeName = initialNodeName;
|
|
90
96
|
let state = initialState;
|
|
91
97
|
const { name, assistantId: initialAssistantId } = agent;
|
|
92
98
|
|
|
93
|
-
const
|
|
99
|
+
const propertyHeaders = properties.authorization
|
|
100
|
+
? { authorization: `Bearer ${properties.authorization}` }
|
|
101
|
+
: null;
|
|
102
|
+
|
|
103
|
+
const client = new LangGraphClient({
|
|
104
|
+
apiUrl: deploymentUrl,
|
|
105
|
+
apiKey: langsmithApiKey,
|
|
106
|
+
defaultHeaders: { ...propertyHeaders },
|
|
107
|
+
});
|
|
94
108
|
|
|
95
109
|
let threadId = argsInitialThreadId ?? randomUUID();
|
|
96
110
|
if (argsInitialThreadId && argsInitialThreadId.startsWith("ck-")) {
|
|
@@ -130,7 +144,11 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
130
144
|
}
|
|
131
145
|
state = langGraphDefaultMergeState(state, formattedMessages, actions, name);
|
|
132
146
|
|
|
133
|
-
|
|
147
|
+
const lgInterruptEvent = metaEvents?.find(
|
|
148
|
+
(ev) => ev.name === MetaEventName.LangGraphInterruptEvent,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
if (mode === "continue" && !lgInterruptEvent) {
|
|
134
152
|
await client.threads.updateState(threadId, { values: state, asNode: nodeName });
|
|
135
153
|
}
|
|
136
154
|
|
|
@@ -171,10 +189,16 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
171
189
|
let shouldExit = false;
|
|
172
190
|
let externalRunId = null;
|
|
173
191
|
|
|
174
|
-
const
|
|
192
|
+
const payload: RunsStreamPayload = {
|
|
175
193
|
input: streamInput,
|
|
176
|
-
streamMode: ["events", "values"],
|
|
177
|
-
|
|
194
|
+
streamMode: ["events", "values", "updates"],
|
|
195
|
+
command: undefined,
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
if (lgInterruptEvent?.response) {
|
|
199
|
+
payload.command = { resume: lgInterruptEvent.response };
|
|
200
|
+
}
|
|
201
|
+
const streamResponse = client.runs.stream(threadId, assistantId, payload);
|
|
178
202
|
|
|
179
203
|
const emit = (message: string) => controller.enqueue(new TextEncoder().encode(message));
|
|
180
204
|
|
|
@@ -189,12 +213,23 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
189
213
|
hashedLgcKey: streamInfo.hashedLgcKey,
|
|
190
214
|
});
|
|
191
215
|
for await (const chunk of streamResponse) {
|
|
192
|
-
if (!["events", "values", "error"].includes(chunk.event)) continue;
|
|
216
|
+
if (!["events", "values", "error", "updates"].includes(chunk.event)) continue;
|
|
193
217
|
|
|
194
218
|
if (chunk.event === "error") {
|
|
195
219
|
throw new Error(`Error event thrown: ${chunk.data.message}`);
|
|
196
220
|
}
|
|
197
221
|
|
|
222
|
+
if (chunk.event === "updates" && chunk.data.__interrupt__) {
|
|
223
|
+
emit(
|
|
224
|
+
JSON.stringify({
|
|
225
|
+
event: LangGraphEventTypes.OnInterrupt,
|
|
226
|
+
value: chunk.data.__interrupt__[0].value,
|
|
227
|
+
}) + "\n",
|
|
228
|
+
);
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (chunk.event === "updates") continue;
|
|
232
|
+
|
|
198
233
|
if (chunk.event === "values") {
|
|
199
234
|
latestStateValues = chunk.data;
|
|
200
235
|
continue;
|
|
@@ -317,8 +352,9 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
317
352
|
}
|
|
318
353
|
|
|
319
354
|
state = await client.threads.getState(threadId);
|
|
320
|
-
const
|
|
321
|
-
nodeName = Object.keys(state.metadata.writes)[0];
|
|
355
|
+
const interrupts = state.tasks?.[0]?.interrupts;
|
|
356
|
+
nodeName = interrupts ? nodeName : Object.keys(state.metadata.writes)[0];
|
|
357
|
+
const isEndNode = state.next.length === 0 && !interrupts;
|
|
322
358
|
|
|
323
359
|
telemetry.capture("oss.runtime.agent_execution_stream_ended", streamInfo);
|
|
324
360
|
|
|
@@ -28,8 +28,26 @@ export enum RuntimeEventTypes {
|
|
|
28
28
|
ActionExecutionEnd = "ActionExecutionEnd",
|
|
29
29
|
ActionExecutionResult = "ActionExecutionResult",
|
|
30
30
|
AgentStateMessage = "AgentStateMessage",
|
|
31
|
+
MetaEvent = "MetaEvent",
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
export enum RuntimeMetaEventName {
|
|
35
|
+
LangGraphInterruptEvent = "LangGraphInterruptEvent",
|
|
36
|
+
LangGraphInterruptResumeEvent = "LangGraphInterruptResumeEvent",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type RunTimeMetaEvent =
|
|
40
|
+
| {
|
|
41
|
+
type: RuntimeEventTypes.MetaEvent;
|
|
42
|
+
name: RuntimeMetaEventName.LangGraphInterruptEvent;
|
|
43
|
+
value: string;
|
|
44
|
+
}
|
|
45
|
+
| {
|
|
46
|
+
type: RuntimeEventTypes.MetaEvent;
|
|
47
|
+
name: RuntimeMetaEventName.LangGraphInterruptResumeEvent;
|
|
48
|
+
value: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
33
51
|
export type RuntimeEvent =
|
|
34
52
|
| { type: RuntimeEventTypes.TextMessageStart; messageId: string; parentMessageId?: string }
|
|
35
53
|
| {
|
|
@@ -62,7 +80,8 @@ export type RuntimeEvent =
|
|
|
62
80
|
role: string;
|
|
63
81
|
state: string;
|
|
64
82
|
running: boolean;
|
|
65
|
-
}
|
|
83
|
+
}
|
|
84
|
+
| RunTimeMetaEvent;
|
|
66
85
|
|
|
67
86
|
interface RuntimeEventWithState {
|
|
68
87
|
event: RuntimeEvent | null;
|