@copilotkit/runtime 0.37.0 → 0.38.0-mme-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/.turbo/turbo-build.log +69 -54
  2. package/CHANGELOG.md +11 -0
  3. package/__snapshots__/schema/schema.graphql +15 -4
  4. package/dist/{chunk-NFCPM5AM.mjs → chunk-6NZ4UMOD.mjs} +4 -4
  5. package/dist/chunk-6NZ4UMOD.mjs.map +1 -0
  6. package/dist/{chunk-2CCVVJDU.mjs → chunk-6OJ47NCG.mjs} +13 -15
  7. package/dist/chunk-6OJ47NCG.mjs.map +1 -0
  8. package/dist/chunk-BYB2LNMK.mjs +152 -0
  9. package/dist/chunk-BYB2LNMK.mjs.map +1 -0
  10. package/dist/{chunk-XPAUPJMW.mjs → chunk-EWS5TMDA.mjs} +411 -206
  11. package/dist/chunk-EWS5TMDA.mjs.map +1 -0
  12. package/dist/{chunk-7IFP53C6.mjs → chunk-FRK6BXXV.mjs} +49 -11
  13. package/dist/chunk-FRK6BXXV.mjs.map +1 -0
  14. package/dist/{chunk-BLTAUVRP.mjs → chunk-OZMCHYYR.mjs} +5 -3
  15. package/dist/{chunk-BLTAUVRP.mjs.map → chunk-OZMCHYYR.mjs.map} +1 -1
  16. package/dist/chunk-RHQLCJGG.mjs +7 -0
  17. package/dist/chunk-RHQLCJGG.mjs.map +1 -0
  18. package/dist/{chunk-5HGYI6EG.mjs → chunk-XI3HBDMA.mjs} +13 -5
  19. package/dist/chunk-XI3HBDMA.mjs.map +1 -0
  20. package/dist/{chunk-4UA4RB4C.mjs → chunk-XXYCNRFT.mjs} +12 -10
  21. package/dist/chunk-XXYCNRFT.mjs.map +1 -0
  22. package/dist/failed-response-status-reasons-0ab19e06.d.ts +49 -0
  23. package/dist/graphql/types/base/index.mjs +2 -1
  24. package/dist/graphql/types/converted/index.mjs +3 -2
  25. package/dist/{index-f0875df3.d.ts → index-d5ba24be.d.ts} +24 -23
  26. package/dist/index.d.ts +7 -4
  27. package/dist/index.js +486 -96
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +16 -7
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/{langchain-adapter-9ce103f3.d.ts → langchain-adapter-54784d29.d.ts} +1 -1
  32. package/dist/{langserve-fd5066ee.d.ts → langserve-63794237.d.ts} +24 -7
  33. package/dist/lib/cloud/index.d.ts +6 -0
  34. package/dist/lib/cloud/index.js +18 -0
  35. package/dist/lib/cloud/index.js.map +1 -0
  36. package/dist/lib/cloud/index.mjs +1 -0
  37. package/dist/lib/cloud/index.mjs.map +1 -0
  38. package/dist/lib/index.d.ts +6 -4
  39. package/dist/lib/index.js +480 -96
  40. package/dist/lib/index.js.map +1 -1
  41. package/dist/lib/index.mjs +9 -7
  42. package/dist/lib/integrations/index.d.ts +5 -3
  43. package/dist/lib/integrations/index.js +419 -80
  44. package/dist/lib/integrations/index.js.map +1 -1
  45. package/dist/lib/integrations/index.mjs +7 -5
  46. package/dist/lib/integrations/node-http/index.d.ts +4 -2
  47. package/dist/lib/integrations/node-http/index.js +409 -68
  48. package/dist/lib/integrations/node-http/index.js.map +1 -1
  49. package/dist/lib/integrations/node-http/index.mjs +6 -4
  50. package/dist/pages-router-d94f01da.d.ts +21 -0
  51. package/dist/service-adapters/index.d.ts +2 -2
  52. package/dist/service-adapters/index.js +54 -8
  53. package/dist/service-adapters/index.js.map +1 -1
  54. package/dist/service-adapters/index.mjs +5 -4
  55. package/dist/utils/index.d.ts +1 -0
  56. package/dist/utils/index.js +174 -0
  57. package/dist/utils/index.js.map +1 -0
  58. package/dist/utils/index.mjs +12 -0
  59. package/dist/utils/index.mjs.map +1 -0
  60. package/package.json +6 -4
  61. package/src/graphql/inputs/cloud-guardrails.input.ts +2 -5
  62. package/src/graphql/inputs/cloud.input.ts +2 -2
  63. package/src/graphql/resolvers/copilot.resolver.ts +269 -30
  64. package/src/graphql/types/response-status.type.ts +16 -2
  65. package/src/index.ts +1 -0
  66. package/src/lib/cloud/index.ts +4 -0
  67. package/src/lib/copilot-runtime.ts +13 -37
  68. package/src/lib/integrations/nextjs/app-router.ts +9 -17
  69. package/src/lib/integrations/nextjs/pages-router.ts +9 -15
  70. package/src/lib/integrations/node-http/index.ts +6 -14
  71. package/src/lib/integrations/shared.ts +37 -17
  72. package/src/lib/logger.ts +28 -0
  73. package/src/service-adapters/events.ts +20 -2
  74. package/src/service-adapters/google/google-genai-adapter.ts +3 -0
  75. package/src/service-adapters/google/utils.ts +1 -1
  76. package/src/service-adapters/index.ts +1 -1
  77. package/src/service-adapters/langchain/langserve.ts +10 -4
  78. package/src/service-adapters/langchain/utils.ts +58 -9
  79. package/src/utils/failed-response-status-reasons.ts +48 -0
  80. package/src/utils/index.ts +1 -0
  81. package/dist/chunk-2CCVVJDU.mjs.map +0 -1
  82. package/dist/chunk-4UA4RB4C.mjs.map +0 -1
  83. package/dist/chunk-5HGYI6EG.mjs.map +0 -1
  84. package/dist/chunk-7IFP53C6.mjs.map +0 -1
  85. package/dist/chunk-NFCPM5AM.mjs.map +0 -1
  86. package/dist/chunk-XPAUPJMW.mjs.map +0 -1
  87. package/dist/pages-router-b6bc6c60.d.ts +0 -30
  88. package/src/lib/guardrails.ts +0 -3
