@copilotkit/runtime 1.5.12-next.6 → 1.5.12

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/__snapshots__/schema/schema.graphql +33 -0
  3. package/dist/{chunk-XM2VJFL6.mjs → chunk-4LRVKGBI.mjs} +2 -2
  4. package/dist/{chunk-YGXAWYRB.mjs → chunk-IS3QAGOU.mjs} +2 -2
  5. package/dist/{chunk-ON4AESON.mjs → chunk-PFELVFS7.mjs} +540 -221
  6. package/dist/chunk-PFELVFS7.mjs.map +1 -0
  7. package/dist/{chunk-TPTCSIAR.mjs → chunk-S3KKBII4.mjs} +42 -30
  8. package/dist/chunk-S3KKBII4.mjs.map +1 -0
  9. package/dist/{chunk-BKIGYRXE.mjs → chunk-W6EE6OTN.mjs} +2 -2
  10. package/dist/{copilot-runtime-da917bd5.d.ts → copilot-runtime-8c442d65.d.ts} +16 -5
  11. package/dist/graphql/types/converted/index.d.ts +1 -1
  12. package/dist/{groq-adapter-c35c5374.d.ts → groq-adapter-7a82cd22.d.ts} +21 -1
  13. package/dist/{index-24315d90.d.ts → index-a7f37670.d.ts} +1 -1
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +628 -297
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +10 -10
  18. package/dist/{langserve-a16ef8f4.d.ts → langserve-e308c437.d.ts} +32 -3
  19. package/dist/lib/index.d.ts +4 -4
  20. package/dist/lib/index.js +626 -295
  21. package/dist/lib/index.js.map +1 -1
  22. package/dist/lib/index.mjs +6 -6
  23. package/dist/lib/integrations/index.d.ts +4 -4
  24. package/dist/lib/integrations/index.js +495 -237
  25. package/dist/lib/integrations/index.js.map +1 -1
  26. package/dist/lib/integrations/index.mjs +5 -5
  27. package/dist/lib/integrations/nest/index.d.ts +3 -3
  28. package/dist/lib/integrations/nest/index.js +495 -237
  29. package/dist/lib/integrations/nest/index.js.map +1 -1
  30. package/dist/lib/integrations/nest/index.mjs +3 -3
  31. package/dist/lib/integrations/node-express/index.d.ts +3 -3
  32. package/dist/lib/integrations/node-express/index.js +495 -237
  33. package/dist/lib/integrations/node-express/index.js.map +1 -1
  34. package/dist/lib/integrations/node-express/index.mjs +3 -3
  35. package/dist/lib/integrations/node-http/index.d.ts +3 -3
  36. package/dist/lib/integrations/node-http/index.js +495 -237
  37. package/dist/lib/integrations/node-http/index.js.map +1 -1
  38. package/dist/lib/integrations/node-http/index.mjs +2 -2
  39. package/dist/service-adapters/index.d.ts +4 -4
  40. package/dist/service-adapters/index.js +23 -11
  41. package/dist/service-adapters/index.js.map +1 -1
  42. package/dist/service-adapters/index.mjs +1 -1
  43. package/package.json +2 -2
  44. package/src/graphql/inputs/extensions.input.ts +21 -0
  45. package/src/graphql/inputs/generate-copilot-response.input.ts +4 -0
  46. package/src/graphql/inputs/load-agent-state.input.ts +10 -0
  47. package/src/graphql/resolvers/copilot.resolver.ts +8 -3
  48. package/src/graphql/resolvers/state.resolver.ts +23 -0
  49. package/src/graphql/types/agents-response.type.ts +1 -4
  50. package/src/graphql/types/copilot-response.type.ts +5 -1
  51. package/src/graphql/types/extensions-response.type.ts +23 -0
  52. package/src/graphql/types/load-agent-state-response.type.ts +17 -0
  53. package/src/lib/integrations/shared.ts +2 -1
  54. package/src/lib/runtime/copilot-runtime.ts +102 -9
  55. package/src/lib/runtime/remote-lg-action.ts +24 -12
  56. package/src/service-adapters/anthropic/anthropic-adapter.ts +2 -3
  57. package/src/service-adapters/empty/empty-adapter.ts +2 -2
  58. package/src/service-adapters/events.ts +5 -0
  59. package/src/service-adapters/experimental/ollama/ollama-adapter.ts +2 -2
  60. package/src/service-adapters/groq/groq-adapter.ts +2 -2
  61. package/src/service-adapters/langchain/langchain-adapter.ts +10 -3
  62. package/src/service-adapters/openai/openai-adapter.ts +4 -3
  63. package/src/service-adapters/openai/openai-assistant-adapter.ts +15 -4
  64. package/src/service-adapters/service-adapter.ts +4 -0
  65. package/src/service-adapters/unify/unify-adapter.ts +2 -3
  66. package/dist/chunk-ON4AESON.mjs.map +0 -1
  67. package/dist/chunk-TPTCSIAR.mjs.map +0 -1
  68. /package/dist/{chunk-XM2VJFL6.mjs.map → chunk-4LRVKGBI.mjs.map} +0 -0
  69. /package/dist/{chunk-YGXAWYRB.mjs.map → chunk-IS3QAGOU.mjs.map} +0 -0
  70. /package/dist/{chunk-BKIGYRXE.mjs.map → chunk-W6EE6OTN.mjs.map} +0 -0
