@copilotkit/runtime 1.9.2-next.9 → 1.9.3-next.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/CHANGELOG.md +176 -0
- package/dist/{chunk-Z5GYTKMD.mjs → chunk-EK5RTZVJ.mjs} +225 -149
- package/dist/chunk-EK5RTZVJ.mjs.map +1 -0
- package/dist/{chunk-SMDVD4VG.mjs → chunk-KCYFFRJY.mjs} +2 -2
- package/dist/{chunk-4JBKY7XT.mjs → chunk-QLLV2QVK.mjs} +48 -28
- package/dist/chunk-QLLV2QVK.mjs.map +1 -0
- package/dist/{chunk-5YGKE5SN.mjs → chunk-R5D7D7YN.mjs} +2 -2
- package/dist/{chunk-UUXRYAB4.mjs → chunk-RCCT2GOF.mjs} +2 -2
- package/dist/{chunk-ALZ5H3VD.mjs → chunk-YGS5B7PN.mjs} +2 -2
- package/dist/{groq-adapter-172a2ca4.d.ts → groq-adapter-742818f2.d.ts} +5 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +267 -171
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9 -9
- package/dist/{langserve-fc5cac89.d.ts → langserve-3e8d0e06.d.ts} +6 -0
- package/dist/lib/index.d.ts +155 -5
- package/dist/lib/index.js +221 -168
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +9 -9
- package/dist/lib/integrations/index.d.ts +3 -3
- package/dist/lib/integrations/index.js +11 -11
- package/dist/lib/integrations/index.js.map +1 -1
- package/dist/lib/integrations/index.mjs +8 -8
- package/dist/lib/integrations/nest/index.d.ts +2 -2
- package/dist/lib/integrations/nest/index.js +11 -11
- package/dist/lib/integrations/nest/index.js.map +1 -1
- package/dist/lib/integrations/nest/index.mjs +4 -4
- package/dist/lib/integrations/node-express/index.d.ts +2 -2
- package/dist/lib/integrations/node-express/index.js +11 -11
- package/dist/lib/integrations/node-express/index.js.map +1 -1
- package/dist/lib/integrations/node-express/index.mjs +4 -4
- package/dist/lib/integrations/node-http/index.d.ts +2 -2
- package/dist/lib/integrations/node-http/index.js +11 -11
- package/dist/lib/integrations/node-http/index.js.map +1 -1
- package/dist/lib/integrations/node-http/index.mjs +3 -3
- package/dist/service-adapters/index.d.ts +5 -4
- package/dist/service-adapters/index.js +47 -27
- package/dist/service-adapters/index.js.map +1 -1
- package/dist/service-adapters/index.mjs +1 -1
- package/dist/{shared-bd953ebf.d.ts → shared-96b46379.d.ts} +16 -18
- package/package.json +11 -11
- package/src/graphql/resolvers/copilot.resolver.ts +1 -2
- package/src/lib/runtime/__tests__/{copilot-runtime-trace.test.ts → copilot-runtime-error.test.ts} +27 -27
- package/src/lib/runtime/__tests__/mcp-tools-utils.test.ts +464 -0
- package/src/lib/runtime/agui-action.ts +9 -3
- package/src/lib/runtime/copilot-runtime.ts +112 -124
- package/src/lib/runtime/mcp-tools-utils.ts +84 -18
- package/src/lib/runtime/remote-actions.ts +6 -0
- package/src/service-adapters/anthropic/anthropic-adapter.ts +64 -4
- package/src/service-adapters/anthropic/utils.ts +3 -8
- package/src/service-adapters/events.ts +40 -1
- package/src/service-adapters/google/google-genai-adapter.ts +5 -0
- package/src/service-adapters/openai/openai-adapter.ts +0 -14
- package/tests/service-adapters/anthropic/anthropic-adapter.test.ts +172 -387
- package/dist/chunk-4JBKY7XT.mjs.map +0 -1
- package/dist/chunk-Z5GYTKMD.mjs.map +0 -1
- /package/dist/{chunk-SMDVD4VG.mjs.map → chunk-KCYFFRJY.mjs.map} +0 -0
- /package/dist/{chunk-5YGKE5SN.mjs.map → chunk-R5D7D7YN.mjs.map} +0 -0
- /package/dist/{chunk-UUXRYAB4.mjs.map → chunk-RCCT2GOF.mjs.map} +0 -0
- /package/dist/{chunk-ALZ5H3VD.mjs.map → chunk-YGS5B7PN.mjs.map} +0 -0
|
@@ -20,13 +20,12 @@ import {
|
|
|
20
20
|
CopilotKitApiDiscoveryError,
|
|
21
21
|
randomId,
|
|
22
22
|
CopilotKitError,
|
|
23
|
-
CopilotKitRemoteEndpointDiscoveryError,
|
|
24
23
|
CopilotKitAgentDiscoveryError,
|
|
25
24
|
CopilotKitMisuseError,
|
|
26
25
|
CopilotKitErrorCode,
|
|
27
26
|
CopilotKitLowLevelError,
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
CopilotErrorHandler,
|
|
28
|
+
CopilotErrorEvent,
|
|
30
29
|
CopilotRequestContext,
|
|
31
30
|
ensureStructuredError,
|
|
32
31
|
} from "@copilotkit/shared";
|
|
@@ -66,7 +65,7 @@ import { ExtensionsInput } from "../../graphql/inputs/extensions.input";
|
|
|
66
65
|
import { ExtensionsResponse } from "../../graphql/types/extensions-response.type";
|
|
67
66
|
import { LoadAgentStateResponse } from "../../graphql/types/load-agent-state-response.type";
|
|
68
67
|
import { Client as LangGraphClient } from "@langchain/langgraph-sdk";
|
|
69
|
-
import { langchainMessagesToCopilotKit
|
|
68
|
+
import { langchainMessagesToCopilotKit } from "./remote-lg-action";
|
|
70
69
|
import { MetaEventInput } from "../../graphql/inputs/meta-event.input";
|
|
71
70
|
import {
|
|
72
71
|
CopilotObservabilityConfig,
|
|
@@ -283,23 +282,23 @@ export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []
|
|
|
283
282
|
createMCPClient?: CreateMCPClientFunction;
|
|
284
283
|
|
|
285
284
|
/**
|
|
286
|
-
* Optional
|
|
285
|
+
* Optional error handler for comprehensive debugging and observability.
|
|
287
286
|
*
|
|
288
|
-
* **Requires publicApiKey**:
|
|
287
|
+
* **Requires publicApiKey**: Error handling only works when requests include a valid publicApiKey.
|
|
289
288
|
* This is a premium CopilotKit Cloud feature.
|
|
290
289
|
*
|
|
291
|
-
* @param
|
|
290
|
+
* @param errorEvent - Structured error event with rich debugging context
|
|
292
291
|
*
|
|
293
292
|
* @example
|
|
294
293
|
* ```typescript
|
|
295
294
|
* const runtime = new CopilotRuntime({
|
|
296
|
-
*
|
|
297
|
-
* debugDashboard.capture(
|
|
295
|
+
* onError: (errorEvent) => {
|
|
296
|
+
* debugDashboard.capture(errorEvent);
|
|
298
297
|
* }
|
|
299
298
|
* });
|
|
300
299
|
* ```
|
|
301
300
|
*/
|
|
302
|
-
|
|
301
|
+
onError?: CopilotErrorHandler;
|
|
303
302
|
}
|
|
304
303
|
|
|
305
304
|
export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
@@ -312,8 +311,8 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
312
311
|
private delegateAgentProcessingToServiceAdapter: boolean;
|
|
313
312
|
private observability?: CopilotObservabilityConfig;
|
|
314
313
|
private availableAgents: Pick<AgentWithEndpoint, "name" | "id">[];
|
|
315
|
-
private
|
|
316
|
-
private
|
|
314
|
+
private onError?: CopilotErrorHandler;
|
|
315
|
+
private hasWarnedAboutError = false;
|
|
317
316
|
|
|
318
317
|
// +++ MCP Properties +++
|
|
319
318
|
private readonly mcpServersConfig?: MCPEndpointConfig[];
|
|
@@ -362,7 +361,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
362
361
|
params?.delegateAgentProcessingToServiceAdapter || false;
|
|
363
362
|
this.observability = params?.observability_c;
|
|
364
363
|
this.agents = params?.agents ?? {};
|
|
365
|
-
this.
|
|
364
|
+
this.onError = params?.onError;
|
|
366
365
|
// +++ MCP Initialization +++
|
|
367
366
|
this.mcpServersConfig = params?.mcpServers;
|
|
368
367
|
this.createMCPClientImpl = params?.createMCPClient;
|
|
@@ -440,9 +439,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
440
439
|
}
|
|
441
440
|
|
|
442
441
|
const instructions =
|
|
443
|
-
|
|
444
|
-
mcpToolInstructions +
|
|
445
|
-
"\nUse them when appropriate to fulfill the user's request.";
|
|
442
|
+
mcpToolInstructions + "\nUse them when appropriate to fulfill the user's request.";
|
|
446
443
|
|
|
447
444
|
const systemMessageIndex = messages.findIndex((msg) => msg.textMessage?.role === "system");
|
|
448
445
|
|
|
@@ -489,16 +486,11 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
489
486
|
publicApiKey,
|
|
490
487
|
} = request;
|
|
491
488
|
|
|
492
|
-
const eventSource = new RuntimeEventSource(
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
// Trace request start
|
|
499
|
-
await this.trace(
|
|
500
|
-
"request",
|
|
501
|
-
{
|
|
489
|
+
const eventSource = new RuntimeEventSource({
|
|
490
|
+
errorHandler: async (error, context) => {
|
|
491
|
+
await this.error("error", context, error, publicApiKey);
|
|
492
|
+
},
|
|
493
|
+
errorContext: {
|
|
502
494
|
threadId,
|
|
503
495
|
runId,
|
|
504
496
|
source: "runtime",
|
|
@@ -506,20 +498,18 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
506
498
|
operation: "processRuntimeRequest",
|
|
507
499
|
method: "POST",
|
|
508
500
|
url: url,
|
|
509
|
-
startTime:
|
|
501
|
+
startTime: Date.now(),
|
|
510
502
|
},
|
|
511
503
|
agent: agentSession ? { name: agentSession.agentName } : undefined,
|
|
512
|
-
messages: {
|
|
513
|
-
input: rawMessages,
|
|
514
|
-
messageCount: rawMessages.length,
|
|
515
|
-
},
|
|
516
504
|
technical: {
|
|
517
505
|
environment: process.env.NODE_ENV,
|
|
518
506
|
},
|
|
519
507
|
},
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
);
|
|
508
|
+
});
|
|
509
|
+
// Track request start time for logging
|
|
510
|
+
const requestStartTime = Date.now();
|
|
511
|
+
// For storing streamed chunks if progressive logging is enabled
|
|
512
|
+
const streamedChunks: any[] = [];
|
|
523
513
|
|
|
524
514
|
try {
|
|
525
515
|
if (
|
|
@@ -755,8 +745,8 @@ please use an LLM adapter instead.`,
|
|
|
755
745
|
);
|
|
756
746
|
}
|
|
757
747
|
|
|
758
|
-
//
|
|
759
|
-
await this.
|
|
748
|
+
// Track the error
|
|
749
|
+
await this.error(
|
|
760
750
|
"error",
|
|
761
751
|
{
|
|
762
752
|
threadId,
|
|
@@ -787,10 +777,8 @@ please use an LLM adapter instead.`,
|
|
|
787
777
|
}
|
|
788
778
|
|
|
789
779
|
async getAllAgents(graphqlContext: GraphQLContext): Promise<(AgentWithEndpoint | Agent)[]> {
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
this.discoverAgentsFromAgui(),
|
|
793
|
-
]);
|
|
780
|
+
const agentsWithEndpoints = await this.discoverAgentsFromEndpoints(graphqlContext);
|
|
781
|
+
const aguiAgents = this.discoverAgentsFromAgui();
|
|
794
782
|
|
|
795
783
|
this.availableAgents = [...agentsWithEndpoints, ...aguiAgents].map((a) => ({
|
|
796
784
|
name: a.name,
|
|
@@ -885,39 +873,12 @@ please use an LLM adapter instead.`,
|
|
|
885
873
|
return agents;
|
|
886
874
|
}
|
|
887
875
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
let data: Array<{ assistant_id: string; graph_id: string }> | { detail: string } = [];
|
|
895
|
-
try {
|
|
896
|
-
data = await client.assistants.search();
|
|
897
|
-
|
|
898
|
-
if (data && "detail" in data && (data.detail as string).toLowerCase() === "not found") {
|
|
899
|
-
throw new CopilotKitAgentDiscoveryError({ availableAgents: this.availableAgents });
|
|
900
|
-
}
|
|
901
|
-
} catch (e) {
|
|
902
|
-
throw new CopilotKitMisuseError({
|
|
903
|
-
message: `
|
|
904
|
-
Failed to find or contact agent ${agent.graphId}.
|
|
905
|
-
Make sure the LangGraph API is running and the agent is defined in langgraph.json
|
|
906
|
-
|
|
907
|
-
See more: https://docs.copilotkit.ai/troubleshooting/common-issues`,
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
const endpointAgents = data.map((entry) => ({
|
|
911
|
-
name: entry.graph_id,
|
|
912
|
-
id: entry.assistant_id,
|
|
913
|
-
description: "",
|
|
914
|
-
}));
|
|
915
|
-
return [...agents, ...endpointAgents];
|
|
916
|
-
},
|
|
917
|
-
Promise.resolve([]),
|
|
918
|
-
);
|
|
919
|
-
|
|
920
|
-
return agents;
|
|
876
|
+
discoverAgentsFromAgui(): Agent[] {
|
|
877
|
+
return Object.entries(this.agents ?? []).map(([key, agent]: [string, AbstractAgent]) => ({
|
|
878
|
+
name: (agent as any).agentName ?? key,
|
|
879
|
+
id: agent.agentId ?? key,
|
|
880
|
+
description: agent.description ?? "",
|
|
881
|
+
}));
|
|
921
882
|
}
|
|
922
883
|
|
|
923
884
|
async loadAgentState(
|
|
@@ -992,37 +953,43 @@ please use an LLM adapter instead.`,
|
|
|
992
953
|
? { authorization: `Bearer ${graphqlContext.properties.authorization}` }
|
|
993
954
|
: null;
|
|
994
955
|
|
|
995
|
-
let client: LangGraphClient;
|
|
996
|
-
if ("endpoint" in agent && agent.endpoint.type === EndpointType.LangGraphPlatform) {
|
|
997
|
-
client = new LangGraphClient({
|
|
998
|
-
apiUrl: agent.endpoint.deploymentUrl,
|
|
999
|
-
apiKey: agent.endpoint.langsmithApiKey,
|
|
1000
|
-
defaultHeaders: { ...propertyHeaders },
|
|
1001
|
-
});
|
|
1002
|
-
} else {
|
|
1003
|
-
const aguiAgent = graphqlContext._copilotkit.runtime.agents[agent.name] as LangGraphAgent;
|
|
1004
|
-
if (!aguiAgent) {
|
|
1005
|
-
throw new Error(`Agent: ${agent.name} could not be resolved`);
|
|
1006
|
-
}
|
|
1007
|
-
// @ts-expect-error -- both clients are the same
|
|
1008
|
-
client = aguiAgent.client;
|
|
1009
|
-
}
|
|
1010
956
|
let state: any = {};
|
|
1011
957
|
try {
|
|
1012
|
-
|
|
958
|
+
let client: LangGraphClient | null;
|
|
959
|
+
if ("endpoint" in agent && agent.endpoint.type === EndpointType.LangGraphPlatform) {
|
|
960
|
+
client = new LangGraphClient({
|
|
961
|
+
apiUrl: agent.endpoint.deploymentUrl,
|
|
962
|
+
apiKey: agent.endpoint.langsmithApiKey,
|
|
963
|
+
defaultHeaders: { ...propertyHeaders },
|
|
964
|
+
});
|
|
965
|
+
} else {
|
|
966
|
+
const aguiAgent = graphqlContext._copilotkit.runtime.agents[agent.name] as LangGraphAgent;
|
|
967
|
+
if (!aguiAgent) {
|
|
968
|
+
throw new Error(`Agent: ${agent.name} could not be resolved`);
|
|
969
|
+
}
|
|
970
|
+
// @ts-expect-error -- both clients are the same
|
|
971
|
+
client = aguiAgent.client ?? null;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
state = client ? ((await client.threads.getState(threadId)).values as any) : {};
|
|
1013
975
|
} catch (error) {
|
|
1014
976
|
// All errors from agent state loading are user configuration issues
|
|
1015
977
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
978
|
+
const errorStatus = error?.response?.status || error?.status;
|
|
1016
979
|
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
980
|
+
if (errorStatus === 404) {
|
|
981
|
+
state = {};
|
|
982
|
+
} else {
|
|
983
|
+
// Log user configuration errors at debug level to reduce noise
|
|
984
|
+
console.debug(`Agent '${agentName}' configuration issue: ${errorMessage}`);
|
|
985
|
+
|
|
986
|
+
// Throw a configuration error - all agent state loading failures are user setup issues
|
|
987
|
+
throw new ResolvedCopilotKitError({
|
|
988
|
+
status: 400,
|
|
989
|
+
message: `Agent '${agentName}' failed to execute: ${errorMessage}`,
|
|
990
|
+
code: CopilotKitErrorCode.CONFIGURATION_ERROR,
|
|
991
|
+
});
|
|
992
|
+
}
|
|
1026
993
|
}
|
|
1027
994
|
|
|
1028
995
|
if (Object.keys(state).length === 0) {
|
|
@@ -1069,8 +1036,8 @@ please use an LLM adapter instead.`,
|
|
|
1069
1036
|
// for backwards compatibility, deal with the case when no threadId is provided
|
|
1070
1037
|
const threadId = threadIdFromRequest ?? agentSession.threadId;
|
|
1071
1038
|
|
|
1072
|
-
//
|
|
1073
|
-
await this.
|
|
1039
|
+
// Track agent request start
|
|
1040
|
+
await this.error(
|
|
1074
1041
|
"agent_state",
|
|
1075
1042
|
{
|
|
1076
1043
|
threadId,
|
|
@@ -1160,7 +1127,27 @@ please use an LLM adapter instead.`,
|
|
|
1160
1127
|
});
|
|
1161
1128
|
|
|
1162
1129
|
try {
|
|
1163
|
-
const eventSource = new RuntimeEventSource(
|
|
1130
|
+
const eventSource = new RuntimeEventSource({
|
|
1131
|
+
errorHandler: async (error, context) => {
|
|
1132
|
+
await this.error("error", context, error, publicApiKey);
|
|
1133
|
+
},
|
|
1134
|
+
errorContext: {
|
|
1135
|
+
threadId,
|
|
1136
|
+
source: "agent",
|
|
1137
|
+
request: {
|
|
1138
|
+
operation: "processAgentRequest",
|
|
1139
|
+
method: "POST",
|
|
1140
|
+
startTime: requestStartTime,
|
|
1141
|
+
},
|
|
1142
|
+
agent: {
|
|
1143
|
+
name: agentName,
|
|
1144
|
+
nodeName: nodeName,
|
|
1145
|
+
},
|
|
1146
|
+
technical: {
|
|
1147
|
+
environment: process.env.NODE_ENV,
|
|
1148
|
+
},
|
|
1149
|
+
},
|
|
1150
|
+
});
|
|
1164
1151
|
const stream = await currentAgent.remoteAgentHandler({
|
|
1165
1152
|
name: agentName,
|
|
1166
1153
|
threadId,
|
|
@@ -1250,8 +1237,8 @@ please use an LLM adapter instead.`,
|
|
|
1250
1237
|
this.convertStreamingErrorToStructured(error),
|
|
1251
1238
|
);
|
|
1252
1239
|
|
|
1253
|
-
//
|
|
1254
|
-
await this.
|
|
1240
|
+
// Track streaming errors
|
|
1241
|
+
await this.error(
|
|
1255
1242
|
"error",
|
|
1256
1243
|
{
|
|
1257
1244
|
threadId,
|
|
@@ -1360,8 +1347,8 @@ please use an LLM adapter instead.`,
|
|
|
1360
1347
|
this.convertStreamingErrorToStructured(err),
|
|
1361
1348
|
);
|
|
1362
1349
|
|
|
1363
|
-
//
|
|
1364
|
-
await this.
|
|
1350
|
+
// Track the agent error
|
|
1351
|
+
await this.error(
|
|
1365
1352
|
"error",
|
|
1366
1353
|
{
|
|
1367
1354
|
threadId,
|
|
@@ -1420,6 +1407,7 @@ please use an LLM adapter instead.`,
|
|
|
1420
1407
|
frontendUrl: url,
|
|
1421
1408
|
agents: this.agents,
|
|
1422
1409
|
metaEvents: request.metaEvents,
|
|
1410
|
+
nodeName: request.agentSession?.nodeName,
|
|
1423
1411
|
});
|
|
1424
1412
|
|
|
1425
1413
|
const configuredActions =
|
|
@@ -1533,45 +1521,45 @@ please use an LLM adapter instead.`,
|
|
|
1533
1521
|
});
|
|
1534
1522
|
}
|
|
1535
1523
|
|
|
1536
|
-
private async
|
|
1537
|
-
type:
|
|
1524
|
+
private async error(
|
|
1525
|
+
type: CopilotErrorEvent["type"],
|
|
1538
1526
|
context: CopilotRequestContext,
|
|
1539
1527
|
error?: any,
|
|
1540
1528
|
publicApiKey?: string,
|
|
1541
1529
|
): Promise<void> {
|
|
1542
|
-
if (!this.
|
|
1530
|
+
if (!this.onError) return;
|
|
1543
1531
|
|
|
1544
1532
|
// Just check if publicApiKey is defined (regardless of validity)
|
|
1545
1533
|
if (!publicApiKey) {
|
|
1546
|
-
if (!this.
|
|
1534
|
+
if (!this.hasWarnedAboutError) {
|
|
1547
1535
|
console.warn(
|
|
1548
|
-
"CopilotKit:
|
|
1536
|
+
"CopilotKit: onError handler provided but requires publicApiKey to be defined for error handling to work.",
|
|
1549
1537
|
);
|
|
1550
|
-
this.
|
|
1538
|
+
this.hasWarnedAboutError = true;
|
|
1551
1539
|
}
|
|
1552
1540
|
return;
|
|
1553
1541
|
}
|
|
1554
1542
|
|
|
1555
1543
|
try {
|
|
1556
|
-
const
|
|
1544
|
+
const errorEvent: CopilotErrorEvent = {
|
|
1557
1545
|
type,
|
|
1558
1546
|
timestamp: Date.now(),
|
|
1559
1547
|
context,
|
|
1560
1548
|
...(error && { error }),
|
|
1561
1549
|
};
|
|
1562
1550
|
|
|
1563
|
-
await this.
|
|
1564
|
-
} catch (
|
|
1565
|
-
// Don't let
|
|
1566
|
-
console.error("Error in
|
|
1551
|
+
await this.onError(errorEvent);
|
|
1552
|
+
} catch (errorHandlerError) {
|
|
1553
|
+
// Don't let error handler errors break the main flow
|
|
1554
|
+
console.error("Error in onError handler:", errorHandlerError);
|
|
1567
1555
|
}
|
|
1568
1556
|
}
|
|
1569
1557
|
|
|
1570
1558
|
/**
|
|
1571
|
-
* Public method to
|
|
1572
|
-
* This allows the GraphQL resolver to send validation errors through the
|
|
1559
|
+
* Public method to handle GraphQL validation errors
|
|
1560
|
+
* This allows the GraphQL resolver to send validation errors through the error system
|
|
1573
1561
|
*/
|
|
1574
|
-
public async
|
|
1562
|
+
public async errorGraphQLError(
|
|
1575
1563
|
error: { message: string; code: string; type: string },
|
|
1576
1564
|
context: {
|
|
1577
1565
|
operation: string;
|
|
@@ -1579,10 +1567,10 @@ please use an LLM adapter instead.`,
|
|
|
1579
1567
|
guardrailsEnabled: boolean;
|
|
1580
1568
|
},
|
|
1581
1569
|
): Promise<void> {
|
|
1582
|
-
if (!this.
|
|
1570
|
+
if (!this.onError) return;
|
|
1583
1571
|
|
|
1584
1572
|
try {
|
|
1585
|
-
await this.
|
|
1573
|
+
await this.onError({
|
|
1586
1574
|
type: "error",
|
|
1587
1575
|
timestamp: Date.now(),
|
|
1588
1576
|
context: {
|
|
@@ -1602,9 +1590,9 @@ please use an LLM adapter instead.`,
|
|
|
1602
1590
|
},
|
|
1603
1591
|
error,
|
|
1604
1592
|
});
|
|
1605
|
-
} catch (
|
|
1606
|
-
// Don't let
|
|
1607
|
-
console.error("Error in
|
|
1593
|
+
} catch (errorHandlerError) {
|
|
1594
|
+
// Don't let error handler errors break the main flow
|
|
1595
|
+
console.error("Error in onError handler:", errorHandlerError);
|
|
1608
1596
|
}
|
|
1609
1597
|
}
|
|
1610
1598
|
}
|
|
@@ -14,7 +14,7 @@ export interface MCPTool {
|
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
16
|
/** The function to call to execute the tool on the MCP server. */
|
|
17
|
-
execute(
|
|
17
|
+
execute(params: any): Promise<any>;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -51,7 +51,7 @@ export function extractParametersFromSchema(
|
|
|
51
51
|
? (toolOrSchema as MCPTool).schema
|
|
52
52
|
: (toolOrSchema as MCPTool["schema"]);
|
|
53
53
|
|
|
54
|
-
const toolParameters = schema?.parameters || schema?.parameters
|
|
54
|
+
const toolParameters = schema?.parameters?.jsonSchema || schema?.parameters;
|
|
55
55
|
const properties = toolParameters?.properties;
|
|
56
56
|
const requiredParams = new Set(toolParameters?.required || []);
|
|
57
57
|
|
|
@@ -62,15 +62,45 @@ export function extractParametersFromSchema(
|
|
|
62
62
|
for (const paramName in properties) {
|
|
63
63
|
if (Object.prototype.hasOwnProperty.call(properties, paramName)) {
|
|
64
64
|
const paramDef = properties[paramName];
|
|
65
|
+
|
|
66
|
+
// Enhanced type extraction with support for complex types
|
|
67
|
+
let type = paramDef.type || "string";
|
|
68
|
+
let description = paramDef.description || "";
|
|
69
|
+
|
|
70
|
+
// Handle arrays with items
|
|
71
|
+
if (type === "array" && paramDef.items) {
|
|
72
|
+
const itemType = paramDef.items.type || "object";
|
|
73
|
+
if (itemType === "object" && paramDef.items.properties) {
|
|
74
|
+
// For arrays of objects, describe the structure
|
|
75
|
+
const itemProperties = Object.keys(paramDef.items.properties).join(", ");
|
|
76
|
+
description =
|
|
77
|
+
description +
|
|
78
|
+
(description ? " " : "") +
|
|
79
|
+
`Array of objects with properties: ${itemProperties}`;
|
|
80
|
+
} else {
|
|
81
|
+
// For arrays of primitives
|
|
82
|
+
type = `array<${itemType}>`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Handle enums
|
|
87
|
+
if (paramDef.enum && Array.isArray(paramDef.enum)) {
|
|
88
|
+
const enumValues = paramDef.enum.join(" | ");
|
|
89
|
+
description = description + (description ? " " : "") + `Allowed values: ${enumValues}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Handle objects with properties
|
|
93
|
+
if (type === "object" && paramDef.properties) {
|
|
94
|
+
const objectProperties = Object.keys(paramDef.properties).join(", ");
|
|
95
|
+
description =
|
|
96
|
+
description + (description ? " " : "") + `Object with properties: ${objectProperties}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
65
99
|
parameters.push({
|
|
66
100
|
name: paramName,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
type: paramDef.type || "string",
|
|
70
|
-
description: paramDef.description,
|
|
101
|
+
type: type,
|
|
102
|
+
description: description,
|
|
71
103
|
required: requiredParams.has(paramName),
|
|
72
|
-
// Attributes might not directly map, handle if necessary
|
|
73
|
-
// attributes: paramDef.attributes || undefined,
|
|
74
104
|
});
|
|
75
105
|
}
|
|
76
106
|
}
|
|
@@ -95,7 +125,7 @@ export function convertMCPToolsToActions(
|
|
|
95
125
|
|
|
96
126
|
const handler = async (params: any): Promise<any> => {
|
|
97
127
|
try {
|
|
98
|
-
const result = await tool.execute(
|
|
128
|
+
const result = await tool.execute(params);
|
|
99
129
|
// Ensure the result is a string or stringify it, as required by many LLMs.
|
|
100
130
|
// This might need adjustment depending on how different LLMs handle tool results.
|
|
101
131
|
return typeof result === "string" ? result : JSON.stringify(result);
|
|
@@ -148,16 +178,49 @@ export function generateMcpToolInstructions(toolsMap: Record<string, MCPTool>):
|
|
|
148
178
|
if (tool.schema && typeof tool.schema === "object") {
|
|
149
179
|
const schema = tool.schema as any;
|
|
150
180
|
|
|
151
|
-
// Extract parameters from JSON Schema
|
|
152
|
-
|
|
153
|
-
|
|
181
|
+
// Extract parameters from JSON Schema - check both schema.parameters.properties and schema.properties
|
|
182
|
+
const toolParameters = schema.parameters?.jsonSchema || schema.parameters;
|
|
183
|
+
const properties = toolParameters?.properties || schema.properties;
|
|
184
|
+
const requiredParams = toolParameters?.required || schema.required || [];
|
|
154
185
|
|
|
155
|
-
|
|
156
|
-
|
|
186
|
+
if (properties) {
|
|
187
|
+
// Build parameter documentation from properties with enhanced type information
|
|
188
|
+
const paramsList = Object.entries(properties).map(([paramName, propSchema]) => {
|
|
157
189
|
const propDetails = propSchema as any;
|
|
158
190
|
const requiredMark = requiredParams.includes(paramName) ? "*" : "";
|
|
159
|
-
|
|
160
|
-
|
|
191
|
+
let typeInfo = propDetails.type || "any";
|
|
192
|
+
let description = propDetails.description ? ` - ${propDetails.description}` : "";
|
|
193
|
+
|
|
194
|
+
// Enhanced type display for complex schemas
|
|
195
|
+
if (typeInfo === "array" && propDetails.items) {
|
|
196
|
+
const itemType = propDetails.items.type || "object";
|
|
197
|
+
if (itemType === "object" && propDetails.items.properties) {
|
|
198
|
+
const itemProps = Object.keys(propDetails.items.properties).join(", ");
|
|
199
|
+
typeInfo = `array<object>`;
|
|
200
|
+
description =
|
|
201
|
+
description +
|
|
202
|
+
(description ? " " : " - ") +
|
|
203
|
+
`Array of objects with properties: ${itemProps}`;
|
|
204
|
+
} else {
|
|
205
|
+
typeInfo = `array<${itemType}>`;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Handle enums
|
|
210
|
+
if (propDetails.enum && Array.isArray(propDetails.enum)) {
|
|
211
|
+
const enumValues = propDetails.enum.join(" | ");
|
|
212
|
+
description =
|
|
213
|
+
description + (description ? " " : " - ") + `Allowed values: ${enumValues}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Handle objects
|
|
217
|
+
if (typeInfo === "object" && propDetails.properties) {
|
|
218
|
+
const objectProps = Object.keys(propDetails.properties).join(", ");
|
|
219
|
+
description =
|
|
220
|
+
description +
|
|
221
|
+
(description ? " " : " - ") +
|
|
222
|
+
`Object with properties: ${objectProps}`;
|
|
223
|
+
}
|
|
161
224
|
|
|
162
225
|
return ` - ${paramName}${requiredMark} (${typeInfo})${description}`;
|
|
163
226
|
});
|
|
@@ -183,6 +246,9 @@ ${toolsDoc}
|
|
|
183
246
|
When using these tools:
|
|
184
247
|
1. Only provide valid parameters according to their type requirements
|
|
185
248
|
2. Required parameters are marked with *
|
|
186
|
-
3.
|
|
187
|
-
4.
|
|
249
|
+
3. For array parameters, provide data in the correct array format
|
|
250
|
+
4. For object parameters, include all required nested properties
|
|
251
|
+
5. For enum parameters, use only the allowed values listed
|
|
252
|
+
6. Format API calls correctly with the expected parameter structure
|
|
253
|
+
7. Always check tool responses to determine your next action`;
|
|
188
254
|
}
|
|
@@ -131,6 +131,7 @@ export async function setupRemoteActions({
|
|
|
131
131
|
frontendUrl,
|
|
132
132
|
agents,
|
|
133
133
|
metaEvents,
|
|
134
|
+
nodeName,
|
|
134
135
|
}: {
|
|
135
136
|
remoteEndpointDefinitions: EndpointDefinition[];
|
|
136
137
|
graphqlContext: GraphQLContext;
|
|
@@ -139,10 +140,13 @@ export async function setupRemoteActions({
|
|
|
139
140
|
frontendUrl?: string;
|
|
140
141
|
agents: Record<string, AbstractAgent>;
|
|
141
142
|
metaEvents?: MetaEventInput[];
|
|
143
|
+
nodeName?: string;
|
|
142
144
|
}): Promise<Action[]> {
|
|
143
145
|
const logger = graphqlContext.logger.child({ component: "remote-actions.fetchRemoteActions" });
|
|
144
146
|
logger.debug({ remoteEndpointDefinitions }, "Fetching from remote endpoints");
|
|
145
147
|
|
|
148
|
+
const threadMetadata = (graphqlContext.properties?.threadMetadata as Record<string, any>) || {};
|
|
149
|
+
|
|
146
150
|
// Remove duplicates of remoteEndpointDefinitions.url
|
|
147
151
|
const filtered = remoteEndpointDefinitions.filter((value, index, self) => {
|
|
148
152
|
if (value.type === EndpointType.LangGraphPlatform) {
|
|
@@ -204,6 +208,8 @@ export async function setupRemoteActions({
|
|
|
204
208
|
agentStates,
|
|
205
209
|
agent: agent,
|
|
206
210
|
metaEvents,
|
|
211
|
+
threadMetadata,
|
|
212
|
+
nodeName,
|
|
207
213
|
}),
|
|
208
214
|
);
|
|
209
215
|
}
|