@copilotkit/runtime 1.9.2-next.8 → 1.9.2

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 (86) hide show
  1. package/CHANGELOG.md +177 -0
  2. package/dist/{chunk-4TLMVLU4.mjs → chunk-56ZNYBXV.mjs} +2 -2
  3. package/dist/chunk-AMUJQ6IR.mjs +50 -0
  4. package/dist/chunk-AMUJQ6IR.mjs.map +1 -0
  5. package/dist/{chunk-5SG4WWXH.mjs → chunk-GB4M7WUE.mjs} +2 -2
  6. package/dist/{chunk-JWPSIGSA.mjs → chunk-HJYWUUFY.mjs} +2 -2
  7. package/dist/{chunk-KYCDL2KX.mjs → chunk-M35WOOEP.mjs} +2 -2
  8. package/dist/{chunk-IIXJVVTV.mjs → chunk-QLLV2QVK.mjs} +132 -78
  9. package/dist/chunk-QLLV2QVK.mjs.map +1 -0
  10. package/dist/{chunk-WIXS6EG7.mjs → chunk-TE5QWP4H.mjs} +2401 -2055
  11. package/dist/chunk-TE5QWP4H.mjs.map +1 -0
  12. package/dist/{chunk-5BIEM2UU.mjs → chunk-XWBDEXDA.mjs} +4 -3
  13. package/dist/{chunk-5BIEM2UU.mjs.map → chunk-XWBDEXDA.mjs.map} +1 -1
  14. package/dist/{groq-adapter-25a2bd35.d.ts → groq-adapter-742818f2.d.ts} +5 -1
  15. package/dist/index.d.ts +4 -3
  16. package/dist/index.js +3747 -3303
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +12 -8
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/{langserve-4a5c9217.d.ts → langserve-3e8d0e06.d.ts} +13 -7
  21. package/dist/lib/index.d.ts +155 -5
  22. package/dist/lib/index.js +2808 -2407
  23. package/dist/lib/index.js.map +1 -1
  24. package/dist/lib/index.mjs +9 -8
  25. package/dist/lib/integrations/index.d.ts +3 -3
  26. package/dist/lib/integrations/index.js +151 -96
  27. package/dist/lib/integrations/index.js.map +1 -1
  28. package/dist/lib/integrations/index.mjs +7 -6
  29. package/dist/lib/integrations/nest/index.d.ts +2 -2
  30. package/dist/lib/integrations/nest/index.js +151 -96
  31. package/dist/lib/integrations/nest/index.js.map +1 -1
  32. package/dist/lib/integrations/nest/index.mjs +5 -4
  33. package/dist/lib/integrations/node-express/index.d.ts +2 -2
  34. package/dist/lib/integrations/node-express/index.js +151 -96
  35. package/dist/lib/integrations/node-express/index.js.map +1 -1
  36. package/dist/lib/integrations/node-express/index.mjs +5 -4
  37. package/dist/lib/integrations/node-http/index.d.ts +2 -2
  38. package/dist/lib/integrations/node-http/index.js +151 -96
  39. package/dist/lib/integrations/node-http/index.js.map +1 -1
  40. package/dist/lib/integrations/node-http/index.mjs +4 -3
  41. package/dist/service-adapters/index.d.ts +6 -4
  42. package/dist/service-adapters/index.js +202 -107
  43. package/dist/service-adapters/index.js.map +1 -1
  44. package/dist/service-adapters/index.mjs +6 -2
  45. package/dist/service-adapters/shared/index.d.ts +9 -0
  46. package/dist/service-adapters/shared/index.js +72 -0
  47. package/dist/service-adapters/shared/index.js.map +1 -0
  48. package/dist/service-adapters/shared/index.mjs +8 -0
  49. package/dist/service-adapters/shared/index.mjs.map +1 -0
  50. package/dist/{shared-941d59dc.d.ts → shared-96b46379.d.ts} +23 -21
  51. package/dist/utils/index.d.ts +17 -1
  52. package/dist/utils/index.js +3 -2
  53. package/dist/utils/index.js.map +1 -1
  54. package/dist/utils/index.mjs +1 -1
  55. package/package.json +11 -11
  56. package/src/agents/langgraph/event-source.ts +36 -38
  57. package/src/agents/langgraph/events.ts +19 -1
  58. package/src/graphql/resolvers/copilot.resolver.ts +85 -42
  59. package/src/lib/error-messages.ts +200 -0
  60. package/src/lib/integrations/shared.ts +43 -0
  61. package/src/lib/runtime/__tests__/{copilot-runtime-trace.test.ts → copilot-runtime-error.test.ts} +27 -27
  62. package/src/lib/runtime/__tests__/mcp-tools-utils.test.ts +464 -0
  63. package/src/lib/runtime/agui-action.ts +9 -3
  64. package/src/lib/runtime/copilot-runtime.ts +156 -160
  65. package/src/lib/runtime/mcp-tools-utils.ts +84 -18
  66. package/src/lib/runtime/remote-action-constructors.ts +28 -3
  67. package/src/lib/runtime/remote-actions.ts +6 -0
  68. package/src/lib/runtime/remote-lg-action.ts +85 -3
  69. package/src/lib/streaming.ts +125 -36
  70. package/src/service-adapters/anthropic/anthropic-adapter.ts +67 -8
  71. package/src/service-adapters/anthropic/utils.ts +3 -8
  72. package/src/service-adapters/events.ts +75 -80
  73. package/src/service-adapters/google/google-genai-adapter.ts +5 -0
  74. package/src/service-adapters/groq/groq-adapter.ts +66 -56
  75. package/src/service-adapters/index.ts +1 -0
  76. package/src/service-adapters/openai/openai-adapter.ts +4 -3
  77. package/src/service-adapters/shared/error-utils.ts +61 -0
  78. package/src/service-adapters/shared/index.ts +1 -0
  79. package/src/utils/failed-response-status-reasons.ts +23 -1
  80. package/tests/service-adapters/anthropic/anthropic-adapter.test.ts +172 -387
  81. package/dist/chunk-IIXJVVTV.mjs.map +0 -1
  82. package/dist/chunk-WIXS6EG7.mjs.map +0 -1
  83. /package/dist/{chunk-4TLMVLU4.mjs.map → chunk-56ZNYBXV.mjs.map} +0 -0
  84. /package/dist/{chunk-5SG4WWXH.mjs.map → chunk-GB4M7WUE.mjs.map} +0 -0
  85. /package/dist/{chunk-JWPSIGSA.mjs.map → chunk-HJYWUUFY.mjs.map} +0 -0
  86. /package/dist/{chunk-KYCDL2KX.mjs.map → chunk-M35WOOEP.mjs.map} +0 -0