@@ -1,5 +1,16 @@
1
1
  import { Arg, Ctx, Mutation, Query, Resolver } from "type-graphql";
2
- import { Subject, firstValueFrom, shareReplay, skipWhile, takeWhile } from "rxjs";
2
+ import {
3
+ ReplaySubject,
4
+ Subject,
5
+ Subscription,
6
+ finalize,
7
+ firstValueFrom,
8
+ shareReplay,
9
+ skipWhile,
10
+ take,
11
+ takeWhile,
12
+ tap,
13
+ } from "rxjs";
3
14
  import { GenerateCopilotResponseInput } from "../inputs/generate-copilot-response.input";
4
15
  import { CopilotResponse } from "../types/copilot-response.type";
5
16
  import { MessageRole } from "../types/enums";
@@ -7,9 +18,82 @@ import { Repeater } from "graphql-yoga";
7
18
  import type { CopilotRequestContextProperties, GraphQLContext } from "../../lib/integrations";
8
19
  import { nanoid } from "nanoid";
9
20
  import { RuntimeEvent, RuntimeEventTypes } from "../../service-adapters/events";
10
- import { MessageStatusUnion, SuccessMessageStatus } from "../types/message-status.type";
21
+ import {
22
+ FailedMessageStatus,
23
+ MessageStatusUnion,
24
+ SuccessMessageStatus,
25
+ } from "../types/message-status.type";
11
26
  import { ResponseStatusUnion, SuccessResponseStatus } from "../types/response-status.type";
12
27
  import { GraphQLJSONObject } from "graphql-scalars";
