@copilotkit/runtime 1.9.2-next.7 → 1.9.2-next.9

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 (78) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/{chunk-IIXJVVTV.mjs → chunk-4JBKY7XT.mjs} +109 -75
  3. package/dist/chunk-4JBKY7XT.mjs.map +1 -0
  4. package/dist/{chunk-LSB3QZHS.mjs → chunk-5YGKE5SN.mjs} +2 -2
  5. package/dist/{chunk-2PQGAIVB.mjs → chunk-ALZ5H3VD.mjs} +2 -2
  6. package/dist/chunk-AMUJQ6IR.mjs +50 -0
  7. package/dist/chunk-AMUJQ6IR.mjs.map +1 -0
  8. package/dist/{chunk-2UAJCT5X.mjs → chunk-SMDVD4VG.mjs} +2 -2
  9. package/dist/{chunk-GW6ERFKI.mjs → chunk-UUXRYAB4.mjs} +2 -2
  10. package/dist/{chunk-5BIEM2UU.mjs → chunk-XWBDEXDA.mjs} +4 -3
  11. package/dist/{chunk-5BIEM2UU.mjs.map → chunk-XWBDEXDA.mjs.map} +1 -1
  12. package/dist/{chunk-HB4D2KJC.mjs → chunk-Z5GYTKMD.mjs} +2345 -2066
  13. package/dist/chunk-Z5GYTKMD.mjs.map +1 -0
  14. package/dist/{groq-adapter-25a2bd35.d.ts → groq-adapter-172a2ca4.d.ts} +1 -1
  15. package/dist/index.d.ts +4 -3
  16. package/dist/index.js +3713 -3356
  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/lib/index.d.ts +3 -3
  21. package/dist/lib/index.js +2981 -2624
  22. package/dist/lib/index.js.map +1 -1
  23. package/dist/lib/index.mjs +9 -8
  24. package/dist/lib/integrations/index.d.ts +3 -3
  25. package/dist/lib/integrations/index.js +141 -86
  26. package/dist/lib/integrations/index.js.map +1 -1
  27. package/dist/lib/integrations/index.mjs +7 -6
  28. package/dist/lib/integrations/nest/index.d.ts +2 -2
  29. package/dist/lib/integrations/nest/index.js +141 -86
  30. package/dist/lib/integrations/nest/index.js.map +1 -1
  31. package/dist/lib/integrations/nest/index.mjs +5 -4
  32. package/dist/lib/integrations/node-express/index.d.ts +2 -2
  33. package/dist/lib/integrations/node-express/index.js +141 -86
  34. package/dist/lib/integrations/node-express/index.js.map +1 -1
  35. package/dist/lib/integrations/node-express/index.mjs +5 -4
  36. package/dist/lib/integrations/node-http/index.d.ts +2 -2
  37. package/dist/lib/integrations/node-http/index.js +141 -86
  38. package/dist/lib/integrations/node-http/index.js.map +1 -1
  39. package/dist/lib/integrations/node-http/index.mjs +4 -3
  40. package/dist/service-adapters/index.d.ts +5 -4
  41. package/dist/service-adapters/index.js +179 -104
  42. package/dist/service-adapters/index.js.map +1 -1
  43. package/dist/service-adapters/index.mjs +6 -2
  44. package/dist/service-adapters/shared/index.d.ts +9 -0
  45. package/dist/service-adapters/shared/index.js +72 -0
  46. package/dist/service-adapters/shared/index.js.map +1 -0
  47. package/dist/service-adapters/shared/index.mjs +8 -0
  48. package/dist/service-adapters/shared/index.mjs.map +1 -0
  49. package/dist/{shared-941d59dc.d.ts → shared-bd953ebf.d.ts} +8 -4
  50. package/dist/utils/index.d.ts +17 -1
  51. package/dist/utils/index.js +3 -2
  52. package/dist/utils/index.js.map +1 -1
  53. package/dist/utils/index.mjs +1 -1
  54. package/package.json +2 -2
  55. package/src/agents/langgraph/event-source.ts +36 -38
  56. package/src/agents/langgraph/events.ts +19 -1
  57. package/src/graphql/resolvers/copilot.resolver.ts +84 -40
  58. package/src/lib/error-messages.ts +200 -0
  59. package/src/lib/integrations/shared.ts +43 -0
  60. package/src/lib/runtime/copilot-runtime.ts +56 -48
  61. package/src/lib/runtime/remote-action-constructors.ts +28 -3
  62. package/src/lib/runtime/remote-lg-action.ts +130 -40
  63. package/src/lib/streaming.ts +125 -36
  64. package/src/service-adapters/anthropic/anthropic-adapter.ts +3 -4
  65. package/src/service-adapters/events.ts +37 -81
  66. package/src/service-adapters/groq/groq-adapter.ts +66 -56
  67. package/src/service-adapters/index.ts +1 -0
  68. package/src/service-adapters/openai/openai-adapter.ts +18 -3
  69. package/src/service-adapters/shared/error-utils.ts +61 -0
  70. package/src/service-adapters/shared/index.ts +1 -0
  71. package/src/utils/failed-response-status-reasons.ts +23 -1
  72. package/dist/chunk-HB4D2KJC.mjs.map +0 -1
  73. package/dist/chunk-IIXJVVTV.mjs.map +0 -1
  74. package/dist/{chunk-LSB3QZHS.mjs.map → chunk-5YGKE5SN.mjs.map} +0 -0
  75. package/dist/{chunk-2PQGAIVB.mjs.map → chunk-ALZ5H3VD.mjs.map} +0 -0
  76. package/dist/{chunk-2UAJCT5X.mjs.map → chunk-SMDVD4VG.mjs.map} +0 -0
  77. package/dist/{chunk-GW6ERFKI.mjs.map → chunk-UUXRYAB4.mjs.map} +0 -0
  78. package/dist/{langserve-4a5c9217.d.ts → langserve-fc5cac89.d.ts} +7 -7
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Error message configuration - Single source of truth for all error messages
3
+ *
4
+ * This centralized configuration system provides:
5
+ *
6
+ * 🎯 **Benefits:**
7
+ * - Single source of truth for all error messages
8
+ * - Easy content management without touching code
9
+ * - Consistent error messaging across the application
10
+ * - Ready for internationalization (i18n)
11
+ * - Type-safe configuration with TypeScript
12
+ * - Categorized errors for better handling
13
+ *
14
+ * 📝 **How to use:**
15
+ * 1. Add new error patterns to `errorPatterns` object
16
+ * 2. Use {context} placeholder for dynamic context injection
17
+ * 3. Specify category, severity, and actionable flags
18
+ * 4. Add fallback messages for error categories
19
+ *
20
+ * 🔧 **How to maintain:**
21
+ * - Content teams can update messages here without touching logic
22
+ * - Developers add new error patterns as needed
23
+ * - Use categories to group similar errors
24
+ * - Mark errors as actionable if users can fix them
25
+ *
26
+ * 🌍 **Future i18n support:**
27
+ * - Replace `message` string with `messages: { en: "...", es: "..." }`
28
+ * - Add locale parameter to helper functions
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Adding a new error pattern:
33
+ * "CUSTOM_ERROR": {
34
+ * message: "Custom error occurred in {context}. Please try again.",
35
+ * category: "unknown",
36
+ * severity: "error",
37
+ * actionable: true
38
+ * }
39
+ * ```
40
+ */
41
+
42
+ export interface ErrorPatternConfig {
43
+ message: string;
44
+ category: "network" | "connection" | "authentication" | "validation" | "unknown";
45
+ severity: "error" | "warning" | "info";
46
+ actionable: boolean;
47
+ }
48
+
49
+ export interface ErrorConfig {
50
+ errorPatterns: Record<string, ErrorPatternConfig>;
51
+ fallbacks: Record<string, string>;
52
+ contextTemplates: Record<string, string>;
53
+ }
54
+
55
+ export const errorConfig: ErrorConfig = {
56
+ errorPatterns: {
57
+ ECONNREFUSED: {
58
+ message:
59
+ "Connection refused - the agent service is not running or not accessible at the specified address. Please check that your agent is started and listening on the correct port.",
60
+ category: "network",
61
+ severity: "error",
62
+ actionable: true,
63
+ },
64
+ ENOTFOUND: {
65
+ message:
66
+ "Host not found - the agent service URL appears to be incorrect or the service is not accessible. Please verify the agent endpoint URL.",
67
+ category: "network",
68
+ severity: "error",
69
+ actionable: true,
70
+ },
71
+ ETIMEDOUT: {
72
+ message:
73
+ "Connection timeout - the agent service is taking too long to respond. This could indicate network issues or an overloaded agent service.",
74
+ category: "network",
75
+ severity: "warning",
76
+ actionable: true,
77
+ },
78
+ terminated: {
79
+ message:
80
+ "Agent {context} was unexpectedly terminated. This often indicates an error in the agent service (e.g., authentication failures, missing environment variables, or agent crashes). Check the agent logs for the root cause.",
81
+ category: "connection",
82
+ severity: "error",
83
+ actionable: true,
84
+ },
85
+ UND_ERR_SOCKET: {
86
+ message:
87
+ "Socket connection was closed unexpectedly. This typically indicates the agent service encountered an error and shut down the connection. Check the agent logs for the underlying cause.",
88
+ category: "connection",
89
+ severity: "error",
90
+ actionable: true,
91
+ },
92
+ other_side_closed: {
93
+ message:
94
+ "The agent service closed the connection unexpectedly. This usually indicates an error in the agent service. Check the agent logs for more details.",
95
+ category: "connection",
96
+ severity: "error",
97
+ actionable: true,
98
+ },
99
+ fetch_failed: {
100
+ message:
101
+ "Failed to connect to the agent service. Please verify the agent is running and the endpoint URL is correct.",
102
+ category: "network",
103
+ severity: "error",
104
+ actionable: true,
105
+ },
106
+ // Authentication patterns
107
+ "401": {
108
+ message:
109
+ "Authentication failed. Please check your API keys and ensure they are correctly configured.",
110
+ category: "authentication",
111
+ severity: "error",
112
+ actionable: true,
113
+ },
114
+ "api key": {
115
+ message:
116
+ "API key error detected. Please verify your API key is correct and has the necessary permissions.",
117
+ category: "authentication",
118
+ severity: "error",
119
+ actionable: true,
120
+ },
121
+ unauthorized: {
122
+ message: "Unauthorized access. Please check your authentication credentials.",
123
+ category: "authentication",
124
+ severity: "error",
125
+ actionable: true,
126
+ },
127
+ // Python-specific error patterns
128
+ AuthenticationError: {
129
+ message:
130
+ "OpenAI authentication failed. Please check your OPENAI_API_KEY environment variable or API key configuration.",
131
+ category: "authentication",
132
+ severity: "error",
133
+ actionable: true,
134
+ },
135
+ "Incorrect API key provided": {
136
+ message:
137
+ "OpenAI API key is invalid. Please verify your OPENAI_API_KEY is correct and active.",
138
+ category: "authentication",
139
+ severity: "error",
140
+ actionable: true,
141
+ },
142
+ RateLimitError: {
143
+ message:
144
+ "OpenAI rate limit exceeded. Please wait a moment and try again, or check your OpenAI usage limits.",
145
+ category: "network",
146
+ severity: "warning",
147
+ actionable: true,
148
+ },
149
+ InvalidRequestError: {
150
+ message:
151
+ "Invalid request to OpenAI API. Please check your request parameters and model configuration.",
152
+ category: "validation",
153
+ severity: "error",
154
+ actionable: true,
155
+ },
156
+ PermissionDeniedError: {
157
+ message:
158
+ "Permission denied for OpenAI API. Please check your API key permissions and billing status.",
159
+ category: "authentication",
160
+ severity: "error",
161
+ actionable: true,
162
+ },
163
+ NotFoundError: {
164
+ message: "OpenAI resource not found. Please check your model name and availability.",
165
+ category: "validation",
166
+ severity: "error",
167
+ actionable: true,
168
+ },
169
+ },
170
+ fallbacks: {
171
+ network:
172
+ "A network error occurred while connecting to the agent service. Please check your connection and ensure the agent service is running.",
173
+ connection:
174
+ "The connection to the agent service was lost unexpectedly. This may indicate an issue with the agent service.",
175
+ authentication: "Authentication failed. Please check your API keys and credentials.",
176
+ validation: "Invalid input or configuration. Please check your parameters and try again.",
177
+ unknown: "An unexpected error occurred. Please check the logs for more details.",
178
+ default: "An unexpected error occurred. Please check the logs for more details.",
179
+ },
180
+ contextTemplates: {
181
+ connection: "connection",
182
+ event_streaming_connection: "event streaming connection",
183
+ agent_streaming_connection: "agent streaming connection",
184
+ langgraph_agent_connection: "LangGraph agent connection",
185
+ },
186
+ };
187
+
188
+ /**
189
+ * Helper function to get error pattern configuration by key
190
+ */
191
+ export function getErrorPattern(key: string): ErrorPatternConfig | undefined {
192
+ return errorConfig.errorPatterns[key];
193
+ }
194
+
195
+ /**
196
+ * Helper function to get fallback message by category
197
+ */
198
+ export function getFallbackMessage(category: string): string {
199
+ return errorConfig.fallbacks[category] || errorConfig.fallbacks.default;
200
+ }
@@ -10,6 +10,7 @@ import { createYoga } from "graphql-yoga";
10
10
  import telemetry from "../telemetry-client";
11
11
  import { StateResolver } from "../../graphql/resolvers/state.resolver";
12
12
  import * as packageJson from "../../../package.json";
13
+ import { CopilotKitError, CopilotKitErrorCode } from "@copilotkit/shared";
13
14
 
14
15
  const logger = createLogger();
15
16
 
@@ -79,6 +80,9 @@ export type CommonConfig = {
79
80
  schema: ReturnType<typeof buildSchema>;
80
81
  plugins: Parameters<typeof createYoga>[0]["plugins"];
81
82
  context: (ctx: YogaInitialContext) => Promise<Partial<GraphQLContext>>;
83
+ maskedErrors: {
84
+ maskError: (error: any, message: string, isDev?: boolean) => any;
85
+ };
82
86
  };
83
87
 
84
88
  export function getCommonConfig(options: CreateCopilotRuntimeServerOptions): CommonConfig {
@@ -108,11 +112,50 @@ export function getCommonConfig(options: CreateCopilotRuntimeServerOptions): Com
108
112
  },
109
113
  });
110
114
 
115
+ // User error codes that should not be logged as server errors
116
+ const userErrorCodes = [
117
+ CopilotKitErrorCode.AGENT_NOT_FOUND,
118
+ CopilotKitErrorCode.API_NOT_FOUND,
119
+ CopilotKitErrorCode.REMOTE_ENDPOINT_NOT_FOUND,
120
+ CopilotKitErrorCode.CONFIGURATION_ERROR,
121
+ CopilotKitErrorCode.MISSING_PUBLIC_API_KEY_ERROR,
122
+ ];
123
+
111
124
  return {
112
125
  logging: createLogger({ component: "Yoga GraphQL", level: logLevel }),
113
126
  schema: buildSchema(),
114
127
  plugins: [useDeferStream(), addCustomHeaderPlugin],
115
128
  context: (ctx: YogaInitialContext): Promise<Partial<GraphQLContext>> =>
116
129
  createContext(ctx, options, contextLogger, options.properties),
130
+ // Suppress logging for user configuration errors
131
+ maskedErrors: {
132
+ maskError: (error: any, message: string, isDev?: boolean) => {
133
+ // Check if this is a user configuration error (could be wrapped in GraphQLError)
134
+ const originalError = error.originalError || error;
135
+ const extensions = error.extensions;
136
+ const errorCode = extensions?.code;
137
+
138
+ // Suppress logging for user errors based on error code
139
+ if (errorCode && userErrorCodes.includes(errorCode)) {
140
+ // Log user configuration errors at debug level instead
141
+ console.debug("User configuration error:", error.message);
142
+ return error;
143
+ }
144
+
145
+ // Check if the original error is a user error
146
+ if (
147
+ originalError instanceof CopilotKitError &&
148
+ userErrorCodes.includes(originalError.code)
149
+ ) {
150
+ // Log user configuration errors at debug level instead
151
+ console.debug("User configuration error:", error.message);
152
+ return error;
153
+ }
154
+
155
+ // For application errors, log normally and mask if needed
156
+ console.error("Application error:", error);
157
+ return error;
158
+ },
159
+ },
117
160
  };
118
161
  }
@@ -28,6 +28,7 @@ import {
28
28
  CopilotTraceHandler,
29
29
  CopilotTraceEvent,
30
30
  CopilotRequestContext,
31
+ ensureStructuredError,
31
32
  } from "@copilotkit/shared";
32
33
  import {
33
34
  CopilotServiceAdapter,
@@ -65,7 +66,7 @@ import { ExtensionsInput } from "../../graphql/inputs/extensions.input";
65
66
  import { ExtensionsResponse } from "../../graphql/types/extensions-response.type";
66
67
  import { LoadAgentStateResponse } from "../../graphql/types/load-agent-state-response.type";
67
68
  import { Client as LangGraphClient } from "@langchain/langgraph-sdk";
68
- import { langchainMessagesToCopilotKit } from "./remote-lg-action";
69
+ import { langchainMessagesToCopilotKit, isUserConfigurationError } from "./remote-lg-action";
69
70
  import { MetaEventInput } from "../../graphql/inputs/meta-event.input";
70
71
  import {
71
72
  CopilotObservabilityConfig,
@@ -89,6 +90,8 @@ import { LangGraphAgent } from "./langgraph/langgraph-agent";
89
90
  type CreateMCPClientFunction = (config: MCPEndpointConfig) => Promise<MCPClient>;
90
91
  // --- MCP Imports ---
91
92
 
93
+ import { generateHelpfulErrorMessage } from "../streaming";
94
+
92
95
  export interface CopilotRuntimeRequest {
93
96
  serviceAdapter: CopilotServiceAdapter;
94
97
  messages: MessageInput[];
@@ -746,9 +749,10 @@ please use an LLM adapter instead.`,
746
749
  if (error instanceof CopilotKitError) {
747
750
  structuredError = error;
748
751
  } else {
749
- // Convert non-CopilotKitErrors to structured errors
750
- console.error("Error getting response:", error);
751
- structuredError = this.convertStreamingErrorToStructured(error);
752
+ // Convert non-CopilotKitErrors to structured errors, but preserve already structured ones
753
+ structuredError = ensureStructuredError(error, (err) =>
754
+ this.convertStreamingErrorToStructured(err),
755
+ );
752
756
  }