@@ -20,14 +20,14 @@ 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
- CopilotTraceHandler,
29
- CopilotTraceEvent,
27
+ CopilotErrorHandler,
28
+ CopilotErrorEvent,
30
29
  CopilotRequestContext,
30
+ ensureStructuredError,
31
31
  } from "@copilotkit/shared";
32
32
  import {
33
33
  CopilotServiceAdapter,
@@ -89,6 +89,8 @@ import { LangGraphAgent } from "./langgraph/langgraph-agent";
89
89
  type CreateMCPClientFunction = (config: MCPEndpointConfig) => Promise<MCPClient>;
90
90
  // --- MCP Imports ---
91
91
 
92
+ import { generateHelpfulErrorMessage } from "../streaming";
93
+
92
94
  export interface CopilotRuntimeRequest {
93
95
  serviceAdapter: CopilotServiceAdapter;
94
96
  messages: MessageInput[];
@@ -280,23 +282,23 @@ export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []
280
282
  createMCPClient?: CreateMCPClientFunction;
281
283
 
282
284
  /**
283
- * Optional trace handler for comprehensive debugging and observability.
285
+ * Optional error handler for comprehensive debugging and observability.
284
286
  *
285
- * **Requires publicApiKey**: Tracing only works when requests include a valid publicApiKey.
287
+ * **Requires publicApiKey**: Error handling only works when requests include a valid publicApiKey.
286
288
  * This is a premium CopilotKit Cloud feature.
287
289
  *
288
- * @param traceEvent - Structured trace event with rich debugging context
290
+ * @param errorEvent - Structured error event with rich debugging context
289
291
  *
290
292
  * @example
291
293
  * ```typescript
292
294
  * const runtime = new CopilotRuntime({
293
- * onTrace: (traceEvent) => {
294
- * debugDashboard.capture(traceEvent);
295
+ * onError: (errorEvent) => {
296
+ * debugDashboard.capture(errorEvent);
295
297
  * }
296
298
  * });
297
299
  * ```
298
300
  */
299
- onTrace?: CopilotTraceHandler;
301
+ onError?: CopilotErrorHandler;
300
302
  }
301
303
 
302
304
  export class CopilotRuntime<const T extends Parameter[] | [] = []> {
@@ -309,8 +311,8 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
309
311
  private delegateAgentProcessingToServiceAdapter: boolean;
310
312
  private observability?: CopilotObservabilityConfig;
311
313
  private availableAgents: Pick<AgentWithEndpoint, "name" | "id">[];
312
- private onTrace?: CopilotTraceHandler;
313
- private hasWarnedAboutTracing = false;
314
+ private onError?: CopilotErrorHandler;
315
+ private hasWarnedAboutError = false;
314
316
 
315
317
  // +++ MCP Properties +++
316
318
  private readonly mcpServersConfig?: MCPEndpointConfig[];
@@ -359,7 +361,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
359
361
  params?.delegateAgentProcessingToServiceAdapter || false;
360
362
  this.observability = params?.observability_c;
361
363
  this.agents = params?.agents ?? {};
362
- this.onTrace = params?.onTrace;
364
+ this.onError = params?.onError;
363
365
  // +++ MCP Initialization +++
364
366
  this.mcpServersConfig = params?.mcpServers;
365
367
  this.createMCPClientImpl = params?.createMCPClient;
@@ -437,9 +439,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
437
439
  }
438
440
 
439
441
  const instructions =
440
- "You have access to the following tools provided by external Model Context Protocol (MCP) servers:\n" +
441
- mcpToolInstructions +
442
- "\nUse them when appropriate to fulfill the user's request.";
442
+ mcpToolInstructions + "\nUse them when appropriate to fulfill the user's request.";
443
443
 
444
444
  const systemMessageIndex = messages.findIndex((msg) => msg.textMessage?.role === "system");
445
445
 
@@ -486,16 +486,11 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
486
486
  publicApiKey,
487
487
  } = request;
