@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.
- package/.turbo/turbo-build.log +69 -54
- package/CHANGELOG.md +11 -0
- package/__snapshots__/schema/schema.graphql +15 -4
- package/dist/{chunk-NFCPM5AM.mjs → chunk-6NZ4UMOD.mjs} +4 -4
- package/dist/chunk-6NZ4UMOD.mjs.map +1 -0
- package/dist/{chunk-2CCVVJDU.mjs → chunk-6OJ47NCG.mjs} +13 -15
- package/dist/chunk-6OJ47NCG.mjs.map +1 -0
- package/dist/chunk-BYB2LNMK.mjs +152 -0
- package/dist/chunk-BYB2LNMK.mjs.map +1 -0
- package/dist/{chunk-XPAUPJMW.mjs → chunk-EWS5TMDA.mjs} +411 -206
- package/dist/chunk-EWS5TMDA.mjs.map +1 -0
- package/dist/{chunk-7IFP53C6.mjs → chunk-FRK6BXXV.mjs} +49 -11
- package/dist/chunk-FRK6BXXV.mjs.map +1 -0
- package/dist/{chunk-BLTAUVRP.mjs → chunk-OZMCHYYR.mjs} +5 -3
- package/dist/{chunk-BLTAUVRP.mjs.map → chunk-OZMCHYYR.mjs.map} +1 -1
- package/dist/chunk-RHQLCJGG.mjs +7 -0
- package/dist/chunk-RHQLCJGG.mjs.map +1 -0
- package/dist/{chunk-5HGYI6EG.mjs → chunk-XI3HBDMA.mjs} +13 -5
- package/dist/chunk-XI3HBDMA.mjs.map +1 -0
- package/dist/{chunk-4UA4RB4C.mjs → chunk-XXYCNRFT.mjs} +12 -10
- package/dist/chunk-XXYCNRFT.mjs.map +1 -0
- package/dist/failed-response-status-reasons-0ab19e06.d.ts +49 -0
- package/dist/graphql/types/base/index.mjs +2 -1
- package/dist/graphql/types/converted/index.mjs +3 -2
- package/dist/{index-f0875df3.d.ts → index-d5ba24be.d.ts} +24 -23
- package/dist/index.d.ts +7 -4
- package/dist/index.js +486 -96
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -7
- package/dist/index.mjs.map +1 -1
- package/dist/{langchain-adapter-9ce103f3.d.ts → langchain-adapter-54784d29.d.ts} +1 -1
- package/dist/{langserve-fd5066ee.d.ts → langserve-63794237.d.ts} +24 -7
- package/dist/lib/cloud/index.d.ts +6 -0
- package/dist/lib/cloud/index.js +18 -0
- package/dist/lib/cloud/index.js.map +1 -0
- package/dist/lib/cloud/index.mjs +1 -0
- package/dist/lib/cloud/index.mjs.map +1 -0
- package/dist/lib/index.d.ts +6 -4
- package/dist/lib/index.js +480 -96
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +9 -7
- package/dist/lib/integrations/index.d.ts +5 -3
- package/dist/lib/integrations/index.js +419 -80
- package/dist/lib/integrations/index.js.map +1 -1
- package/dist/lib/integrations/index.mjs +7 -5
- package/dist/lib/integrations/node-http/index.d.ts +4 -2
- package/dist/lib/integrations/node-http/index.js +409 -68
- package/dist/lib/integrations/node-http/index.js.map +1 -1
- package/dist/lib/integrations/node-http/index.mjs +6 -4
- package/dist/pages-router-d94f01da.d.ts +21 -0
- package/dist/service-adapters/index.d.ts +2 -2
- package/dist/service-adapters/index.js +54 -8
- package/dist/service-adapters/index.js.map +1 -1
- package/dist/service-adapters/index.mjs +5 -4
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +174 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +12 -0
- package/dist/utils/index.mjs.map +1 -0
- package/package.json +6 -4
- package/src/graphql/inputs/cloud-guardrails.input.ts +2 -5
- package/src/graphql/inputs/cloud.input.ts +2 -2
- package/src/graphql/resolvers/copilot.resolver.ts +269 -30
- package/src/graphql/types/response-status.type.ts +16 -2
- package/src/index.ts +1 -0
- package/src/lib/cloud/index.ts +4 -0
- package/src/lib/copilot-runtime.ts +13 -37
- package/src/lib/integrations/nextjs/app-router.ts +9 -17
- package/src/lib/integrations/nextjs/pages-router.ts +9 -15
- package/src/lib/integrations/node-http/index.ts +6 -14
- package/src/lib/integrations/shared.ts +37 -17
- package/src/lib/logger.ts +28 -0
- package/src/service-adapters/events.ts +20 -2
- package/src/service-adapters/google/google-genai-adapter.ts +3 -0
- package/src/service-adapters/google/utils.ts +1 -1
- package/src/service-adapters/index.ts +1 -1
- package/src/service-adapters/langchain/langserve.ts +10 -4
- package/src/service-adapters/langchain/utils.ts +58 -9
- package/src/utils/failed-response-status-reasons.ts +48 -0
- package/src/utils/index.ts +1 -0
- package/dist/chunk-2CCVVJDU.mjs.map +0 -1
- package/dist/chunk-4UA4RB4C.mjs.map +0 -1
- package/dist/chunk-5HGYI6EG.mjs.map +0 -1
- package/dist/chunk-7IFP53C6.mjs.map +0 -1
- package/dist/chunk-NFCPM5AM.mjs.map +0 -1
- package/dist/chunk-XPAUPJMW.mjs.map +0 -1
- package/dist/pages-router-b6bc6c60.d.ts +0 -30
- package/src/lib/guardrails.ts +0 -3
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { Arg, Ctx, Mutation, Query, Resolver } from "type-graphql";
|
|
2
|
-
import {
|
|
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 {
|
|
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
|
-
|
|
29
|
-
|
|
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
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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:
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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) =>
|
|
137
|
-
|
|
138
|
-
responseStatus
|
|
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(() =>
|
|
46
|
-
reason:
|
|
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
|
@@ -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?:
|
|
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
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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;
|