753
757
 
754
758
  // Trace the error
@@ -948,10 +952,24 @@ please use an LLM adapter instead.`,
948
952
  if (response.status === 404) {
949
953
  throw new CopilotKitApiDiscoveryError({ url: fetchUrl });
950
954
  }
955
+
956
+ // Extract semantic error information from response body
957
+ let errorMessage = `HTTP ${response.status} error`;
958
+ try {
959
+ const errorBody = await response.text();
960
+ const parsedError = JSON.parse(errorBody);
961
+ if (parsedError.error && typeof parsedError.error === "string") {
962
+ errorMessage = parsedError.error;
963
+ }
964
+ } catch {
965
+ // If parsing fails, fall back to generic message
966
+ }
967
+
951
968
  throw new ResolvedCopilotKitError({
952
969
  status: response.status,
953
970
  url: fetchUrl,
954
971
  isRemoteEndpoint: true,
972
+ message: errorMessage,
955
973
  });
956
974
  }
957
975
 
@@ -992,7 +1010,20 @@ please use an LLM adapter instead.`,
992
1010
  let state: any = {};
993
1011
  try {
994
1012
  state = (await client.threads.getState(threadId)).values as any;
995
- } catch (error) {}
1013
+ } catch (error) {
1014
+ // All errors from agent state loading are user configuration issues
1015
+ const errorMessage = error instanceof Error ? error.message : String(error);
1016
+
1017
+ // Log user configuration errors at debug level to reduce noise
1018
+ console.debug(`Agent '${agentName}' configuration issue: ${errorMessage}`);
1019
+
1020
+ // Throw a configuration error - all agent state loading failures are user setup issues
1021
+ throw new ResolvedCopilotKitError({
1022
+ status: 400,
1023
+ message: `Agent '${agentName}' failed to execute: ${errorMessage}`,
1024
+ code: CopilotKitErrorCode.CONFIGURATION_ERROR,
1025
+ });
1026
+ }
996
1027
 