488
488
 
489
- const eventSource = new RuntimeEventSource();
490
- // Track request start time for logging
491
- const requestStartTime = Date.now();
492
- // For storing streamed chunks if progressive logging is enabled
493
- const streamedChunks: any[] = [];
494
-
495
- // Trace request start
496
- await this.trace(
497
- "request",
498
- {
489
+ const eventSource = new RuntimeEventSource({
490
+ errorHandler: async (error, context) => {
491
+ await this.error("error", context, error, publicApiKey);
492
+ },
493
+ errorContext: {
499
494
  threadId,
500
495
  runId,
501
496
  source: "runtime",
@@ -503,20 +498,18 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
503
498
  operation: "processRuntimeRequest",
504
499
  method: "POST",
505
500
  url: url,
506
- startTime: requestStartTime,
501
+ startTime: Date.now(),
507
502
  },
508
503
  agent: agentSession ? { name: agentSession.agentName } : undefined,
509
- messages: {
510
- input: rawMessages,
511
- messageCount: rawMessages.length,
512
- },
513
504
  technical: {
514
505
  environment: process.env.NODE_ENV,
515
506
  },
516
507
  },
517
- undefined,
518
- publicApiKey,
519
- );
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[] = [];
520
513
 
521
514
  try {
522
515
  if (
@@ -746,13 +739,14 @@ please use an LLM adapter instead.`,
746
739
  if (error instanceof CopilotKitError) {
747
740
  structuredError = error;
748
741
  } else {
749
- // Convert non-CopilotKitErrors to structured errors
750
- console.error("Error getting response:", error);
751
- structuredError = this.convertStreamingErrorToStructured(error);
742
+ // Convert non-CopilotKitErrors to structured errors, but preserve already structured ones
743
+ structuredError = ensureStructuredError(error, (err) =>
744
+ this.convertStreamingErrorToStructured(err),
745
+ );
752
746
  }
753
747
 
754
- // Trace the error
755
- await this.trace(
748
+ // Track the error
749
+ await this.error(
756
750
  "error",
757
751
  {
758
752
  threadId,
@@ -783,10 +777,8 @@ please use an LLM adapter instead.`,
783
777
  }
784
778
 
785
779
  async getAllAgents(graphqlContext: GraphQLContext): Promise<(AgentWithEndpoint | Agent)[]> {
786
- const [agentsWithEndpoints, aguiAgents] = await Promise.all([
787
- this.discoverAgentsFromEndpoints(graphqlContext),
788
- this.discoverAgentsFromAgui(),
789
- ]);
780
+ const agentsWithEndpoints = await this.discoverAgentsFromEndpoints(graphqlContext);
781
+ const aguiAgents = this.discoverAgentsFromAgui();
790
782
 
791
783
  this.availableAgents = [...agentsWithEndpoints, ...aguiAgents].map((a) => ({
792
784
  name: a.name,
@@ -881,39 +873,12 @@ please use an LLM adapter instead.`,
881
873
  return agents;
882
874
  }
883
875
 
884
- async discoverAgentsFromAgui(): Promise<AgentWithEndpoint[]> {
885
- const agents: Promise<AgentWithEndpoint[]> = Object.values(this.agents ?? []).reduce(
886
- async (acc: Promise<Agent[]>, agent: LangGraphAgent) => {
887
- const agents = await acc;
888
-
889
- const client = agent.client;
890
- let data: Array<{ assistant_id: string; graph_id: string }> | { detail: string } = [];
891
- try {
892
- data = await client.assistants.search();
893
-
894
- if (data && "detail" in data && (data.detail as string).toLowerCase() === "not found") {
895
- throw new CopilotKitAgentDiscoveryError({ availableAgents: this.availableAgents });
896
- }
897
- } catch (e) {
898
- throw new CopilotKitMisuseError({
899
- message: `
900
- Failed to find or contact agent ${agent.graphId}.
901
- Make sure the LangGraph API is running and the agent is defined in langgraph.json
902
-
903
- See more: https://docs.copilotkit.ai/troubleshooting/common-issues`,
904
- });
905
- }
906
- const endpointAgents = data.map((entry) => ({
907
- name: entry.graph_id,
908
- id: entry.assistant_id,
909
- description: "",
910
- }));
911
- return [...agents, ...endpointAgents];
912
- },
913
- Promise.resolve([]),
914
- );
915
-
916
- 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
+ }));
917
882
  }
