@copilotkit/runtime 1.9.2-next.8 → 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.
- package/CHANGELOG.md +8 -0
- package/dist/{chunk-IIXJVVTV.mjs → chunk-4JBKY7XT.mjs} +109 -75
- package/dist/chunk-4JBKY7XT.mjs.map +1 -0
- package/dist/{chunk-JWPSIGSA.mjs → chunk-5YGKE5SN.mjs} +2 -2
- package/dist/{chunk-5SG4WWXH.mjs → chunk-ALZ5H3VD.mjs} +2 -2
- package/dist/chunk-AMUJQ6IR.mjs +50 -0
- package/dist/chunk-AMUJQ6IR.mjs.map +1 -0
- package/dist/{chunk-KYCDL2KX.mjs → chunk-SMDVD4VG.mjs} +2 -2
- package/dist/{chunk-4TLMVLU4.mjs → chunk-UUXRYAB4.mjs} +2 -2
- package/dist/{chunk-5BIEM2UU.mjs → chunk-XWBDEXDA.mjs} +4 -3
- package/dist/{chunk-5BIEM2UU.mjs.map → chunk-XWBDEXDA.mjs.map} +1 -1
- package/dist/{chunk-WIXS6EG7.mjs → chunk-Z5GYTKMD.mjs} +2304 -2034
- package/dist/chunk-Z5GYTKMD.mjs.map +1 -0
- package/dist/{groq-adapter-25a2bd35.d.ts → groq-adapter-172a2ca4.d.ts} +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3280 -2932
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12 -8
- package/dist/index.mjs.map +1 -1
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.js +2828 -2480
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +9 -8
- package/dist/lib/integrations/index.d.ts +3 -3
- package/dist/lib/integrations/index.js +141 -86
- package/dist/lib/integrations/index.js.map +1 -1
- package/dist/lib/integrations/index.mjs +7 -6
- package/dist/lib/integrations/nest/index.d.ts +2 -2
- package/dist/lib/integrations/nest/index.js +141 -86
- package/dist/lib/integrations/nest/index.js.map +1 -1
- package/dist/lib/integrations/nest/index.mjs +5 -4
- package/dist/lib/integrations/node-express/index.d.ts +2 -2
- package/dist/lib/integrations/node-express/index.js +141 -86
- package/dist/lib/integrations/node-express/index.js.map +1 -1
- package/dist/lib/integrations/node-express/index.mjs +5 -4
- package/dist/lib/integrations/node-http/index.d.ts +2 -2
- package/dist/lib/integrations/node-http/index.js +141 -86
- package/dist/lib/integrations/node-http/index.js.map +1 -1
- package/dist/lib/integrations/node-http/index.mjs +4 -3
- package/dist/service-adapters/index.d.ts +5 -4
- package/dist/service-adapters/index.js +179 -104
- package/dist/service-adapters/index.js.map +1 -1
- package/dist/service-adapters/index.mjs +6 -2
- package/dist/service-adapters/shared/index.d.ts +9 -0
- package/dist/service-adapters/shared/index.js +72 -0
- package/dist/service-adapters/shared/index.js.map +1 -0
- package/dist/service-adapters/shared/index.mjs +8 -0
- package/dist/service-adapters/shared/index.mjs.map +1 -0
- package/dist/{shared-941d59dc.d.ts → shared-bd953ebf.d.ts} +8 -4
- package/dist/utils/index.d.ts +17 -1
- package/dist/utils/index.js +3 -2
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +1 -1
- package/package.json +2 -2
- package/src/agents/langgraph/event-source.ts +36 -38
- package/src/agents/langgraph/events.ts +19 -1
- package/src/graphql/resolvers/copilot.resolver.ts +84 -40
- package/src/lib/error-messages.ts +200 -0
- package/src/lib/integrations/shared.ts +43 -0
- package/src/lib/runtime/copilot-runtime.ts +56 -48
- package/src/lib/runtime/remote-action-constructors.ts +28 -3
- package/src/lib/runtime/remote-lg-action.ts +85 -3
- package/src/lib/streaming.ts +125 -36
- package/src/service-adapters/anthropic/anthropic-adapter.ts +3 -4
- package/src/service-adapters/events.ts +37 -81
- package/src/service-adapters/groq/groq-adapter.ts +66 -56
- package/src/service-adapters/index.ts +1 -0
- package/src/service-adapters/openai/openai-adapter.ts +18 -3
- package/src/service-adapters/shared/error-utils.ts +61 -0
- package/src/service-adapters/shared/index.ts +1 -0
- package/src/utils/failed-response-status-reasons.ts +23 -1
- package/dist/chunk-IIXJVVTV.mjs.map +0 -1
- package/dist/chunk-WIXS6EG7.mjs.map +0 -1
- package/dist/{chunk-JWPSIGSA.mjs.map → chunk-5YGKE5SN.mjs.map} +0 -0
- package/dist/{chunk-5SG4WWXH.mjs.map → chunk-ALZ5H3VD.mjs.map} +0 -0
- package/dist/{chunk-KYCDL2KX.mjs.map → chunk-SMDVD4VG.mjs.map} +0 -0
- package/dist/{chunk-4TLMVLU4.mjs.map → chunk-UUXRYAB4.mjs.map} +0 -0
- 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
|
-
|
|
751
|
-
|
|
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
|
-
//
|
|
1220
|
-
const structuredError =
|
|
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
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
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
|
-
//
|
|
1481
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
1529
|
+
// For all other errors, preserve the raw error in a basic CopilotKitError
|
|
1522
1530
|
return new CopilotKitError({
|
|
1523
|
-
message:
|
|
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
|
|
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 });
|
|
@@ -19,9 +19,28 @@ import { CustomEventNames, LangGraphEventTypes } from "../../agents/langgraph/ev
|
|
|
19
19
|
import telemetry from "../telemetry-client";
|
|
20
20
|
import { MetaEventInput } from "../../graphql/inputs/meta-event.input";
|
|
21
21
|
import { MetaEventName } from "../../graphql/types/meta-events.type";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
parseJson,
|
|
24
|
+
CopilotKitMisuseError,
|
|
25
|
+
CopilotKitLowLevelError,
|
|
26
|
+
CopilotKitError,
|
|
27
|
+
} from "@copilotkit/shared";
|
|
23
28
|
import { RemoveMessage } from "@langchain/core/messages";
|
|
24
29
|
import { RETRY_CONFIG, isRetryableError, sleep, calculateDelay } from "./retry-utils";
|
|
30
|
+
import { generateHelpfulErrorMessage } from "../streaming";
|
|
31
|
+
|
|
32
|
+
// Utility to determine if an error is a user configuration issue vs system error
|
|
33
|
+
export function isUserConfigurationError(error: any): boolean {
|
|
34
|
+
return (
|
|
35
|
+
(error instanceof CopilotKitError || error instanceof CopilotKitLowLevelError) &&
|
|
36
|
+
(error.code === "NETWORK_ERROR" ||
|
|
37
|
+
error.code === "AUTHENTICATION_ERROR" ||
|
|
38
|
+
error.statusCode === 401 ||
|
|
39
|
+
error.statusCode === 403 ||
|
|
40
|
+
error.message?.toLowerCase().includes("authentication") ||
|
|
41
|
+
error.message?.toLowerCase().includes("api key"))
|
|
42
|
+
);
|
|
43
|
+
}
|
|
25
44
|
|
|
26
45
|
type State = Record<string, any>;
|
|
27
46
|
|
|
@@ -128,6 +147,15 @@ export async function execute(args: ExecutionArgs): Promise<ReadableStream<Uint8
|
|
|
128
147
|
See more: https://docs.copilotkit.ai/troubleshooting/common-issues`,
|
|
129
148
|
});
|
|
130
149
|
} else {
|
|
150
|
+
// Preserve already structured CopilotKit errors with semantic information
|
|
151
|
+
if (
|
|
152
|
+
lastError instanceof CopilotKitError ||
|
|
153
|
+
lastError instanceof CopilotKitLowLevelError ||
|
|
154
|
+
(lastError instanceof Error && lastError.name && lastError.name.includes("CopilotKit"))
|
|
155
|
+
) {
|
|
156
|
+
throw lastError; // Re-throw to preserve semantic information and visibility settings
|
|
157
|
+
}
|
|
158
|
+
|
|
131
159
|
throw new CopilotKitMisuseError({
|
|
132
160
|
message: `
|
|
133
161
|
The LangGraph client threw unhandled error ${lastError}.
|
|
@@ -341,7 +369,43 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
341
369
|
if (!["events", "values", "error", "updates"].includes(streamResponseChunk.event)) continue;
|
|
342
370
|
|
|
343
371
|
if (streamResponseChunk.event === "error") {
|
|
344
|
-
|
|
372
|
+
const errorData = streamResponseChunk.data;
|
|
373
|
+
|
|
374
|
+
// Check if this is a structured error from our Python agent
|
|
375
|
+
if (errorData && typeof errorData === "object" && "error_details" in errorData) {
|
|
376
|
+
const errorDetails = (errorData as any).error_details;
|
|
377
|
+
|
|
378
|
+
// Create a structured error with preserved semantic information
|
|
379
|
+
const preservedError = new CopilotKitLowLevelError({
|
|
380
|
+
error: new Error(errorDetails.message),
|
|
381
|
+
url: "langgraph platform agent",
|
|
382
|
+
message: `${errorDetails.type}: ${errorDetails.message}`,
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Add additional error context
|
|
386
|
+
if (errorDetails.status_code) {
|
|
387
|
+
(preservedError as any).statusCode = errorDetails.status_code;
|
|
388
|
+
}
|
|
389
|
+
if (errorDetails.response_data) {
|
|
390
|
+
(preservedError as any).responseData = errorDetails.response_data;
|
|
391
|
+
}
|
|
392
|
+
(preservedError as any).agentName = errorDetails.agent_name;
|
|
393
|
+
(preservedError as any).originalErrorType = errorDetails.type;
|
|
394
|
+
|
|
395
|
+
throw preservedError;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Fallback for generic error messages
|
|
399
|
+
const helpfulMessage = generateHelpfulErrorMessage(
|
|
400
|
+
new Error(errorData.message),
|
|
401
|
+
"LangGraph Platform agent",
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
throw new CopilotKitLowLevelError({
|
|
405
|
+
error: new Error(errorData.message),
|
|
406
|
+
url: "langgraph platform agent",
|
|
407
|
+
message: helpfulMessage,
|
|
408
|
+
});
|
|
345
409
|
}
|
|
346
410
|
|
|
347
411
|
// Force event type, as data is not properly defined on the LG side.
|
|
@@ -507,11 +571,29 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
507
571
|
|
|
508
572
|
return Promise.resolve();
|
|
509
573
|
} catch (e) {
|
|
510
|
-
|
|
574
|
+
// Distinguish between user errors and system errors for logging
|
|
575
|
+
if (isUserConfigurationError(e)) {
|
|
576
|
+
// Log user errors at debug level to reduce noise
|
|
577
|
+
logger.debug({ error: e.message, code: e.code }, "User configuration error");
|
|
578
|
+
} else {
|
|
579
|
+
// Log actual system errors at error level
|
|
580
|
+
logger.error(e);
|
|
581
|
+
}
|
|
582
|
+
|
|
511
583
|
telemetry.capture("oss.runtime.agent_execution_stream_errored", {
|
|
512
584
|
...streamInfo,
|
|
513
585
|
error: e.message,
|
|
514
586
|
});
|
|
587
|
+
|
|
588
|
+
// Re-throw CopilotKit errors so they can be handled properly at higher levels
|
|
589
|
+
if (
|
|
590
|
+
e instanceof CopilotKitError ||
|
|
591
|
+
e instanceof CopilotKitLowLevelError ||
|
|
592
|
+
(e instanceof Error && e.name && e.name.includes("CopilotKit"))
|
|
593
|
+
) {
|
|
594
|
+
throw e;
|
|
595
|
+
}
|
|
596
|
+
|
|
515
597
|
return Promise.resolve();
|
|
516
598
|
}
|
|
517
599
|
}
|