997
1028
  if (Object.keys(state).length === 0) {
998
1029
  return {
@@ -1193,8 +1224,6 @@ please use an LLM adapter instead.`,
1193
1224
  from(stream).subscribe({
1194
1225
  next: (event) => eventStream$.next(event),
1195
1226
  error: async (err) => {
1196
- console.error("Error in stream", err);
1197
-
1198
1227
  // Log error with observability if enabled
1199
1228
  if (this.observability?.enabled && publicApiKey) {
1200
1229
  try {
@@ -1216,8 +1245,10 @@ please use an LLM adapter instead.`,
1216
1245
  }
1217
1246
  }
1218
1247
 
1219
- // Convert network termination errors to structured errors
1220
- const structuredError = this.convertStreamingErrorToStructured(err);
1248
+ // Preserve structured CopilotKit errors, only convert unstructured errors
1249
+ const structuredError = ensureStructuredError(err, (error) =>
1250
+ this.convertStreamingErrorToStructured(error),
1251
+ );
1221
1252
 
1222
1253
  // Trace streaming errors
1223
1254
  await this.trace(
@@ -1325,12 +1356,9 @@ please use an LLM adapter instead.`,
1325
1356
  }
1326
1357
 
1327
1358
  // Ensure error is structured
1328
- let structuredError: CopilotKitError;
1329
- if (error instanceof CopilotKitError) {
1330
- structuredError = error;
1331
- } else {
1332
- structuredError = this.convertStreamingErrorToStructured(error);
1333
- }
1359
+ const structuredError = ensureStructuredError(error, (err) =>
1360
+ this.convertStreamingErrorToStructured(err),
1361
+ );
1334
1362
 
1335
1363
  // Trace the agent error
1336
1364
  await this.trace(
@@ -1477,50 +1505,30 @@ please use an LLM adapter instead.`,
1477
1505
  }