918
883
 
919
884
  async loadAgentState(
@@ -948,10 +913,24 @@ please use an LLM adapter instead.`,
948
913
  if (response.status === 404) {
949
914
  throw new CopilotKitApiDiscoveryError({ url: fetchUrl });
950
915
  }
916
+
917
+ // Extract semantic error information from response body
918
+ let errorMessage = `HTTP ${response.status} error`;
919
+ try {
920
+ const errorBody = await response.text();
921
+ const parsedError = JSON.parse(errorBody);
922
+ if (parsedError.error && typeof parsedError.error === "string") {
923
+ errorMessage = parsedError.error;
924
+ }
925
+ } catch {
926
+ // If parsing fails, fall back to generic message
927
+ }
928
+
951
929
  throw new ResolvedCopilotKitError({
952
930
  status: response.status,
953
931
  url: fetchUrl,
954
932
  isRemoteEndpoint: true,
933
+ message: errorMessage,
955
934
  });
956
935
  }
957
936
 
@@ -974,25 +953,44 @@ please use an LLM adapter instead.`,
974
953
  ? { authorization: `Bearer ${graphqlContext.properties.authorization}` }
975
954
  : null;
976
955
 
977
- let client: LangGraphClient;
978
- if ("endpoint" in agent && agent.endpoint.type === EndpointType.LangGraphPlatform) {
979
- client = new LangGraphClient({
980
- apiUrl: agent.endpoint.deploymentUrl,
981
- apiKey: agent.endpoint.langsmithApiKey,
982
- defaultHeaders: { ...propertyHeaders },
983
- });
984
- } else {
985
- const aguiAgent = graphqlContext._copilotkit.runtime.agents[agent.name] as LangGraphAgent;
986
- if (!aguiAgent) {
987
- throw new Error(`Agent: ${agent.name} could not be resolved`);
988
- }
989
- // @ts-expect-error -- both clients are the same
990
- client = aguiAgent.client;
991
- }
992
956
  let state: any = {};
993
957
  try {
994
- state = (await client.threads.getState(threadId)).values as any;
995
- } catch (error) {}
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) : {};
975
+ } catch (error) {
976
+ // All errors from agent state loading are user configuration issues
977
+ const errorMessage = error instanceof Error ? error.message : String(error);
978
+ const errorStatus = error?.response?.status || error?.status;
979
+
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
+ }
993
+ }
996
994
 
997
995
  if (Object.keys(state).length === 0) {
998
996
  return {
@@ -1038,8 +1036,8 @@ please use an LLM adapter instead.`,
1038
1036
  // for backwards compatibility, deal with the case when no threadId is provided
1039
1037
  const threadId = threadIdFromRequest ?? agentSession.threadId;
1040
1038
 
1041
- // Trace agent request start
1042
- await this.trace(
1039
+ // Track agent request start
1040
+ await this.error(
1043
1041
  "agent_state",
1044
1042
  {
1045
1043
  threadId,
@@ -1129,7 +1127,27 @@ please use an LLM adapter instead.`,
1129
1127
  });