28
+ import { plainToInstance } from "class-transformer";
29
+ import { GuardrailsResult, GuardrailsResultStatus } from "../types/guardrails-result.type";
30
+ import { GraphQLError } from "graphql";
31
+ import {
32
+ GuardrailsValidationFailureResponse,
33
+ MessageStreamInterruptedResponse,
34
+ UnknownErrorResponse,
35
+ } from "../../utils";
36
+ import { CopilotRuntimeLogger } from "../../lib/logger";
37
+
38
+ const invokeGuardrails = async ({
39
+ baseUrl,
40
+ copilotCloudPublicApiKey,
41
+ data,
42
+ logger,
43
+ onResult,
44
+ }: {
45
+ baseUrl: string;
46
+ copilotCloudPublicApiKey: string;
47
+ data: GenerateCopilotResponseInput;
48
+ logger: CopilotRuntimeLogger;
49
+ onResult: (result: GuardrailsResult) => void;
50
+ }) => {
51
+ if (
52
+ data.messages.length &&
53
+ data.messages[data.messages.length - 1].textMessage?.role === MessageRole.user
54
+ ) {
55
+ const messages = data.messages
56
+ .filter(
57
+ (m) =>
58
+ m.textMessage !== undefined &&
59
+ (m.textMessage.role === MessageRole.user || m.textMessage.role === MessageRole.assistant),
60
+ )
61
+ .map((m) => ({
62
+ role: m.textMessage!.role,
63
+ content: m.textMessage.content,
64
+ }));
65
+
66
+ const lastMessage = messages[messages.length - 1];
67
+ const restOfMessages = messages.slice(0, -1);
68
+
69
+ const body = {
70
+ input: lastMessage.content,
71
+ validTopics: data.cloud.guardrails.inputValidationRules.allowList,
72
+ invalidTopics: data.cloud.guardrails.inputValidationRules.denyList,
73
+ messages: restOfMessages,
74
+ };
75
+
76
+ const guardrailsResult = await fetch(`${baseUrl}/guardrails/validate`, {
77
+ method: "POST",
78
+ headers: {
79
+ "Content-Type": "application/json",
80
+ "X-CopilotCloud-Public-API-Key": copilotCloudPublicApiKey,
81
+ },
82
+ body: JSON.stringify(body),
83
+ });
84
+
85
+ const responseBody = await guardrailsResult.json();
86
+
87
+ if (!guardrailsResult.ok) {
88
+ logger.error({ error: responseBody }, "Failed to invoke guardrails");
89
+ throw new GraphQLError("Failed to invoke guardrails");
90
+ }
91
+
92
+ onResult(responseBody);
93
+ } else {
94
+ onResult({ status: GuardrailsResultStatus.ALLOWED });
95
+ }
96
+ };
13
97
 
14
98
  @Resolver(() => CopilotResponse)