@@ -42,7 +42,6 @@ import {
42
42
  } from "../types/converted";
43
43
  import telemetry from "../../lib/telemetry-client";
44
44
  import { randomId } from "@copilotkit/shared";
45
- import { EndpointType, LangGraphPlatformAgent } from "../../lib/runtime/remote-actions";
46
45
  import { AgentsResponse } from "../types/agents-response.type";
47
46
 
48
47
  const invokeGuardrails = async ({
@@ -113,12 +112,14 @@ export class CopilotResolver {
113
112
  let logger = ctx.logger.child({ component: "CopilotResolver.availableAgents" });
114
113
 
115
114
  logger.debug("Processing");
116
- const agents = await ctx._copilotkit.runtime.discoverAgentsFromEndpoints(ctx);
115
+ const agentsWithEndpoints = await ctx._copilotkit.runtime.discoverAgentsFromEndpoints(ctx);
117
116
 
118
117
  logger.debug("Event source created, creating response");
119
118
 
120
119
  return {
121
- agents,
120
+ agents: agentsWithEndpoints.map(
121
+ ({ endpoint, ...agentWithoutEndpoint }) => agentWithoutEndpoint,
122
+ ),
122
123
  };
123
124
  }
124
125
 
@@ -192,6 +193,7 @@ export class CopilotResolver {
192
193
  runId,
193
194
  serverSideActions,
194
195
  actionInputsWithoutAgents,
196
+ extensions,
195
197
  } = await copilotRuntime.processRuntimeRequest({
196
198
  serviceAdapter,
197
199
  messages: data.messages,
@@ -207,6 +209,7 @@ export class CopilotResolver {
207
209
  agentSession: data.agentSession,
208
210
  agentStates: data.agentStates,
209
211
  url: data.frontend.url,
212
+ extensions: data.extensions,
210
213
  });
211
214
 
212
215
  logger.debug("Event source created, creating response");
@@ -215,6 +218,7 @@ export class CopilotResolver {
215
218
  threadId,
216
219
  runId,
217
220
  status: firstValueFrom(responseStatus$),
221
+ extensions,
218
222
  messages: new Repeater(async (pushMessage, stopStreamingMessages) => {
219
223
  logger.debug("Messages repeater created");
220
224
 
@@ -281,6 +285,7 @@ export class CopilotResolver {
281
285
  (action) =>
282
286
  !serverSideActions.find((serverSideAction) => serverSideAction.name == action.name),
283
287
  ),
288
+ threadId,
284
289
  })
285
290
  .pipe(
286
291
  // shareReplay() ensures that later subscribers will see the whole stream instead of
@@ -0,0 +1,23 @@
1
+ import { Arg, Resolver } from "type-graphql";
2
+ import { Ctx } from "type-graphql";
3
+ import { Query } from "type-graphql";
4
+ import { LoadAgentStateResponse } from "../types/load-agent-state-response.type";
5
+ import type { GraphQLContext } from "../../lib/integrations";
6
+ import { LoadAgentStateInput } from "../inputs/load-agent-state.input";
7
+
8
+ @Resolver(() => LoadAgentStateResponse)
9
+ export class StateResolver {
10
+ @Query(() => LoadAgentStateResponse)
11
+ async loadAgentState(@Ctx() ctx: GraphQLContext, @Arg("data") data: LoadAgentStateInput) {
12
+ const agents = await ctx._copilotkit.runtime.discoverAgentsFromEndpoints(ctx);
13
+ const agent = agents.find((agent) => agent.name === data.agentName);
14
+
15
+ if (!agent) {
16
+ throw new Error("Agent not found");
17
+ }
18
+
19
+ const state = await ctx._copilotkit.runtime.loadAgentState(ctx, data.threadId, data.agentName);
20
+
21
+ return state;
22
+ }
23
+ }
@@ -1,7 +1,4 @@
1
- import { Field, InterfaceType, ObjectType } from "type-graphql";
2
- import { MessageRole } from "./enums";
3
- import { MessageStatusUnion } from "./message-status.type";
4
- import { ResponseStatusUnion } from "./response-status.type";
1
+ import { Field, ObjectType } from "type-graphql";
5
2
 
6
3
  @ObjectType()
7
4
  export class Agent {
@@ -2,6 +2,7 @@ import { Field, InterfaceType, ObjectType } from "type-graphql";
2
2
  import { MessageRole } from "./enums";
3
3
  import { MessageStatusUnion } from "./message-status.type";
4
4
  import { ResponseStatusUnion } from "./response-status.type";
5
+ import { ExtensionsResponse } from "./extensions-response.type";
5
6
 
6
7
  @InterfaceType({
7
8
  resolveType(value) {
@@ -17,7 +18,7 @@ import { ResponseStatusUnion } from "./response-status.type";
17
18
  return undefined;
18
19
  },
19
20
  })
20
- abstract class BaseMessageOutput {
21
+ export abstract class BaseMessageOutput {
21
22
  @Field(() => String)
22
23
  id: string;
23
24
 
@@ -110,4 +111,7 @@ export class CopilotResponse {
110
111
 
111
112
  @Field(() => [BaseMessageOutput])
112
113
  messages: (typeof BaseMessageOutput)[];
114
+
115
+ @Field(() => ExtensionsResponse, { nullable: true })
116
+ extensions?: ExtensionsResponse;
113
117
  }
@@ -0,0 +1,23 @@
1
+ import { Field, ObjectType } from "type-graphql";
2
+
3
+ /**
4
+ * The extensions response is used to receive additional information from the copilot runtime, specific to a
5
+ * service adapter or agent framework.
6
+ *
7
+ * Next time a request to the runtime is made, the extensions response will be included in the request as input.
8
+ */
9
+
10
+ @ObjectType()
11
+ export class ExtensionsResponse {
12
+ @Field(() => OpenAIApiAssistantAPIResponse, { nullable: true })
13
+ openaiAssistantAPI?: OpenAIApiAssistantAPIResponse;
14
+ }
15
+
16
+ @ObjectType()
17
+ export class OpenAIApiAssistantAPIResponse {
18
+ @Field(() => String, { nullable: true })
19
+ runId?: string;
20
+
21
+ @Field(() => String, { nullable: true })
22
+ threadId?: string;
23
+ }
@@ -0,0 +1,17 @@
1
+ import { Field, ObjectType } from "type-graphql";
2
+ import { BaseMessageOutput } from "./copilot-response.type";
3
+
4
+ @ObjectType()
5
+ export class LoadAgentStateResponse {
6
+ @Field(() => String)
7
+ threadId: string;
8
+
9
+ @Field(() => Boolean)
10
+ threadExists: boolean;
11
+
12
+ @Field(() => String)
13
+ state: string;
14
+
15
+ @Field(() => String)
16
+ messages: string;
17
+ }
@@ -8,6 +8,7 @@ import { CopilotCloudOptions } from "../cloud";
8
8
  import { LogLevel, createLogger } from "../../lib/logger";
9
9
  import { createYoga } from "graphql-yoga";
10
10
  import telemetry from "../telemetry-client";
11
+ import { StateResolver } from "../../graphql/resolvers/state.resolver";
11
12
 
12
13
  const logger = createLogger();
13
14
 
@@ -58,7 +59,7 @@ export function buildSchema(
58
59
  ) {
59
60
  logger.debug("Building GraphQL schema...");
60
61
  const schema = buildSchemaSync({
61
- resolvers: [CopilotResolver],
62
+ resolvers: [CopilotResolver, StateResolver],
62
63
  emitSchemaFile: options.emitSchemaFile,
63
64
  });
64
65
  logger.debug("GraphQL schema built successfully");
@@ -24,19 +24,20 @@ import {
24
24
  CopilotKitAgentDiscoveryError,
25
25
  CopilotKitMisuseError,
26
26
  } from "@copilotkit/shared";
27
- import { Client as LangGraphClient } from "@langchain/langgraph-sdk";
28
27
  import {
29
28
  CopilotServiceAdapter,
30
29
  EmptyAdapter,
31
30
  RemoteChain,
32
31
  RemoteChainParameters,
33
32
  } from "../../service-adapters";
33
+
34
34
  import { MessageInput } from "../../graphql/inputs/message.input";
35
35
  import { ActionInput } from "../../graphql/inputs/action.input";
36
36
  import { RuntimeEventSource } from "../../service-adapters/events";
37
37
  import { convertGqlInputToMessages } from "../../service-adapters/conversion";
38
38
  import { Message } from "../../graphql/types/converted";
39
39
  import { ForwardedParametersInput } from "../../graphql/inputs/forwarded-parameters.input";
40
+
40
41
  import {
41
42
  isLangGraphAgentAction,
42
43
  LangGraphAgentAction,
@@ -46,6 +47,7 @@ import {
46
47
  CopilotKitEndpoint,
47
48
  LangGraphPlatformEndpoint,
48
49
  } from "./remote-actions";
50
+
49
51
  import { GraphQLContext } from "../integrations/shared";
50
52
  import { AgentSessionInput } from "../../graphql/inputs/agent-session.input";
51
53
  import { from } from "rxjs";
@@ -53,6 +55,11 @@ import { AgentStateInput } from "../../graphql/inputs/agent-state.input";
53
55
  import { ActionInputAvailability } from "../../graphql/types/enums";
54
56
  import { createHeaders } from "./remote-action-constructors";
55
57
  import { Agent } from "../../graphql/types/agents-response.type";
58
+ import { ExtensionsInput } from "../../graphql/inputs/extensions.input";
59
+ import { ExtensionsResponse } from "../../graphql/types/extensions-response.type";
60
+ import { LoadAgentStateResponse } from "../../graphql/types/load-agent-state-response.type";
61
+ import { Client as LangGraphClient } from "@langchain/langgraph-sdk";
62
+ import { langchainMessagesToCopilotKit } from "./remote-lg-action";
56
63
 
57
64
  interface CopilotRuntimeRequest {
58
65
  serviceAdapter: CopilotServiceAdapter;
@@ -67,6 +74,7 @@ interface CopilotRuntimeRequest {
67
74
  graphqlContext: GraphQLContext;
68
75
  forwardedParameters?: ForwardedParametersInput;
69
76
  url?: string;
77
+ extensions?: ExtensionsInput;
70
78
  }
71
79
 
72
80
  interface CopilotRuntimeResponse {
@@ -75,6 +83,7 @@ interface CopilotRuntimeResponse {
75
83
  eventSource: RuntimeEventSource;
76
84
  serverSideActions: Action<any>[];
77
85
  actionInputsWithoutAgents: ActionInput[];
86
+ extensions?: ExtensionsResponse;
78
87
  }
79
88
 
80
89
  type ActionsConfiguration<T extends Parameter[] | [] = []> =
@@ -114,6 +123,8 @@ interface Middleware {
114
123
  onAfterRequest?: OnAfterRequestHandler;
115
124
  }
116
125
 
126
+ type AgentWithEndpoint = Agent & { endpoint: EndpointDefinition };
127
+
117
128
  export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []> {
118
129
  /**
119
130
  * Middleware to be used by the runtime.
@@ -193,6 +204,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
193
204
  forwardedParameters,
194
205
  agentSession,
195
206
  url,
207
+ extensions,
196
208
  } = request;
197
209
 
198
210
  const eventSource = new RuntimeEventSource();
@@ -243,12 +255,17 @@ please use an LLM adapter instead.`,
243
255
  runId,
244
256
  eventSource,
245
257
  forwardedParameters,
258
+ extensions,
246
259
  });
247
260
 
261
+ // for backwards compatibility, we deal with the case that no threadId is provided
262
+ // by the frontend, by using the threadId from the response
263
+ const nonEmptyThreadId = threadId ?? result.threadId;
264
+
248
265
  outputMessagesPromise
249
266
  .then((outputMessages) => {
250
267
  this.onAfterRequest?.({
251
- threadId: result.threadId,
268
+ threadId: nonEmptyThreadId,
252
269
  runId: result.runId,
253
270
  inputMessages,
254
271
  outputMessages,
@@ -259,7 +276,7 @@ please use an LLM adapter instead.`,
259
276
  .catch((_error) => {});
260
277
 
261
278
  return {
262
- threadId: result.threadId,
279
+ threadId: nonEmptyThreadId,
263
280
  runId: result.runId,
264
281
  eventSource,
265
282
  serverSideActions,
@@ -271,6 +288,7 @@ please use an LLM adapter instead.`,
271
288
  // serverSideActions.find((serverSideAction) => serverSideAction.name == action.name),
272
289
  // ),
273
290
  ),
291
+ extensions: result.extensions,
274
292
  };
275
293
  } catch (error) {
276
294
  if (error instanceof CopilotKitError) {
@@ -282,9 +300,7 @@ please use an LLM adapter instead.`,
282
300
  }
283
301
  }
284
302
 
285
- async discoverAgentsFromEndpoints(
286
- graphqlContext: GraphQLContext,
287
- ): Promise<(Agent & { endpoint: EndpointDefinition })[]> {
303
+ async discoverAgentsFromEndpoints(graphqlContext: GraphQLContext): Promise<AgentWithEndpoint[]> {
288
304
  const headers = createHeaders(null, graphqlContext);
289
305
  const agents = this.remoteEndpointDefinitions.reduce(
290
306
  async (acc: Promise<Agent[]>, endpoint) => {
@@ -331,8 +347,9 @@ please use an LLM adapter instead.`,
331
347
  const data: InfoResponse = await response.json();
332
348
  const endpointAgents = (data?.agents ?? []).map((agent) => ({
333
349
  name: agent.name,
334
- description: agent.description ?? "",
350
+ description: agent.description ?? "" ?? "",
335
351
  id: randomId(), // Required by Agent type
352
+ endpoint,
336
353
  }));
337
354
  return [...agents, ...endpointAgents];
338
355
  } catch (error) {
@@ -348,11 +365,87 @@ please use an LLM adapter instead.`,
348
365
  return agents;
349
366
  }
350
367
 
368
+ async loadAgentState(
369
+ graphqlContext: GraphQLContext,
370
+ threadId: string,
371
+ agentName: string,
372
+ ): Promise<LoadAgentStateResponse> {
373
+ const agentsWithEndpoints = await this.discoverAgentsFromEndpoints(graphqlContext);
374
+
375
+ const agentWithEndpoint = agentsWithEndpoints.find((agent) => agent.name === agentName);
376
+ if (!agentWithEndpoint) {
377
+ throw new Error("Agent not found");
378
+ }
379
+ const headers = createHeaders(null, graphqlContext);
380
+
381
+ if (agentWithEndpoint.endpoint.type === EndpointType.LangGraphPlatform) {
382
+ const client = new LangGraphClient({
383
+ apiUrl: agentWithEndpoint.endpoint.deploymentUrl,
384
+ apiKey: agentWithEndpoint.endpoint.langsmithApiKey,
385
+ });
386
+ const state = (await client.threads.getState(threadId)).values as any;
387
+
388
+ if (Object.keys(state).length === 0) {
389
+ return {
390
+ threadId,
391
+ threadExists: false,
392
+ state: JSON.stringify({}),
393
+ messages: JSON.stringify([]),
394
+ };
395
+ } else {
396
+ console.log(state);
397
+ const { messages, ...stateWithoutMessages } = state;
398
+ const copilotkitMessages = langchainMessagesToCopilotKit(messages);
399
+ return {
400
+ threadId,
401
+ threadExists: true,
402
+ state: JSON.stringify(stateWithoutMessages),
403
+ messages: JSON.stringify(copilotkitMessages),
404
+ };
405
+ }
406
+ } else if (
407
+ agentWithEndpoint.endpoint.type === EndpointType.CopilotKit ||
408
+ !("type" in agentWithEndpoint.endpoint)
409
+ ) {
410
+ const response = await fetch(
411
+ `${(agentWithEndpoint.endpoint as CopilotKitEndpoint).url}/agents/state`,
412
+ {
413
+ method: "POST",
414
+ headers,
415
+ body: JSON.stringify({
416
+ properties: graphqlContext.properties,
417
+ threadId,
418
+ name: agentName,
419
+ }),
420
+ },
421
+ );
422
+ const data: LoadAgentStateResponse = await response.json();
423
+
424
+ return {
425
+ ...data,
426
+ state: JSON.stringify(data.state),
427
+ messages: JSON.stringify(data.messages),
428
+ };
429
+ } else {
430
+ throw new Error(`Unknown endpoint type: ${(agentWithEndpoint.endpoint as any).type}`);
431
+ }
432
+ }
433
+
351
434
  private async processAgentRequest(
352
435
  request: CopilotRuntimeRequest,
353
436
  ): Promise<CopilotRuntimeResponse> {
354
- const { messages: rawMessages, outputMessagesPromise, graphqlContext, agentSession } = request;
355
- const { threadId, agentName, nodeName } = agentSession;
437
+ const {
438
+ messages: rawMessages,
439
+ outputMessagesPromise,
440
+ graphqlContext,
441
+ agentSession,
442
+ threadId: threadIdFromRequest,
443
+ } = request;
444
+ const { agentName, nodeName } = agentSession;
445
+
446
+ // for backwards compatibility, deal with the case when no threadId is provided
447
+ const threadId = threadIdFromRequest ?? agentSession.threadId;
448
+
356
449
  const serverSideActions = await this.getServerSideActions(request);
357
450
 
358
451
  const messages = convertGqlInputToMessages(rawMessages);
@@ -1,5 +1,6 @@
1
1
  import { Client } from "@langchain/langgraph-sdk";
2
- import { createHash, randomUUID } from "node:crypto";
2
+ import { createHash } from "node:crypto";
3
+ import { randomUUID, isValidUUID } from "@copilotkit/shared";
3
4
  import { parse as parsePartialJson } from "partial-json";
4
5
  import { Logger } from "pino";
5
6
  import { ActionInput } from "../../graphql/inputs/action.input";
@@ -76,7 +77,7 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
76
77
  const {
77
78
  deploymentUrl,
78
79
  langsmithApiKey,
79
- threadId: agrsInitialThreadId,
80
+ threadId: argsInitialThreadId,
80
81
  agent,
81
82
  nodeName: initialNodeName,
82
83
  state: initialState,
@@ -90,26 +91,37 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
90
91
  const { name, assistantId: initialAssistantId } = agent;
91
92
 
92
93
  const client = new Client({ apiUrl: deploymentUrl, apiKey: langsmithApiKey });
93
- let initialThreadId = agrsInitialThreadId;
94
- const wasInitiatedWithExistingThread = !!initialThreadId;
95
- if (initialThreadId && initialThreadId.startsWith("ck-")) {
96
- initialThreadId = initialThreadId.substring(3);
94
+
95
+ let threadId = argsInitialThreadId ?? randomUUID();
96
+ if (argsInitialThreadId && argsInitialThreadId.startsWith("ck-")) {
97
+ threadId = argsInitialThreadId.substring(3);
98
+ }
99
+
100
+ if (!isValidUUID(threadId)) {
101
+ console.warn(
102
+ `Cannot use the threadId ${threadId} with LangGraph Platform. Must be a valid UUID.`,
103
+ );
97
104
  }
98
105
 
99
- const threadId = initialThreadId ?? randomUUID();
100
- if (initialThreadId === threadId) {
106
+ let wasInitiatedWithExistingThread = true;
107
+ try {
101
108
  await client.threads.get(threadId);
102
- } else {
103
- await client.threads.create({ threadId: threadId });
109
+ } catch (error) {
110
+ wasInitiatedWithExistingThread = false;
111
+ await client.threads.create({ threadId });
104
112
  }
105
113
 
106
114
  let agentState = { values: {} };
107
115
  if (wasInitiatedWithExistingThread) {
108
116
  agentState = await client.threads.getState(threadId);
109
117
  }
118
+
110
119
  const agentStateValues = agentState.values as State;
111
120
  state.messages = agentStateValues.messages;
112
- const mode = wasInitiatedWithExistingThread && nodeName != "__end__" ? "continue" : "start";
121
+ const mode =
122
+ threadId && nodeName != "__end__" && nodeName != undefined && nodeName != null
123
+ ? "continue"
124
+ : "start";
113
125
  let formattedMessages = [];
114
126
  try {
115
127
  formattedMessages = copilotkitMessagesToLangChain(messages);
@@ -483,7 +495,7 @@ function langGraphDefaultMergeState(
483
495
  };
484
496
  }
485
497
 
486
- function langchainMessagesToCopilotKit(messages: any[]): any[] {
498
+ export function langchainMessagesToCopilotKit(messages: any[]): any[] {
487
499
  const result: any[] = [];
488
500
  const tool_call_names: Record<string, string> = {};
489
501
 
@@ -29,8 +29,7 @@ import {
29
29
  limitMessagesToTokenCount,
30
30
  } from "./utils";
31
31
 
32
- import { randomId } from "@copilotkit/shared";
33
- import { TextMessage } from "../../graphql/types/converted";
32
+ import { randomId, randomUUID } from "@copilotkit/shared";
34
33
 
35
34
  const DEFAULT_MODEL = "claude-3-sonnet-20240229";
36
35
 
@@ -162,7 +161,7 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
162
161
  });
163
162
 
164
163
  return {
165
- threadId: threadId || randomId(),
164
+ threadId: threadId || randomUUID(),
166
165
  };
167
166
  }
168
167
  }
@@ -20,14 +20,14 @@ import {
20
20
  CopilotRuntimeChatCompletionRequest,
21
21
  CopilotRuntimeChatCompletionResponse,
22
22
  } from "../service-adapter";
23
- import { randomId } from "@copilotkit/shared";
23
+ import { randomUUID } from "@copilotkit/shared";
24
24
 
25
25
  export class EmptyAdapter implements CopilotServiceAdapter {
26
26
  async process(
27
27
  request: CopilotRuntimeChatCompletionRequest,
28
28
  ): Promise<CopilotRuntimeChatCompletionResponse> {
29
29
  return {
30
- threadId: request.threadId || randomId(),
30
+ threadId: request.threadId || randomUUID(),
31
31
  };
32
32
  }
33
33
  }
@@ -226,10 +226,12 @@ export class RuntimeEventSource {
226
226
  serverSideActions,
227
227
  guardrailsResult$,
228
228
  actionInputsWithoutAgents,
229
+ threadId,
229
230
  }: {
230
231
  serverSideActions: Action<any>[];
231
232
  guardrailsResult$?: Subject<GuardrailsResult>;
232
233
  actionInputsWithoutAgents: ActionInput[];
234
+ threadId: string;
233
235
  }) {
234
236
  this.callback(this.eventStream$).catch((error) => {
235
237
  console.error("Error in event source callback", error);
@@ -285,6 +287,7 @@ export class RuntimeEventSource {
285
287
  eventWithState.actionExecutionParentMessageId,
286
288
  eventWithState.actionExecutionId,
287
289
  actionInputsWithoutAgents,
290
+ threadId,
288
291
  ).catch((error) => {
289
292
  console.error(error);
290
293
  });
@@ -313,6 +316,7 @@ async function executeAction(
313
316
  actionExecutionParentMessageId: string | null,
314
317
  actionExecutionId: string,
315
318
  actionInputsWithoutAgents: ActionInput[],
319
+ threadId: string,
316
320
  ) {
317
321
  if (guardrailsResult$) {
318
322
  const { status } = await firstValueFrom(guardrailsResult$);
@@ -370,6 +374,7 @@ async function executeAction(
370
374
 
371
375
  const stream = await action.langGraphAgentHandler({
372
376
  name: action.name,
377
+ threadId,
373
378
  actionInputsWithoutAgents,
374
379
  additionalMessages: [agentExecution, agentExecutionResult],
375
380
  });
@@ -24,7 +24,7 @@ import {
24
24
  CopilotRuntimeChatCompletionResponse,
25
25
  } from "../../service-adapter";
26
26
  import { Ollama } from "@langchain/community/llms/ollama";
27
- import { randomId } from "@copilotkit/shared";
27
+ import { randomId, randomUUID } from "@copilotkit/shared";
28
28
 
29
29
  const DEFAULT_MODEL = "llama3:latest";
30
30
 
@@ -73,7 +73,7 @@ export class ExperimentalOllamaAdapter implements CopilotServiceAdapter {
73
73
  eventStream$.complete();
74
74
  });
75
75
  return {
76
- threadId: request.threadId || randomId(),
76
+ threadId: request.threadId || randomUUID(),
77
77
  };
78
78
  }
79
79
  }
@@ -25,7 +25,7 @@ import {
25
25
  convertMessageToOpenAIMessage,
26
26
  limitMessagesToTokenCount,
27
27
  } from "../openai/utils";
28
- import { randomId } from "@copilotkit/shared";
28
+ import { randomUUID } from "@copilotkit/shared";
29
29
 
30
30
  const DEFAULT_MODEL = "llama3-groq-70b-8192-tool-use-preview";
31
31
 
@@ -167,7 +167,7 @@ export class GroqAdapter implements CopilotServiceAdapter {
167
167
  });
168
168
 
169
169
  return {
170
- threadId: threadId || randomId(),
170
+ threadId: request.threadId || randomUUID(),
171
171
  };
172
172
  }
173
173
  }
@@ -44,7 +44,7 @@ import {
44
44
  } from "./utils";
45
45
  import { DynamicStructuredTool } from "@langchain/core/tools";
46
46
  import { LangChainReturnType } from "./types";
47
- import { randomId } from "@copilotkit/shared";
47
+ import { randomUUID } from "@copilotkit/shared";
48
48
  import { awaitAllCallbacks } from "@langchain/core/callbacks/promises";
49
49
 
50
50
  interface ChainFnParameters {
@@ -72,8 +72,15 @@ export class LangChainAdapter implements CopilotServiceAdapter {
72
72
  request: CopilotRuntimeChatCompletionRequest,
73
73
  ): Promise<CopilotRuntimeChatCompletionResponse> {
74
74
  try {
75
- const { eventSource, model, actions, messages, runId } = request;
76
- const threadId = request.threadId ?? randomId();
75
+ const {
76
+ eventSource,
77
+ model,
78
+ actions,
79
+ messages,
80
+ runId,
81
+ threadId: threadIdFromRequest,
82
+ } = request;
83
+ const threadId = threadIdFromRequest ?? randomUUID();
77
84
  const result = await this.options.chainFn({
78
85
  messages: messages.map(convertMessageToLangChainMessage),
79
86
  tools: actions.map(convertActionInputToLangChainTool),
@@ -59,7 +59,7 @@ import {
59
59
  convertMessageToOpenAIMessage,
60
60
  limitMessagesToTokenCount,
61
61
  } from "./utils";
62
- import { randomId } from "@copilotkit/shared";
62
+ import { randomUUID } from "@copilotkit/shared";
63
63
 
64
64
  const DEFAULT_MODEL = "gpt-4o";
65
65
 
@@ -107,7 +107,7 @@ export class OpenAIAdapter implements CopilotServiceAdapter {
107
107
  request: CopilotRuntimeChatCompletionRequest,
108
108
  ): Promise<CopilotRuntimeChatCompletionResponse> {
109
109
  const {
110
- threadId,
110
+ threadId: threadIdFromRequest,
111
111
  model = this.model,
112
112
  messages,
113
113
  actions,
@@ -115,6 +115,7 @@ export class OpenAIAdapter implements CopilotServiceAdapter {
115
115
  forwardedParameters,
116
116
  } = request;
117
117
  const tools = actions.map(convertActionInputToOpenAITool);
118
+ const threadId = threadIdFromRequest ?? randomUUID();
118
119
 
119
120
  let openaiMessages = messages.map(convertMessageToOpenAIMessage);
120
121
  openaiMessages = limitMessagesToTokenCount(openaiMessages, tools, model);
@@ -204,7 +205,7 @@ export class OpenAIAdapter implements CopilotServiceAdapter {
204
205
  });
205
206
 
206
207
  return {
207
- threadId: threadId || randomId(),
208
+ threadId,
208
209
  };
209
210
  }
210
211
  }