1478
1506
 
1479
1507
  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
- }
1508
+ // Determine a more helpful error message based on context
1509
+ let helpfulMessage = generateHelpfulErrorMessage(error, "agent streaming connection");
1493
1510
 
1494
- // Handle other network-related errors
1511
+ // For network-related errors, use CopilotKitLowLevelError to preserve the original error
1495
1512
  if (
1496
1513
  error?.message?.includes("fetch failed") ||
1497
1514
  error?.message?.includes("ECONNREFUSED") ||
1498
1515
  error?.message?.includes("ENOTFOUND") ||
1499
- error?.message?.includes("ETIMEDOUT")
1516
+ error?.message?.includes("ETIMEDOUT") ||
1517
+ error?.message?.includes("terminated") ||
1518
+ error?.cause?.code === "UND_ERR_SOCKET" ||
1519
+ error?.message?.includes("other side closed") ||
1520
+ error?.code === "UND_ERR_SOCKET"
1500
1521
  ) {
1501
1522
  return new CopilotKitLowLevelError({
1502
1523
  error: error instanceof Error ? error : new Error(String(error)),
1503
1524
  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,
1525
+ message: helpfulMessage,
1518
1526
  });
1519
1527
  }
1520
1528
 
1521
- // Default: convert unknown streaming errors
1529
+ // For all other errors, preserve the raw error in a basic CopilotKitError
1522
1530
  return new CopilotKitError({
1523
- message: `Agent streaming error: ${error?.message || String(error)}`,
1531
+ message: helpfulMessage,
1524
1532
  code: CopilotKitErrorCode.UNKNOWN,
1525
1533
  });