1130
1128
 
1131
1129
  try {
1132
- 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
+ });
1133
1151
  const stream = await currentAgent.remoteAgentHandler({
1134
1152
  name: agentName,
1135
1153
  threadId,
@@ -1193,8 +1211,6 @@ please use an LLM adapter instead.`,
1193
1211
  from(stream).subscribe({
1194
1212
  next: (event) => eventStream$.next(event),
1195
1213
  error: async (err) => {
1196
- console.error("Error in stream", err);
1197
-
1198
1214
  // Log error with observability if enabled
1199
1215
  if (this.observability?.enabled && publicApiKey) {
1200
1216
  try {
@@ -1216,11 +1232,13 @@ please use an LLM adapter instead.`,
1216
1232
  }
1217
1233
  }
1218
1234
 
1219
- // Convert network termination errors to structured errors
1220
- const structuredError = this.convertStreamingErrorToStructured(err);
1235
+ // Preserve structured CopilotKit errors, only convert unstructured errors
1236
+ const structuredError = ensureStructuredError(err, (error) =>
1237
+ this.convertStreamingErrorToStructured(error),
1238
+ );
1221
1239
 
1222
- // Trace streaming errors
1223
- await this.trace(
1240
+ // Track streaming errors
1241
+ await this.error(
1224
1242
  "error",
1225
1243
  {
1226
1244
  threadId,
@@ -1325,15 +1343,12 @@ please use an LLM adapter instead.`,
1325
1343
  }
1326
1344
 
1327
1345
  // Ensure error is structured
1328
- let structuredError: CopilotKitError;
1329
- if (error instanceof CopilotKitError) {
1330
- structuredError = error;
1331
- } else {
1332
- structuredError = this.convertStreamingErrorToStructured(error);
1333
- }
1346
+ const structuredError = ensureStructuredError(error, (err) =>
1347
+ this.convertStreamingErrorToStructured(err),
1348
+ );
1334
1349
 
1335
- // Trace the agent error
1336
- await this.trace(
1350
+ // Track the agent error
1351
+ await this.error(
1337
1352
  "error",
1338
1353
  {
1339
1354
  threadId,
@@ -1392,6 +1407,7 @@ please use an LLM adapter instead.`,
1392
1407
  frontendUrl: url,
1393
1408
  agents: this.agents,
1394
1409
  metaEvents: request.metaEvents,
1410
+ nodeName: request.agentSession?.nodeName,
1395
1411
  });
1396
1412
 
1397
1413
  const configuredActions =
@@ -1477,93 +1493,73 @@ please use an LLM adapter instead.`,
1477
1493
  }
1478
1494
 
1479
1495
  private convertStreamingErrorToStructured(error: any): CopilotKitError {
1480
- // Handle network termination errors
1481
- if (
1482
- error?.message?.includes("terminated") ||
1483
- error?.cause?.code === "UND_ERR_SOCKET" ||
1484
- error?.message?.includes("other side closed") ||
1485
- error?.code === "UND_ERR_SOCKET"
1486
- ) {
1487
- return new CopilotKitError({
1488
- message:
1489
- "Connection to agent was unexpectedly terminated. This may be due to the agent service being restarted or network issues. Please try again.",
1490
- code: CopilotKitErrorCode.NETWORK_ERROR,
1491
- });
1492
- }
1496
+ // Determine a more helpful error message based on context
1497
+ let helpfulMessage = generateHelpfulErrorMessage(error, "agent streaming connection");
1493
1498
 
1494
- // Handle other network-related errors
1499
+ // For network-related errors, use CopilotKitLowLevelError to preserve the original error
1495
1500
  if (
1496
1501
  error?.message?.includes("fetch failed") ||
1497
1502
  error?.message?.includes("ECONNREFUSED") ||
1498
1503
  error?.message?.includes("ENOTFOUND") ||
1499
- error?.message?.includes("ETIMEDOUT")
1504
+ error?.message?.includes("ETIMEDOUT") ||
1505
+ error?.message?.includes("terminated") ||
1506
+ error?.cause?.code === "UND_ERR_SOCKET" ||
1507
+ error?.message?.includes("other side closed") ||
1508
+ error?.code === "UND_ERR_SOCKET"
1500
1509
  ) {
1501
1510
  return new CopilotKitLowLevelError({
1502
1511
  error: error instanceof Error ? error : new Error(String(error)),
1503
1512
  url: "agent streaming connection",
1504
- message:
1505
- "Network error occurred during agent streaming. Please check your connection and try again.",
1506
- });
1507
- }
1508
-
1509
- // Handle abort/cancellation errors (these are usually normal)
1510
- if (
1511
- error?.message?.includes("aborted") ||
1512
- error?.message?.includes("canceled") ||
1513
- error?.message?.includes("signal is aborted")
1514
- ) {
1515
- return new CopilotKitError({
1516
- message: "Agent request was cancelled",
1517
- code: CopilotKitErrorCode.UNKNOWN,
1513
+ message: helpfulMessage,
1518
1514
  });
1519
1515
  }
1520
1516
 
1521
- // Default: convert unknown streaming errors
1517
+ // For all other errors, preserve the raw error in a basic CopilotKitError
1522
1518
  return new CopilotKitError({
1523
- message: `Agent streaming error: ${error?.message || String(error)}`,
1519
+ message: helpfulMessage,
1524
1520
  code: CopilotKitErrorCode.UNKNOWN,
1525
1521
  });
1526
1522
  }
1527
1523
 
1528
- private async trace(
1529
- type: CopilotTraceEvent["type"],
1524
+ private async error(
1525
+ type: CopilotErrorEvent["type"],
1530
1526
  context: CopilotRequestContext,
1531
1527
  error?: any,
1532
1528
  publicApiKey?: string,
1533
1529
  ): Promise<void> {
1534
- if (!this.onTrace) return;
1530
+ if (!this.onError) return;
1535
1531
 
1532
+ // Just check if publicApiKey is defined (regardless of validity)
1536
1533
  if (!publicApiKey) {
1537
- if (!this.hasWarnedAboutTracing) {
1534
+ if (!this.hasWarnedAboutError) {
1538
1535
  console.warn(
1539
- "CopilotKit: onTrace handler provided but requires publicApiKey for tracing to work. " +
1540
- "This is a CopilotKit Cloud feature. See: https://docs.copilotkit.ai/cloud",
1536
+ "CopilotKit: onError handler provided but requires publicApiKey to be defined for error handling to work.",
1541
1537
  );
1542
- this.hasWarnedAboutTracing = true;
1538
+ this.hasWarnedAboutError = true;
1543
1539
  }
1544
1540
  return;
1545
1541
  }
1546
1542
 
1547
1543
  try {
1548
- const traceEvent: CopilotTraceEvent = {
1544
+ const errorEvent: CopilotErrorEvent = {
1549
1545
  type,
1550
1546
  timestamp: Date.now(),
1551
1547
  context,
1552
1548
  ...(error && { error }),
1553
1549
  };
1554
1550
 
1555
- await this.onTrace(traceEvent);
1556
- } catch (traceError) {
1557
- // Don't let trace errors break the main flow
1558
- console.error("Error in onTrace handler:", traceError);
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);
1559
1555
  }
1560
1556
  }
1561
1557
 
1562
1558
  /**
1563
- * Public method to trace GraphQL validation errors
1564
- * This allows the GraphQL resolver to send validation errors through the trace system
1559
+ * Public method to handle GraphQL validation errors
1560
+ * This allows the GraphQL resolver to send validation errors through the error system
1565
1561
  */
1566
- public async traceGraphQLError(
1562
+ public async errorGraphQLError(
1567
1563
  error: { message: string; code: string; type: string },
1568
1564
  context: {
1569
1565
  operation: string;
@@ -1571,10 +1567,10 @@ please use an LLM adapter instead.`,
1571
1567
  guardrailsEnabled: boolean;
1572
1568
  },
1573
1569
  ): Promise<void> {
1574
- if (!this.onTrace) return;
1570
+ if (!this.onError) return;
1575
1571
 
1576
1572
  try {
1577
- await this.onTrace({
1573
+ await this.onError({
1578
1574
  type: "error",
1579
1575
  timestamp: Date.now(),
1580
1576
  context: {
@@ -1594,9 +1590,9 @@ please use an LLM adapter instead.`,
1594
1590
  },
1595
1591
  error,
1596
1592
  });
1597
- } catch (traceError) {
1598
- // Don't let trace errors break the main flow
1599
- console.error("Error in onTrace handler:", traceError);
1593
+ } catch (errorHandlerError) {
1594
+ // Don't let error handler errors break the main flow
1595
+ console.error("Error in onError handler:", errorHandlerError);
1600
1596
  }
1601
1597
  }
1602
1598
  }