@copilotkit/runtime 1.5.15-next.3 → 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 +10 -0
- package/__snapshots__/schema/schema.graphql +26 -0
- package/dist/{chunk-WPJHMQDF.mjs → chunk-6Z3DFNOC.mjs} +2 -2
- package/dist/{chunk-KPOZF6JI.mjs → chunk-EC2ZHPRU.mjs} +2 -2
- package/dist/{chunk-I2OII4XX.mjs → chunk-QDK4OP2Y.mjs} +2 -2
- package/dist/{chunk-EV3MMEAZ.mjs → chunk-W4G47FRC.mjs} +513 -295
- 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 +787 -571
- 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 +787 -571
- 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 +4 -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 +35 -8
- package/src/service-adapters/events.ts +20 -1
- package/dist/chunk-EV3MMEAZ.mjs.map +0 -1
- /package/dist/{chunk-WPJHMQDF.mjs.map → chunk-6Z3DFNOC.mjs.map} +0 -0
- /package/dist/{chunk-KPOZF6JI.mjs.map → chunk-EC2ZHPRU.mjs.map} +0 -0
- /package/dist/{chunk-I2OII4XX.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 {
|
|
@@ -465,6 +467,7 @@ please use an LLM adapter instead.`,
|
|
|
465
467
|
graphqlContext,
|
|
466
468
|
agentSession,
|
|
467
469
|
threadId: threadIdFromRequest,
|
|
470
|
+
metaEvents,
|
|
468
471
|
} = request;
|
|
469
472
|
const { agentName, nodeName } = agentSession;
|
|
470
473
|
|
|
@@ -509,6 +512,7 @@ please use an LLM adapter instead.`,
|
|
|
509
512
|
threadId,
|
|
510
513
|
nodeName,
|
|
511
514
|
actionInputsWithoutAgents,
|
|
515
|
+
metaEvents,
|
|
512
516
|
});
|
|
513
517
|
|
|
514
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
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.
|
|
@@ -85,6 +89,7 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
85
89
|
actions,
|
|
86
90
|
logger,
|
|
87
91
|
properties,
|
|
92
|
+
metaEvents,
|
|
88
93
|
} = args;
|
|
89
94
|
|
|
90
95
|
let nodeName = initialNodeName;
|
|
@@ -139,7 +144,11 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
139
144
|
}
|
|
140
145
|
state = langGraphDefaultMergeState(state, formattedMessages, actions, name);
|
|
141
146
|
|
|
142
|
-
|
|
147
|
+
const lgInterruptEvent = metaEvents?.find(
|
|
148
|
+
(ev) => ev.name === MetaEventName.LangGraphInterruptEvent,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
if (mode === "continue" && !lgInterruptEvent) {
|
|
143
152
|
await client.threads.updateState(threadId, { values: state, asNode: nodeName });
|
|
144
153
|
}
|
|
145
154
|
|
|
@@ -180,10 +189,16 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
180
189
|
let shouldExit = false;
|
|
181
190
|
let externalRunId = null;
|
|
182
191
|
|
|
183
|
-
const
|
|
192
|
+
const payload: RunsStreamPayload = {
|
|
184
193
|
input: streamInput,
|
|
185
|
-
streamMode: ["events", "values"],
|
|
186
|
-
|
|
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);
|
|
187
202
|
|
|
188
203
|
const emit = (message: string) => controller.enqueue(new TextEncoder().encode(message));
|
|
189
204
|
|
|
@@ -198,12 +213,23 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
198
213
|
hashedLgcKey: streamInfo.hashedLgcKey,
|
|
199
214
|
});
|
|
200
215
|
for await (const chunk of streamResponse) {
|
|
201
|
-
if (!["events", "values", "error"].includes(chunk.event)) continue;
|
|
216
|
+
if (!["events", "values", "error", "updates"].includes(chunk.event)) continue;
|
|
202
217
|
|
|
203
218
|
if (chunk.event === "error") {
|
|
204
219
|
throw new Error(`Error event thrown: ${chunk.data.message}`);
|
|
205
220
|
}
|
|
206
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
|
+
|
|
207
233
|
if (chunk.event === "values") {
|
|
208
234
|
latestStateValues = chunk.data;
|
|
209
235
|
continue;
|
|
@@ -326,8 +352,9 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
326
352
|
}
|
|
327
353
|
|
|
328
354
|
state = await client.threads.getState(threadId);
|
|
329
|
-
const
|
|
330
|
-
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;
|
|
331
358
|
|
|
332
359
|
telemetry.capture("oss.runtime.agent_execution_stream_ended", streamInfo);
|
|
333
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;
|