1526
1534
  }
@@ -1533,11 +1541,11 @@ please use an LLM adapter instead.`,
1533
1541
  ): Promise<void> {
1534
1542
  if (!this.onTrace) return;
1535
1543
 
1544
+ // Just check if publicApiKey is defined (regardless of validity)
1536
1545
  if (!publicApiKey) {
1537
1546
  if (!this.hasWarnedAboutTracing) {
1538
1547
  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",
1548
+ "CopilotKit: onTrace handler provided but requires publicApiKey to be defined for tracing to work.",
1541
1549
  );
1542
1550
  this.hasWarnedAboutTracing = true;
1543
1551
  }
@@ -22,6 +22,9 @@ import { parseJson, tryMap } from "@copilotkit/shared";
22
22
  import { ActionInput } from "../../graphql/inputs/action.input";
23
23
  import { fetchWithRetry } from "./retry-utils";
24
24
 
25
+ // Import the utility function from remote-lg-action
26
+ import { isUserConfigurationError } from "./remote-lg-action";
27
+
25
28
  export function constructLGCRemoteAction({
26
29
  endpoint,
27
30
  graphqlContext,
@@ -93,11 +96,33 @@ export function constructLGCRemoteAction({
93
96
  writeJsonLineResponseToEventStream(response, eventSource.eventStream$);
94
97
  return eventSource.processLangGraphEvents();
95
98
  } catch (error) {
99
+ // Preserve structured CopilotKit errors with semantic information
100
+ if (error instanceof CopilotKitError || error instanceof CopilotKitLowLevelError) {
101
+ // Distinguish between user errors and system errors for logging
102
+ if (isUserConfigurationError(error)) {
103
+ logger.debug(
104
+ { url: endpoint.deploymentUrl, error: error.message, code: error.code },
105
+ "User configuration error in LangGraph Platform agent",
106
+ );
107
+ } else {
108
+ logger.error(
109
+ { url: endpoint.deploymentUrl, error: error.message, type: error.constructor.name },
110
+ "LangGraph Platform agent error",
111
+ );
112
+ }
113
+ throw error; // Re-throw the structured error to preserve semantic information
114
+ }
115
+
116
+ // For other errors, log and wrap them
96
117
  logger.error(
97
118
  { url: endpoint.deploymentUrl, status: 500, body: error.message },
98
119
  "Failed to execute LangGraph Platform agent",
99
120
  );
100
- throw new Error("Failed to execute LangGraph Platform agent");
121
+ throw new CopilotKitLowLevelError({
122
+ error: error instanceof Error ? error : new Error(String(error)),
123
+ url: endpoint.deploymentUrl,
124
+ message: "Failed to execute LangGraph Platform agent",
125
+ });
101
126
  }
102
127
  },
103
128
  }));
@@ -180,7 +205,7 @@ export function constructRemoteActions({
180
205
  logger.debug({ actionName: action.name, result }, "Executed remote action");
181
206
  return result;
182
207
  } catch (error) {
183
- if (error instanceof CopilotKitError) {
208
+ if (error instanceof CopilotKitError || error instanceof CopilotKitLowLevelError) {
184
209
  throw error;
185
210
  }
186
211
  throw new CopilotKitLowLevelError({ error, url: fetchUrl });
@@ -275,7 +300,7 @@ export function constructRemoteActions({
275
300
  throw new Error("Unsupported agent type");
276
301
  }
277
302
  } catch (error) {
278
- if (error instanceof CopilotKitError) {
303
+ if (error instanceof CopilotKitError || error instanceof CopilotKitLowLevelError) {
279
304
  throw error;
280
305
  }
281
306
  throw new CopilotKitLowLevelError({ error, url: fetchUrl });