15
99
  export class CopilotResolver {
@@ -25,17 +109,53 @@ export class CopilotResolver {
25
109
  @Arg("properties", () => GraphQLJSONObject, { nullable: true })
26
110
  properties?: CopilotRequestContextProperties,
27
111
  ) {
28
- if (properties) {
29
- ctx._copilotkit.properties = { ...ctx._copilotkit.properties, ...properties };
30
- }
112
+ let logger = ctx.logger.child({ component: "CopilotResolver.generateCopilotResponse" });
113
+ logger.debug({ data }, "Generating Copilot response");
114
+
31
115
  const copilotRuntime = ctx._copilotkit.runtime;
32
116
  const serviceAdapter = ctx._copilotkit.serviceAdapter;
33
- const responseStatus = new Subject<typeof ResponseStatusUnion>();
34
117
 
118
+ if (properties) {
119
+ logger.debug("Properties provided, merging with context properties");
120
+ ctx.properties = { ...ctx.properties, ...properties };
121
+ }
122
+
123
+ let copilotCloudPublicApiKey: string | null = null;
124
+ let copilotCloudBaseUrl: string;
125
+
126
+ if (data.cloud) {
127
+ logger = logger.child({ cloud: true });
128
+ logger.debug("Cloud configuration provided, checking for public API key in headers");
129
+ const key = ctx.request.headers.get("x-copilotcloud-public-api-key");
130
+ if (key) {
131
+ logger.debug("Public API key found in headers");
132
+ copilotCloudPublicApiKey = key;
133
+ } else {
134
+ logger.error("Public API key not found in headers");
135
+ throw new GraphQLError("X-CopilotCloud-Public-API-Key header is required");
136
+ }
137
+
138
+ if (process.env.COPILOT_CLOUD_BASE_URL) {
139
+ copilotCloudBaseUrl = process.env.COPILOT_CLOUD_BASE_URL;
140
+ } else if (ctx._copilotkit.baseUrl) {
141
+ copilotCloudBaseUrl = ctx._copilotkit.baseUrl;
142
+ } else {
143
+ copilotCloudBaseUrl = "https://api.cloud.copilotkit.ai";
144
+ }
145
+
146
+ logger = logger.child({ copilotCloudBaseUrl });
147
+ }
148
+ logger.debug("Setting up subjects");
149
+ const responseStatus$ = new ReplaySubject<typeof ResponseStatusUnion>();
150
+ const interruptStreaming$ = new ReplaySubject<{ reason: string; messageId?: string }>();
151
+ const guardrailsResult$ = new ReplaySubject<GuardrailsResult>();
152
+
153
+ logger.debug("Processing");
35
154
  const {
36
155
  eventSource,
37
156
  threadId = nanoid(),
38
157
  runId,
158
+ actions,
39
159
  } = await copilotRuntime.process({
40
160
  serviceAdapter,
41
161
  messages: data.messages,
@@ -45,18 +165,60 @@ export class CopilotResolver {
45
165
  publicApiKey: undefined,
46
166
  });
47
167
 
168
+ logger.debug("Event source created, creating response");
169
+
48
170
  const response = {
49
171
  threadId,
50
172
  runId,
51
- status: firstValueFrom(responseStatus),
173
+ status: firstValueFrom(responseStatus$),
52
174
  messages: new Repeater(async (pushMessage, stopStreamingMessages) => {
175
+ logger.debug("Messages repeater created");
176
+
177
+ if (data.cloud?.guardrails) {
178
+ logger = logger.child({ guardrails: true });
179
+ logger.debug("Guardrails is enabled, validating input");
180
+
181
+ invokeGuardrails({
182
+ baseUrl: copilotCloudBaseUrl,
183
+ copilotCloudPublicApiKey,
184
+ data,
185
+ logger,
186
+ onResult: (result) => {
187
+ logger.debug({ status: result.status }, "Guardrails validation done");
188
+ guardrailsResult$.next(result);
189
+ if (result.status === "denied") {
190
+ responseStatus$.next(
191
+ new GuardrailsValidationFailureResponse({ guardrailsReason: result.reason }),
192
+ );
193
+ interruptStreaming$.next({
194
+ reason: `Interrupted due to Guardrails validation failure. Reason: ${result.reason}`,
195
+ });
196
+ }
197
+ },
198
+ });
199
+ }
200
+
201
+ let eventStreamSubscription: Subscription;
202
+
53
203
  // run and process the event stream
54
- const eventStream = eventSource.process(copilotRuntime.actions).pipe(
55
- // shareReplay() ensures that later subscribers will see the whole stream instead of
56
- // just the events that were emitted after the subscriber was added.
57
- shareReplay(),
58
- );
59
- eventStream.subscribe({
204
+ const eventStream = eventSource
205
+ .process({
206
+ serversideActions: copilotRuntime.actions,
207
+ guardrailsResult$: data.cloud?.guardrails ? guardrailsResult$ : null,
208
+ })
209
+ .pipe(
210
+ // shareReplay() ensures that later subscribers will see the whole stream instead of
211
+ // just the events that were emitted after the subscriber was added.
212
+ shareReplay(),
213
+ finalize(() => {
214
+ logger.debug("Event stream finalized, stopping streaming messages");
215
+ stopStreamingMessages();
216
+ }),
217
+ );
218
+
219
+ logger.debug("Event stream created, subscribing to event stream");
220
+
221
+ eventStreamSubscription = eventStream.subscribe({
60
222
  next: async (event) => {
61
223
  switch (event.type) {
62
224
  ////////////////////////////////
@@ -74,21 +236,61 @@ export class CopilotResolver {
74
236
  // signal when we are done streaming
75
237
  const streamingTextStatus = new Subject<typeof MessageStatusUnion>();
76
238
 
239
+ const messageId = nanoid();
240
+
77
241
  // push the new message
78
242
  pushMessage({
79
- id: nanoid(),
243
+ id: messageId,
80
244
  status: firstValueFrom(streamingTextStatus),
81
245
  createdAt: new Date(),
82
246
  role: MessageRole.assistant,
83
247
  content: new Repeater(async (pushTextChunk, stopStreamingText) => {
84
- // push the message content
85
- await textMessageContentStream.forEach(async (e: RuntimeEvent) => {
86
- if (e.type == RuntimeEventTypes.TextMessageContent) {
87
- await pushTextChunk(e.content);
88
- }
248
+ logger.debug("Text message content repeater created");
249
+
250
+ let textSubscription: Subscription;
251
+
252
+ interruptStreaming$
253
+ .pipe(
254
+ shareReplay(),
255
+ take(1),
256
+ tap(({ reason, messageId }) => {
257
+ logger.debug({ reason, messageId }, "Text streaming interrupted");
258
+
259
+ streamingTextStatus.next(
260
+ plainToInstance(FailedMessageStatus, { reason }),
261
+ );
262
+
263
+ responseStatus$.next(new MessageStreamInterruptedResponse({ messageId }));
264
+ stopStreamingText();
265
+ textSubscription.unsubscribe();
266
+ }),
267
+ )
268
+ .subscribe();
269
+
270
+ logger.debug("Subscribing to text message content stream");
271
+
272
+ textSubscription = textMessageContentStream.subscribe({
273
+ next: async (e: RuntimeEvent) => {
274
+ if (e.type == RuntimeEventTypes.TextMessageContent) {
275
+ await pushTextChunk(e.content);
276
+ }
277
+ },
278
+ error: (err) => {
279
+ logger.error({ err }, "Error in text message content stream");
280
+ interruptStreaming$.next({
281
+ reason: "Error streaming message content",
282
+ messageId,
283
+ });
284
+ stopStreamingText();
285
+ textSubscription.unsubscribe();
286
+ },
287
+ complete: () => {
288
+ logger.debug("Text message content stream completed");
289
+ streamingTextStatus.next(new SuccessMessageStatus());
290
+ stopStreamingText();
291
+ textSubscription.unsubscribe();
292
+ },
89
293
  });
90
- stopStreamingText();
91
- streamingTextStatus.next(new SuccessMessageStatus());
92
294
  }),
93
295
  });
94
296
  break;
@@ -96,6 +298,7 @@ export class CopilotResolver {
96
298
  // ActionExecutionStart
97
299
  ////////////////////////////////
98
300
  case RuntimeEventTypes.ActionExecutionStart:
301
+ logger.debug("Action execution start event received");
99
302
  const actionExecutionArgumentStream = eventStream.pipe(
100
303
  skipWhile((e) => e !== event),
101
304
  takeWhile((e) => e.type != RuntimeEventTypes.ActionExecutionEnd),
@@ -108,13 +311,33 @@ export class CopilotResolver {
108
311
  name: event.actionName,
109
312
  scope: event.scope!,
110
313
  arguments: new Repeater(async (pushArgumentsChunk, stopStreamingArguments) => {
111
- await actionExecutionArgumentStream.forEach(async (e: RuntimeEvent) => {
112
- if (e.type == RuntimeEventTypes.ActionExecutionArgs) {
113
- await pushArgumentsChunk(e.args);
114
- }
314
+ logger.debug("Action execution argument stream created");
315
+
316
+ let actionExecutionArgumentSubscription: Subscription;
317
+ actionExecutionArgumentSubscription = actionExecutionArgumentStream.subscribe({
318
+ next: async (e: RuntimeEvent) => {
319
+ if (e.type == RuntimeEventTypes.ActionExecutionArgs) {
320
+ await pushArgumentsChunk(e.args);
321
+ }
322
+ },
323
+ error: (err) => {
324
+ logger.error({ err }, "Error in action execution argument stream");
325
+ streamingArgumentsStatus.next(
326
+ plainToInstance(FailedMessageStatus, {
327
+ reason:
328
+ "An unknown error has occurred in the action execution argument stream",
329
+ }),
330
+ );
331
+ stopStreamingArguments();
332
+ actionExecutionArgumentSubscription.unsubscribe();
333
+ },
334
+ complete: () => {
335
+ logger.debug("Action execution argument stream completed");
336
+ streamingArgumentsStatus.next(new SuccessMessageStatus());
337
+ stopStreamingArguments();
338
+ actionExecutionArgumentSubscription.unsubscribe();
339
+ },
115
340
  });
116
- stopStreamingArguments();
117
- streamingArgumentsStatus.next(new SuccessMessageStatus());
118
341
  }),
119
342
  });
120
343
  break;
@@ -122,6 +345,7 @@ export class CopilotResolver {
122
345
  // ActionExecutionResult
123
346
  ////////////////////////////////
124
347
  case RuntimeEventTypes.ActionExecutionResult:
348
+ logger.debug("Action execution result event received");
125
349
  pushMessage({
126
350
  id: nanoid(),
127
351
  status: new SuccessMessageStatus(),
@@ -133,9 +357,24 @@ export class CopilotResolver {
133
357
  break;
134
358
  }
135
359
  },
136
- error: (err) => console.error("Error in event source", err),
137
- complete: () => {
138
- responseStatus.next(new SuccessResponseStatus());
360
+ error: (err) => {
361
+ logger.error({ err }, "Error in event stream");
362
+ responseStatus$.next(
363
+ new UnknownErrorResponse({
364
+ description: `An unknown error has occurred in the event stream`,
365
+ }),
366
+ );
367
+ eventStreamSubscription.unsubscribe();
368
+ stopStreamingMessages();
369
+ },
370
+ complete: async () => {
371
+ logger.debug("Event stream completed");
372
+ if (data.cloud?.guardrails) {
373
+ logger.debug("Guardrails is enabled, waiting for guardrails result");
374
+ await firstValueFrom(guardrailsResult$);
375
+ }
376
+ responseStatus$.next(new SuccessResponseStatus());
377
+ eventStreamSubscription.unsubscribe();
139
378
  stopStreamingMessages();
140
379
  },
141
380
  });
@@ -1,3 +1,4 @@
1
+ import { GraphQLJSON } from "graphql-scalars";
1
2
  import { Field, InterfaceType, ObjectType, createUnionType, registerEnumType } from "type-graphql";
2
3
 
3
4
  export enum ResponseStatusCode {
@@ -38,12 +39,25 @@ export class SuccessResponseStatus extends BaseResponseStatus {
38
39
  code: ResponseStatusCode = ResponseStatusCode.Success;
39
40
  }
40
41
 
42
+ export enum FailedResponseStatusReason {
43
+ GUARDRAILS_VALIDATION_FAILED = "GUARDRAILS_VALIDATION_FAILED",
44
+ MESSAGE_STREAM_INTERRUPTED = "MESSAGE_STREAM_INTERRUPTED",
45
+ UNKNOWN_ERROR = "UNKNOWN_ERROR",
46
+ }
47
+
48
+ registerEnumType(FailedResponseStatusReason, {
49
+ name: "FailedResponseStatusReason",
50
+ });
51
+
41
52
  @ObjectType({ implements: BaseResponseStatus })
42
53
  export class FailedResponseStatus extends BaseResponseStatus {
43
54
  code: ResponseStatusCode = ResponseStatusCode.Failed;
44
55
 
45
- @Field(() => String)
46
- reason: string;
56
+ @Field(() => FailedResponseStatusReason)
57
+ reason: FailedResponseStatusReason;
58
+
59
+ @Field(() => GraphQLJSON, { nullable: true })
60
+ details?: Record<string, any> = null;
47
61
  }
48
62
 
49
63
  export const ResponseStatusUnion = createUnionType({
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  import "reflect-metadata";
2
2
  export * from "./lib";
3
+ export * from "./utils";
@@ -0,0 +1,4 @@
1
+ export interface CopilotCloudOptions {
2
+ baseUrl?: string;
3
+ publicApiKey?: string;
4
+ }
@@ -99,7 +99,7 @@
99
99
  */
100
100
 
101
101
  import { Action, actionParametersToJsonSchema, Parameter } from "@copilotkit/shared";
102
- import { RemoteChain, CopilotServiceAdapter } from "../service-adapters";
102
+ import { RemoteChain, RemoteChainParameters, CopilotServiceAdapter } from "../service-adapters";
103
103
  import { CopilotCloud, RemoteCopilotCloud } from "./copilot-cloud";
104
104
  import { MessageInput } from "../graphql/inputs/message.input";
105
105
  import { ActionInput } from "../graphql/inputs/action.input";
@@ -119,6 +119,7 @@ interface CopilotRuntimeResponse {
119
119
  threadId?: string;
120
120
  runId?: string;
121
121
  eventSource: RuntimeEventSource;
122
+ actions: Action<any>[];
122
123
  }
123
124
 
124
125
  export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []> {
@@ -130,7 +131,7 @@ export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []
130
131
  /*
131
132
  * An array of LangServer URLs.
132
133
  */
133
- langserve?: RemoteChain[];
134
+ langserve?: RemoteChainParameters[];
134
135
 
135
136
  debug?: boolean;
136
137
  copilotCloud?: CopilotCloud;
@@ -170,9 +171,6 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
170
171
  runId,
171
172
  publicApiKey,
172
173
  }: CopilotRuntimeRequest): Promise<CopilotRuntimeResponse> {
173
- // TODO-PROTOCOL: cloud configuration
174
- // const cloud: CopilotCloudConfig = forwardedProps.cloud;
175
-
176
174
  const langserveFunctions: Action<any>[] = [];
177
175
 
178
176
  for (const chainPromise of this.langserve) {
@@ -184,15 +182,15 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
184
182
  }
185
183
  }
186
184
 
187
- const serverSideActionsInput: ActionInput[] = [...this.actions, ...langserveFunctions].map(
188
- (action) => ({
189
- name: action.name,
190
- description: action.description,
191
- jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters)),
192
- }),
193
- );
185
+ const actions = [...this.actions, ...langserveFunctions];
186
+
187
+ const serverSideActionsInput: ActionInput[] = actions.map((action) => ({
188
+ name: action.name,
189
+ description: action.description,
190
+ jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters)),
191
+ }));
194
192
 
195
- const actions = flattenToolCallsNoDuplicates([
193
+ const actionInputs = flattenToolCallsNoDuplicates([
196
194
  ...serverSideActionsInput,
197
195
  ...clientSideActionsInput,
198
196
  ]);
@@ -202,39 +200,17 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
202
200
  // TODO-PROTOCOL: type this and support function calls
203
201
  const result = await serviceAdapter.process({
204
202
  messages: convertGqlInputToMessages(messages),
205
- actions,
203
+ actions: actionInputs,
206
204
  threadId,
207
205
  runId,
208
206
  eventSource,
209
207
  });
210
208
 
211
- // TODO-PROTOCOL add guardrails
212
- //
213
- // if (publicApiKey !== undefined) {
214
- // // wait for the cloud log chat to finish before streaming back the response
215
- // try {
216
- // const checkGuardrailsInputResult = await this.copilotCloud.checkGuardrailsInput({
217
- // cloud,
218
- // publicApiKey,
219
- // messages: forwardedProps.messages || [],
220
- // });
221
-
222
- // if (checkGuardrailsInputResult.status === "denied") {
223
- // // the chat was denied. instead of streaming back the response,
224
- // // we let the client know...
225
- // return {
226
- // stream: new SingleChunkReadableStream(checkGuardrailsInputResult.reason),
227
- // // headers: result.headers,
228
- // };
229
- // }
230
- // } catch (error) {
231
- // console.error("Error checking guardrails:", error);
232
- // }
233
- // }
234
209
  return {
235
210
  threadId: result.threadId,
236
211
  runId: result.runId,
237
212
  eventSource,
213
+ actions,
238
214
  };
239
215
  } catch (error) {
240
216
  console.error("Error getting response:", error);
@@ -1,29 +1,21 @@
1
1
  import { createYoga } from "graphql-yoga";
2
- import { getCommonConfig } from "../shared";
3
- import { CopilotRuntime } from "../../copilot-runtime";
4
- import { CopilotServiceAdapter } from "../../../service-adapters";
2
+ import { CreateCopilotRuntimeServerOptions, getCommonConfig } from "../shared";
5
3
 
6
- export function copilotRuntimeNextJSAppRouterEndpoint({
7
- runtime,
8
- endpoint,
9
- serviceAdapter,
10
- }: {
11
- runtime: CopilotRuntime;
12
- serviceAdapter: CopilotServiceAdapter;
13
- endpoint: string;
14
- }) {
15
- const commonConfig = getCommonConfig({ runtime, serviceAdapter });
4
+ export function copilotRuntimeNextJSAppRouterEndpoint(options: CreateCopilotRuntimeServerOptions) {
5
+ const commonConfig = getCommonConfig(options);
6
+ const logger = commonConfig.logging;
7
+ logger.debug("Creating NextJS App Router endpoint");
16
8
 
17
9
  const yoga = createYoga({
18
10
  ...commonConfig,
19
- graphqlEndpoint: endpoint,
11
+ graphqlEndpoint: options.endpoint,
20
12
  fetchAPI: { Response: globalThis.Response },
21
13
  });
22
14
 
23
15
  return {
24
16
  handleRequest: yoga,
25
- GET: yoga,
26
- POST: yoga,
27
- OPTIONS: yoga,
17
+ GET: yoga as any,
18
+ POST: yoga as any,
19
+ OPTIONS: yoga as any,
28
20
  };
29
21
  }
@@ -1,7 +1,5 @@
1
1
  import { YogaServerInstance, createYoga } from "graphql-yoga";
2
- import { GraphQLContext, getCommonConfig } from "../shared";
3
- import { CopilotRuntime } from "../../copilot-runtime";
4
- import { CopilotServiceAdapter } from "../../../service-adapters";
2
+ import { CreateCopilotRuntimeServerOptions, GraphQLContext, getCommonConfig } from "../shared";
5
3
 
6
4
  export const config = {
7
5
  api: {
@@ -11,25 +9,21 @@ export const config = {
11
9
 
12
10
  export type CopilotRuntimeServerInstance<T> = YogaServerInstance<T, Partial<GraphQLContext>>;
13
11
 
14
- // Theis import is needed to fix the type error
12
+ // This import is needed to fix the type error
15
13
  // Fix is currently in TypeScript 5.5 beta, waiting for stable version
16
14
  // https://github.com/microsoft/TypeScript/issues/42873#issuecomment-2066874644
17
15
  export type {} from "@whatwg-node/server";
18
16
 
19
- export function copilotRuntimeNextJSPagesRouterEndpoint({
20
- runtime,
21
- endpoint,
22
- serviceAdapter,
23
- }: {
24
- runtime: CopilotRuntime;
25
- serviceAdapter: CopilotServiceAdapter;
26
- endpoint: string;
27
- }): CopilotRuntimeServerInstance<GraphQLContext> {
28
- const commonConfig = getCommonConfig({ runtime, serviceAdapter });
17
+ export function copilotRuntimeNextJSPagesRouterEndpoint(
18
+ options: CreateCopilotRuntimeServerOptions,
19
+ ): CopilotRuntimeServerInstance<GraphQLContext> {
20
+ const commonConfig = getCommonConfig(options);
21
+ const logger = commonConfig.logging;
22
+ logger.debug("Creating NextJS Pages Router endpoint");
29
23
 
30
24
  const yoga = createYoga({
31
25
  ...commonConfig,
32
- graphqlEndpoint: endpoint,
26
+ graphqlEndpoint: options.endpoint,
33
27
  });
34
28
 
35
29
  return yoga;
@@ -1,22 +1,14 @@
1
1
  import { createYoga } from "graphql-yoga";
2
- import { getCommonConfig } from "../shared";
3
- import { CopilotRuntime } from "../../copilot-runtime";
4
- import { CopilotServiceAdapter } from "../../../service-adapters";
2
+ import { CreateCopilotRuntimeServerOptions, getCommonConfig } from "../shared";
5
3
 
6
- export function copilotRuntimeNodeHttpEndpoint({
7
- runtime,
8
- endpoint,
9
- serviceAdapter,
10
- }: {
11
- runtime: CopilotRuntime;
12
- serviceAdapter: CopilotServiceAdapter;
13
- endpoint: string;
14
- }) {
15
- const commonConfig = getCommonConfig({ runtime, serviceAdapter });
4
+ export function copilotRuntimeNodeHttpEndpoint(options: CreateCopilotRuntimeServerOptions) {
5
+ const commonConfig = getCommonConfig(options);
6
+ const logger = commonConfig.logging;
7
+ logger.debug("Creating Node HTTP endpoint");
16
8
 
17
9
  const yoga = createYoga({
18
10
  ...commonConfig,
19
- graphqlEndpoint: endpoint,
11
+ graphqlEndpoint: options.endpoint,
20
12
  });
21
13
 
22
14
  return yoga;