@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.
Files changed (60) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/dist/{chunk-Z5GYTKMD.mjs → chunk-EK5RTZVJ.mjs} +225 -149
  3. package/dist/chunk-EK5RTZVJ.mjs.map +1 -0
  4. package/dist/{chunk-SMDVD4VG.mjs → chunk-KCYFFRJY.mjs} +2 -2
  5. package/dist/{chunk-4JBKY7XT.mjs → chunk-QLLV2QVK.mjs} +48 -28
  6. package/dist/chunk-QLLV2QVK.mjs.map +1 -0
  7. package/dist/{chunk-5YGKE5SN.mjs → chunk-R5D7D7YN.mjs} +2 -2
  8. package/dist/{chunk-UUXRYAB4.mjs → chunk-RCCT2GOF.mjs} +2 -2
  9. package/dist/{chunk-ALZ5H3VD.mjs → chunk-YGS5B7PN.mjs} +2 -2
  10. package/dist/{groq-adapter-172a2ca4.d.ts → groq-adapter-742818f2.d.ts} +5 -1
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.js +267 -171
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.mjs +9 -9
  15. package/dist/{langserve-fc5cac89.d.ts → langserve-3e8d0e06.d.ts} +6 -0
  16. package/dist/lib/index.d.ts +155 -5
  17. package/dist/lib/index.js +221 -168
  18. package/dist/lib/index.js.map +1 -1
  19. package/dist/lib/index.mjs +9 -9
  20. package/dist/lib/integrations/index.d.ts +3 -3
  21. package/dist/lib/integrations/index.js +11 -11
  22. package/dist/lib/integrations/index.js.map +1 -1
  23. package/dist/lib/integrations/index.mjs +8 -8
  24. package/dist/lib/integrations/nest/index.d.ts +2 -2
  25. package/dist/lib/integrations/nest/index.js +11 -11
  26. package/dist/lib/integrations/nest/index.js.map +1 -1
  27. package/dist/lib/integrations/nest/index.mjs +4 -4
  28. package/dist/lib/integrations/node-express/index.d.ts +2 -2
  29. package/dist/lib/integrations/node-express/index.js +11 -11
  30. package/dist/lib/integrations/node-express/index.js.map +1 -1
  31. package/dist/lib/integrations/node-express/index.mjs +4 -4
  32. package/dist/lib/integrations/node-http/index.d.ts +2 -2
  33. package/dist/lib/integrations/node-http/index.js +11 -11
  34. package/dist/lib/integrations/node-http/index.js.map +1 -1
  35. package/dist/lib/integrations/node-http/index.mjs +3 -3
  36. package/dist/service-adapters/index.d.ts +5 -4
  37. package/dist/service-adapters/index.js +47 -27
  38. package/dist/service-adapters/index.js.map +1 -1
  39. package/dist/service-adapters/index.mjs +1 -1
  40. package/dist/{shared-bd953ebf.d.ts → shared-96b46379.d.ts} +16 -18
  41. package/package.json +11 -11
  42. package/src/graphql/resolvers/copilot.resolver.ts +1 -2
  43. package/src/lib/runtime/__tests__/{copilot-runtime-trace.test.ts → copilot-runtime-error.test.ts} +27 -27
  44. package/src/lib/runtime/__tests__/mcp-tools-utils.test.ts +464 -0
  45. package/src/lib/runtime/agui-action.ts +9 -3
  46. package/src/lib/runtime/copilot-runtime.ts +112 -124
  47. package/src/lib/runtime/mcp-tools-utils.ts +84 -18
  48. package/src/lib/runtime/remote-actions.ts +6 -0
  49. package/src/service-adapters/anthropic/anthropic-adapter.ts +64 -4
  50. package/src/service-adapters/anthropic/utils.ts +3 -8
  51. package/src/service-adapters/events.ts +40 -1
  52. package/src/service-adapters/google/google-genai-adapter.ts +5 -0
  53. package/src/service-adapters/openai/openai-adapter.ts +0 -14
  54. package/tests/service-adapters/anthropic/anthropic-adapter.test.ts +172 -387
  55. package/dist/chunk-4JBKY7XT.mjs.map +0 -1
  56. package/dist/chunk-Z5GYTKMD.mjs.map +0 -1
  57. /package/dist/{chunk-SMDVD4VG.mjs.map → chunk-KCYFFRJY.mjs.map} +0 -0
  58. /package/dist/{chunk-5YGKE5SN.mjs.map → chunk-R5D7D7YN.mjs.map} +0 -0
  59. /package/dist/{chunk-UUXRYAB4.mjs.map → chunk-RCCT2GOF.mjs.map} +0 -0
  60. /package/dist/{chunk-ALZ5H3VD.mjs.map → chunk-YGS5B7PN.mjs.map} +0 -0
package/dist/index.js CHANGED
@@ -44,7 +44,7 @@ var require_package = __commonJS({
44
44
  publishConfig: {
45
45
  access: "public"
46
46
  },
47
- version: "1.9.2-next.9",
47
+ version: "1.9.3-next.0",
48
48
  sideEffects: false,
49
49
  main: "./dist/index.js",
50
50
  module: "./dist/index.mjs",
@@ -82,11 +82,11 @@ var require_package = __commonJS({
82
82
  "zod-to-json-schema": "^3.23.5"
83
83
  },
84
84
  dependencies: {
85
- "@ag-ui/client": "0.0.28",
86
- "@ag-ui/core": "0.0.28",
87
- "@ag-ui/encoder": "0.0.28",
88
- "@ag-ui/langgraph": "0.0.4",
89
- "@ag-ui/proto": "0.0.28",
85
+ "@ag-ui/client": "0.0.35",
86
+ "@ag-ui/core": "0.0.35",
87
+ "@ag-ui/encoder": "0.0.35",
88
+ "@ag-ui/langgraph": "0.0.7",
89
+ "@ag-ui/proto": "0.0.35",
90
90
  "@anthropic-ai/sdk": "^0.27.3",
91
91
  "@copilotkit/shared": "workspace:*",
92
92
  "@graphql-yoga/plugin-defer-stream": "^3.3.1",
@@ -114,10 +114,10 @@ var require_package = __commonJS({
114
114
  zod: "^3.23.3"
115
115
  },
116
116
  peerDependencies: {
117
- "@ag-ui/client": ">=0.0.28",
118
- "@ag-ui/core": ">=0.0.28",
119
- "@ag-ui/encoder": ">=0.0.28",
120
- "@ag-ui/proto": ">=0.0.28"
117
+ "@ag-ui/client": ">=0.0.34",
118
+ "@ag-ui/core": ">=0.0.34",
119
+ "@ag-ui/encoder": ">=0.0.34",
120
+ "@ag-ui/proto": ">=0.0.34"
121
121
  },
122
122
  keywords: [
123
123
  "copilotkit",
@@ -431,7 +431,6 @@ var OpenAIAdapter = class {
431
431
  const { threadId: threadIdFromRequest, model = this.model, messages, actions, eventSource, forwardedParameters } = request;
432
432
  const tools = actions.map(convertActionInputToOpenAITool);
433
433
  const threadId = threadIdFromRequest ?? (0, import_shared3.randomUUID)();
434
- console.log("messages", messages);
435
434
  const validToolUseIds = /* @__PURE__ */ new Set();
436
435
  for (const message of messages) {
437
436
  if (message.isActionExecutionMessage()) {
@@ -461,29 +460,6 @@ var OpenAIAdapter = class {
461
460
  }
462
461
  };
463
462
  }
464
- console.log("INPUT", {
465
- model,
466
- stream: true,
467
- messages: openaiMessages,
468
- ...tools.length > 0 && {
469
- tools
470
- },
471
- ...(forwardedParameters == null ? void 0 : forwardedParameters.maxTokens) && {
472
- max_tokens: forwardedParameters.maxTokens
473
- },
474
- ...(forwardedParameters == null ? void 0 : forwardedParameters.stop) && {
475
- stop: forwardedParameters.stop
476
- },
477
- ...toolChoice && {
478
- tool_choice: toolChoice
479
- },
480
- ...this.disableParallelToolCalls && {
481
- parallel_tool_calls: false
482
- },
483
- ...(forwardedParameters == null ? void 0 : forwardedParameters.temperature) && {
484
- temperature: forwardedParameters.temperature
485
- }
486
- });
487
463
  try {
488
464
  const stream = this.openai.beta.chat.completions.stream({
489
465
  model,
@@ -865,6 +841,7 @@ var GoogleGenerativeAIAdapter = class extends LangChainAdapter {
865
841
  return message.content && String(message.content).trim().length > 0 || message.tool_calls && message.tool_calls.length > 0;
866
842
  });
867
843
  const model = new import_google_gauth.ChatGoogle({
844
+ apiKey: (options == null ? void 0 : options.apiKey) ?? process.env.GOOGLE_API_KEY,
868
845
  modelName: (options == null ? void 0 : options.model) ?? "gemini-1.5-pro",
869
846
  apiVersion: "v1beta"
870
847
  }).bindTools(tools);
@@ -3182,7 +3159,7 @@ function convertMessageToAnthropicMessage(message) {
3182
3159
  content: [
3183
3160
  {
3184
3161
  type: "tool_result",
3185
- content: message.result,
3162
+ content: message.result || "Action completed successfully",
3186
3163
  tool_use_id: message.actionExecutionId
3187
3164
  }
3188
3165
  ]
@@ -3206,6 +3183,22 @@ var AnthropicAdapter = class {
3206
3183
  this.model = params.model;
3207
3184
  }
3208
3185
  }
3186
+ shouldGenerateFallbackResponse(messages) {
3187
+ var _a, _b, _c;
3188
+ if (messages.length === 0)
3189
+ return false;
3190
+ const lastMessage = messages[messages.length - 1];
3191
+ const endsWithToolResult = lastMessage.role === "user" && Array.isArray(lastMessage.content) && lastMessage.content.some((content) => content.type === "tool_result");
3192
+ if (messages.length >= 3 && endsWithToolResult) {
3193
+ const lastThree = messages.slice(-3);
3194
+ const hasRecentToolPattern = ((_a = lastThree[0]) == null ? void 0 : _a.role) === "user" && // Initial user message
3195
+ ((_b = lastThree[1]) == null ? void 0 : _b.role) === "assistant" && // Assistant tool use
3196
+ Array.isArray(lastThree[1].content) && lastThree[1].content.some((content) => content.type === "tool_use") && ((_c = lastThree[2]) == null ? void 0 : _c.role) === "user" && // Tool result
3197
+ Array.isArray(lastThree[2].content) && lastThree[2].content.some((content) => content.type === "tool_result");
3198
+ return hasRecentToolPattern;
3199
+ }
3200
+ return endsWithToolResult;
3201
+ }
3209
3202
  async process(request) {
3210
3203
  const { threadId, model = this.model, messages: rawMessages, actions, eventSource, forwardedParameters } = request;
3211
3204
  const tools = actions.map(convertActionInputToAnthropicTool);
@@ -3220,18 +3213,22 @@ var AnthropicAdapter = class {
3220
3213
  validToolUseIds.add(message.id);
3221
3214
  }
3222
3215
  }
3216
+ const processedToolResultIds = /* @__PURE__ */ new Set();
3223
3217
  const anthropicMessages = messages.map((message) => {
3224
3218
  if (message.isResultMessage()) {
3225
3219
  if (!validToolUseIds.has(message.actionExecutionId)) {
3226
3220
  return null;
3227
3221
  }
3228
- validToolUseIds.delete(message.actionExecutionId);
3222
+ if (processedToolResultIds.has(message.actionExecutionId)) {
3223
+ return null;
3224
+ }
3225
+ processedToolResultIds.add(message.actionExecutionId);
3229
3226
  return {
3230
3227
  role: "user",
3231
3228
  content: [
3232
3229
  {
3233
3230
  type: "tool_result",
3234
- content: message.result,
3231
+ content: message.result || "Action completed successfully",
3235
3232
  tool_use_id: message.actionExecutionId
3236
3233
  }
3237
3234
  ]
@@ -3277,11 +3274,13 @@ var AnthropicAdapter = class {
3277
3274
  let currentMessageId = (0, import_shared10.randomId)();
3278
3275
  let currentToolCallId = (0, import_shared10.randomId)();
3279
3276
  let filterThinkingTextBuffer = new FilterThinkingTextBuffer();
3277
+ let hasReceivedContent = false;
3280
3278
  try {
3281
3279
  for await (const chunk of stream) {
3282
3280
  if (chunk.type === "message_start") {
3283
3281
  currentMessageId = chunk.message.id;
3284
3282
  } else if (chunk.type === "content_block_start") {
3283
+ hasReceivedContent = true;
3285
3284
  if (chunk.content_block.type === "text") {
3286
3285
  didOutputText = false;
3287
3286
  filterThinkingTextBuffer.reset();
@@ -3333,6 +3332,27 @@ var AnthropicAdapter = class {
3333
3332
  } catch (error) {
3334
3333
  throw convertServiceAdapterError(error, "Anthropic");
3335
3334
  }
3335
+ if (!hasReceivedContent && this.shouldGenerateFallbackResponse(limitedMessages)) {
3336
+ let fallbackContent = "Task completed successfully.";
3337
+ const lastMessage = limitedMessages[limitedMessages.length - 1];
3338
+ if ((lastMessage == null ? void 0 : lastMessage.role) === "user" && Array.isArray(lastMessage.content)) {
3339
+ const toolResult = lastMessage.content.find((c) => c.type === "tool_result");
3340
+ if ((toolResult == null ? void 0 : toolResult.content) && toolResult.content !== "Action completed successfully") {
3341
+ fallbackContent = toolResult.content;
3342
+ }
3343
+ }
3344
+ currentMessageId = (0, import_shared10.randomId)();
3345
+ eventStream$.sendTextMessageStart({
3346
+ messageId: currentMessageId
3347
+ });
3348
+ eventStream$.sendTextMessageContent({
3349
+ messageId: currentMessageId,
3350
+ content: fallbackContent
3351
+ });
3352
+ eventStream$.sendTextMessageEnd({
3353
+ messageId: currentMessageId
3354
+ });
3355
+ }
3336
3356
  eventStream$.complete();
3337
3357
  });
3338
3358
  } catch (error) {
@@ -4583,7 +4603,7 @@ function extractParametersFromSchema(toolOrSchema) {
4583
4603
  var _a;
4584
4604
  const parameters = [];
4585
4605
  const schema = "schema" in (toolOrSchema || {}) ? toolOrSchema.schema : toolOrSchema;
4586
- const toolParameters = (schema == null ? void 0 : schema.parameters) || ((_a = schema == null ? void 0 : schema.parameters) == null ? void 0 : _a.jsonSchema);
4606
+ const toolParameters = ((_a = schema == null ? void 0 : schema.parameters) == null ? void 0 : _a.jsonSchema) || (schema == null ? void 0 : schema.parameters);
4587
4607
  const properties = toolParameters == null ? void 0 : toolParameters.properties;
4588
4608
  const requiredParams = new Set((toolParameters == null ? void 0 : toolParameters.required) || []);
4589
4609
  if (!properties) {
@@ -4592,12 +4612,29 @@ function extractParametersFromSchema(toolOrSchema) {
4592
4612
  for (const paramName in properties) {
4593
4613
  if (Object.prototype.hasOwnProperty.call(properties, paramName)) {
4594
4614
  const paramDef = properties[paramName];
4615
+ let type = paramDef.type || "string";
4616
+ let description = paramDef.description || "";
4617
+ if (type === "array" && paramDef.items) {
4618
+ const itemType = paramDef.items.type || "object";
4619
+ if (itemType === "object" && paramDef.items.properties) {
4620
+ const itemProperties = Object.keys(paramDef.items.properties).join(", ");
4621
+ description = description + (description ? " " : "") + `Array of objects with properties: ${itemProperties}`;
4622
+ } else {
4623
+ type = `array<${itemType}>`;
4624
+ }
4625
+ }
4626
+ if (paramDef.enum && Array.isArray(paramDef.enum)) {
4627
+ const enumValues = paramDef.enum.join(" | ");
4628
+ description = description + (description ? " " : "") + `Allowed values: ${enumValues}`;
4629
+ }
4630
+ if (type === "object" && paramDef.properties) {
4631
+ const objectProperties = Object.keys(paramDef.properties).join(", ");
4632
+ description = description + (description ? " " : "") + `Object with properties: ${objectProperties}`;
4633
+ }
4595
4634
  parameters.push({
4596
4635
  name: paramName,
4597
- // Infer type, default to string. MCP schemas might have more complex types.
4598
- // This might need refinement based on common MCP schema practices.
4599
- type: paramDef.type || "string",
4600
- description: paramDef.description,
4636
+ type,
4637
+ description,
4601
4638
  required: requiredParams.has(paramName)
4602
4639
  });
4603
4640
  }
@@ -4611,9 +4648,7 @@ function convertMCPToolsToActions(mcpTools, mcpEndpoint) {
4611
4648
  const parameters = extractParametersFromSchema(tool);
4612
4649
  const handler = /* @__PURE__ */ __name(async (params) => {
4613
4650
  try {
4614
- const result = await tool.execute({
4615
- params
4616
- });
4651
+ const result = await tool.execute(params);
4617
4652
  return typeof result === "string" ? result : JSON.stringify(result);
4618
4653
  } catch (error) {
4619
4654
  console.error(`Error executing MCP tool '${toolName}' from endpoint ${mcpEndpoint}:`, error);
@@ -4639,17 +4674,38 @@ function generateMcpToolInstructions(toolsMap) {
4639
4674
  }
4640
4675
  const toolEntries = Object.entries(toolsMap);
4641
4676
  const toolsDoc = toolEntries.map(([name, tool]) => {
4677
+ var _a;
4642
4678
  let paramsDoc = " No parameters required";
4643
4679
  try {
4644
4680
  if (tool.schema && typeof tool.schema === "object") {
4645
4681
  const schema = tool.schema;
4646
- if (schema.properties) {
4647
- const requiredParams = schema.required || [];
4648
- const paramsList = Object.entries(schema.properties).map(([paramName, propSchema]) => {
4682
+ const toolParameters = ((_a = schema.parameters) == null ? void 0 : _a.jsonSchema) || schema.parameters;
4683
+ const properties = (toolParameters == null ? void 0 : toolParameters.properties) || schema.properties;
4684
+ const requiredParams = (toolParameters == null ? void 0 : toolParameters.required) || schema.required || [];
4685
+ if (properties) {
4686
+ const paramsList = Object.entries(properties).map(([paramName, propSchema]) => {
4649
4687
  const propDetails = propSchema;
4650
4688
  const requiredMark = requiredParams.includes(paramName) ? "*" : "";
4651
- const typeInfo = propDetails.type || "any";
4652
- const description = propDetails.description ? ` - ${propDetails.description}` : "";
4689
+ let typeInfo = propDetails.type || "any";
4690
+ let description = propDetails.description ? ` - ${propDetails.description}` : "";
4691
+ if (typeInfo === "array" && propDetails.items) {
4692
+ const itemType = propDetails.items.type || "object";
4693
+ if (itemType === "object" && propDetails.items.properties) {
4694
+ const itemProps = Object.keys(propDetails.items.properties).join(", ");
4695
+ typeInfo = `array<object>`;
4696
+ description = description + (description ? " " : " - ") + `Array of objects with properties: ${itemProps}`;
4697
+ } else {
4698
+ typeInfo = `array<${itemType}>`;
4699
+ }
4700
+ }
4701
+ if (propDetails.enum && Array.isArray(propDetails.enum)) {
4702
+ const enumValues = propDetails.enum.join(" | ");
4703
+ description = description + (description ? " " : " - ") + `Allowed values: ${enumValues}`;
4704
+ }
4705
+ if (typeInfo === "object" && propDetails.properties) {
4706
+ const objectProps = Object.keys(propDetails.properties).join(", ");
4707
+ description = description + (description ? " " : " - ") + `Object with properties: ${objectProps}`;
4708
+ }
4653
4709
  return ` - ${paramName}${requiredMark} (${typeInfo})${description}`;
4654
4710
  });
4655
4711
  if (paramsList.length > 0) {
@@ -4670,8 +4726,11 @@ ${toolsDoc}
4670
4726
  When using these tools:
4671
4727
  1. Only provide valid parameters according to their type requirements
4672
4728
  2. Required parameters are marked with *
4673
- 3. Format API calls correctly with the expected parameter structure
4674
- 4. Always check tool responses to determine your next action`;
4729
+ 3. For array parameters, provide data in the correct array format
4730
+ 4. For object parameters, include all required nested properties
4731
+ 5. For enum parameters, use only the allowed values listed
4732
+ 6. Format API calls correctly with the expected parameter structure
4733
+ 7. Always check tool responses to determine your next action`;
4675
4734
  }
4676
4735
  __name(generateMcpToolInstructions, "generateMcpToolInstructions");
4677
4736
 
@@ -4686,8 +4745,8 @@ var CopilotRuntime = class {
4686
4745
  delegateAgentProcessingToServiceAdapter;
4687
4746
  observability;
4688
4747
  availableAgents;
4689
- onTrace;
4690
- hasWarnedAboutTracing = false;
4748
+ onError;
4749
+ hasWarnedAboutError = false;
4691
4750
  // +++ MCP Properties +++
4692
4751
  mcpServersConfig;
4693
4752
  mcpActionCache = /* @__PURE__ */ new Map();
@@ -4713,7 +4772,7 @@ var CopilotRuntime = class {
4713
4772
  this.delegateAgentProcessingToServiceAdapter = (params == null ? void 0 : params.delegateAgentProcessingToServiceAdapter) || false;
4714
4773
  this.observability = params == null ? void 0 : params.observability_c;
4715
4774
  this.agents = (params == null ? void 0 : params.agents) ?? {};
4716
- this.onTrace = params == null ? void 0 : params.onTrace;
4775
+ this.onError = params == null ? void 0 : params.onError;
4717
4776
  this.mcpServersConfig = params == null ? void 0 : params.mcpServers;
4718
4777
  this.createMCPClientImpl = params == null ? void 0 : params.createMCPClient;
4719
4778
  if (this.mcpServersConfig && this.mcpServersConfig.length > 0 && !this.createMCPClientImpl) {
@@ -4758,7 +4817,7 @@ var CopilotRuntime = class {
4758
4817
  if (!mcpToolInstructions) {
4759
4818
  return messages;
4760
4819
  }
4761
- const instructions = "You have access to the following tools provided by external Model Context Protocol (MCP) servers:\n" + mcpToolInstructions + "\nUse them when appropriate to fulfill the user's request.";
4820
+ const instructions = mcpToolInstructions + "\nUse them when appropriate to fulfill the user's request.";
4762
4821
  const systemMessageIndex = messages.findIndex((msg) => {
4763
4822
  var _a;
4764
4823
  return ((_a = msg.textMessage) == null ? void 0 : _a.role) === "system";
@@ -4789,30 +4848,30 @@ var CopilotRuntime = class {
4789
4848
  async processRuntimeRequest(request) {
4790
4849
  var _a, _b, _c, _d, _e;
4791
4850
  const { serviceAdapter, messages: rawMessages, actions: clientSideActionsInput, threadId, runId, outputMessagesPromise, graphqlContext, forwardedParameters, url, extensions, agentSession, agentStates, publicApiKey } = request;
4792
- const eventSource = new RuntimeEventSource();
4793
- const requestStartTime = Date.now();
4794
- const streamedChunks = [];
4795
- await this.trace("request", {
4796
- threadId,
4797
- runId,
4798
- source: "runtime",
4799
- request: {
4800
- operation: "processRuntimeRequest",
4801
- method: "POST",
4802
- url,
4803
- startTime: requestStartTime
4851
+ const eventSource = new RuntimeEventSource({
4852
+ errorHandler: async (error, context) => {
4853
+ await this.error("error", context, error, publicApiKey);
4804
4854
  },
4805
- agent: agentSession ? {
4806
- name: agentSession.agentName
4807
- } : void 0,
4808
- messages: {
4809
- input: rawMessages,
4810
- messageCount: rawMessages.length
4811
- },
4812
- technical: {
4813
- environment: process.env.NODE_ENV
4855
+ errorContext: {
4856
+ threadId,
4857
+ runId,
4858
+ source: "runtime",
4859
+ request: {
4860
+ operation: "processRuntimeRequest",
4861
+ method: "POST",
4862
+ url,
4863
+ startTime: Date.now()
4864
+ },
4865
+ agent: agentSession ? {
4866
+ name: agentSession.agentName
4867
+ } : void 0,
4868
+ technical: {
4869
+ environment: process.env.NODE_ENV
4870
+ }
4814
4871
  }
4815
- }, void 0, publicApiKey);
4872
+ });
4873
+ const requestStartTime = Date.now();
4874
+ const streamedChunks = [];
4816
4875
  try {
4817
4876
  if (Object.keys(this.agents).length && (agentSession == null ? void 0 : agentSession.agentName) && !this.delegateAgentProcessingToServiceAdapter) {
4818
4877
  this.agents = {
@@ -4988,7 +5047,7 @@ please use an LLM adapter instead.`
4988
5047
  } else {
4989
5048
  structuredError = (0, import_shared18.ensureStructuredError)(error, (err) => this.convertStreamingErrorToStructured(err));
4990
5049
  }
4991
- await this.trace("error", {
5050
+ await this.error("error", {
4992
5051
  threadId,
4993
5052
  runId,
4994
5053
  source: "runtime",
@@ -5014,10 +5073,8 @@ please use an LLM adapter instead.`
5014
5073
  }
5015
5074
  }
5016
5075
  async getAllAgents(graphqlContext) {
5017
- const [agentsWithEndpoints, aguiAgents] = await Promise.all([
5018
- this.discoverAgentsFromEndpoints(graphqlContext),
5019
- this.discoverAgentsFromAgui()
5020
- ]);
5076
+ const agentsWithEndpoints = await this.discoverAgentsFromEndpoints(graphqlContext);
5077
+ const aguiAgents = this.discoverAgentsFromAgui();
5021
5078
  this.availableAgents = [
5022
5079
  ...agentsWithEndpoints,
5023
5080
  ...aguiAgents
@@ -5117,40 +5174,15 @@ please use an LLM adapter instead.`
5117
5174
  }, Promise.resolve([]));
5118
5175
  return agents;
5119
5176
  }
5120
- async discoverAgentsFromAgui() {
5121
- const agents = Object.values(this.agents ?? []).reduce(async (acc, agent) => {
5122
- const agents2 = await acc;
5123
- const client = agent.client;
5124
- let data = [];
5125
- try {
5126
- data = await client.assistants.search();
5127
- if (data && "detail" in data && data.detail.toLowerCase() === "not found") {
5128
- throw new import_shared18.CopilotKitAgentDiscoveryError({
5129
- availableAgents: this.availableAgents
5130
- });
5131
- }
5132
- } catch (e) {
5133
- throw new import_shared18.CopilotKitMisuseError({
5134
- message: `
5135
- Failed to find or contact agent ${agent.graphId}.
5136
- Make sure the LangGraph API is running and the agent is defined in langgraph.json
5137
-
5138
- See more: https://docs.copilotkit.ai/troubleshooting/common-issues`
5139
- });
5140
- }
5141
- const endpointAgents = data.map((entry) => ({
5142
- name: entry.graph_id,
5143
- id: entry.assistant_id,
5144
- description: ""
5145
- }));
5146
- return [
5147
- ...agents2,
5148
- ...endpointAgents
5149
- ];
5150
- }, Promise.resolve([]));
5151
- return agents;
5177
+ discoverAgentsFromAgui() {
5178
+ return Object.entries(this.agents ?? []).map(([key, agent]) => ({
5179
+ name: agent.agentName ?? key,
5180
+ id: agent.agentId ?? key,
5181
+ description: agent.description ?? ""
5182
+ }));
5152
5183
  }
5153
5184
  async loadAgentState(graphqlContext, threadId, agentName) {
5185
+ var _a;
5154
5186
  const agents = await this.getAllAgents(graphqlContext);
5155
5187
  const agent = agents.find((agent2) => agent2.name === agentName);
5156
5188
  if (!agent) {
@@ -5210,33 +5242,38 @@ please use an LLM adapter instead.`
5210
5242
  const propertyHeaders = graphqlContext.properties.authorization ? {
5211
5243
  authorization: `Bearer ${graphqlContext.properties.authorization}`
5212
5244
  } : null;
5213
- let client;
5214
- if ("endpoint" in agent && agent.endpoint.type === EndpointType.LangGraphPlatform) {
5215
- client = new import_langgraph_sdk2.Client({
5216
- apiUrl: agent.endpoint.deploymentUrl,
5217
- apiKey: agent.endpoint.langsmithApiKey,
5218
- defaultHeaders: {
5219
- ...propertyHeaders
5220
- }
5221
- });
5222
- } else {
5223
- const aguiAgent = graphqlContext._copilotkit.runtime.agents[agent.name];
5224
- if (!aguiAgent) {
5225
- throw new Error(`Agent: ${agent.name} could not be resolved`);
5226
- }
5227
- client = aguiAgent.client;
5228
- }
5229
5245
  let state = {};
5230
5246
  try {
5231
- state = (await client.threads.getState(threadId)).values;
5247
+ let client;
5248
+ if ("endpoint" in agent && agent.endpoint.type === EndpointType.LangGraphPlatform) {
5249
+ client = new import_langgraph_sdk2.Client({
5250
+ apiUrl: agent.endpoint.deploymentUrl,
5251
+ apiKey: agent.endpoint.langsmithApiKey,
5252
+ defaultHeaders: {
5253
+ ...propertyHeaders
5254
+ }
5255
+ });
5256
+ } else {
5257
+ const aguiAgent = graphqlContext._copilotkit.runtime.agents[agent.name];
5258
+ if (!aguiAgent) {
5259
+ throw new Error(`Agent: ${agent.name} could not be resolved`);
5260
+ }
5261
+ client = aguiAgent.client ?? null;
5262
+ }
5263
+ state = client ? (await client.threads.getState(threadId)).values : {};
5232
5264
  } catch (error) {
5233
5265
  const errorMessage = error instanceof Error ? error.message : String(error);
5234
- console.debug(`Agent '${agentName}' configuration issue: ${errorMessage}`);
5235
- throw new import_shared18.ResolvedCopilotKitError({
5236
- status: 400,
5237
- message: `Agent '${agentName}' failed to execute: ${errorMessage}`,
5238
- code: import_shared18.CopilotKitErrorCode.CONFIGURATION_ERROR
5239
- });
5266
+ const errorStatus = ((_a = error == null ? void 0 : error.response) == null ? void 0 : _a.status) || (error == null ? void 0 : error.status);
5267
+ if (errorStatus === 404) {
5268
+ state = {};
5269
+ } else {
5270
+ console.debug(`Agent '${agentName}' configuration issue: ${errorMessage}`);
5271
+ throw new import_shared18.ResolvedCopilotKitError({
5272
+ status: 400,
5273
+ message: `Agent '${agentName}' failed to execute: ${errorMessage}`,
5274
+ code: import_shared18.CopilotKitErrorCode.CONFIGURATION_ERROR
5275
+ });
5276
+ }
5240
5277
  }
5241
5278
  if (Object.keys(state).length === 0) {
5242
5279
  return {
@@ -5264,7 +5301,7 @@ please use an LLM adapter instead.`
5264
5301
  const requestStartTime = Date.now();
5265
5302
  const streamedChunks = [];
5266
5303
  const threadId = threadIdFromRequest ?? agentSession.threadId;
5267
- await this.trace("agent_state", {
5304
+ await this.error("agent_state", {
5268
5305
  threadId,
5269
5306
  source: "agent",
5270
5307
  request: {
@@ -5332,7 +5369,27 @@ please use an LLM adapter instead.`
5332
5369
  properties: graphqlContext.properties
5333
5370
  }));
5334
5371
  try {
5335
- const eventSource = new RuntimeEventSource();
5372
+ const eventSource = new RuntimeEventSource({
5373
+ errorHandler: async (error, context) => {
5374
+ await this.error("error", context, error, publicApiKey);
5375
+ },
5376
+ errorContext: {
5377
+ threadId,
5378
+ source: "agent",
5379
+ request: {
5380
+ operation: "processAgentRequest",
5381
+ method: "POST",
5382
+ startTime: requestStartTime
5383
+ },
5384
+ agent: {
5385
+ name: agentName,
5386
+ nodeName
5387
+ },
5388
+ technical: {
5389
+ environment: process.env.NODE_ENV
5390
+ }
5391
+ }
5392
+ });
5336
5393
  const stream = await currentAgent.remoteAgentHandler({
5337
5394
  name: agentName,
5338
5395
  threadId,
@@ -5400,7 +5457,7 @@ please use an LLM adapter instead.`
5400
5457
  }
5401
5458
  }
5402
5459
  const structuredError = (0, import_shared18.ensureStructuredError)(err, (error) => this.convertStreamingErrorToStructured(error));
5403
- await this.trace("error", {
5460
+ await this.error("error", {
5404
5461
  threadId,
5405
5462
  source: "agent",
5406
5463
  request: {
@@ -5489,7 +5546,7 @@ please use an LLM adapter instead.`
5489
5546
  }
5490
5547
  }
5491
5548
  const structuredError = (0, import_shared18.ensureStructuredError)(error, (err) => this.convertStreamingErrorToStructured(err));
5492
- await this.trace("error", {
5549
+ await this.error("error", {
5493
5550
  threadId,
5494
5551
  source: "agent",
5495
5552
  request: {
@@ -5515,7 +5572,7 @@ please use an LLM adapter instead.`
5515
5572
  }
5516
5573
  }
5517
5574
  async getServerSideActions(request) {
5518
- var _a, _b;
5575
+ var _a, _b, _c;
5519
5576
  const { graphqlContext, messages: rawMessages, agentStates, url } = request;
5520
5577
  const inputMessages = convertGqlInputToMessages(rawMessages);
5521
5578
  const langserveFunctions = [];
@@ -5538,7 +5595,8 @@ please use an LLM adapter instead.`
5538
5595
  agentStates,
5539
5596
  frontendUrl: url,
5540
5597
  agents: this.agents,
5541
- metaEvents: request.metaEvents
5598
+ metaEvents: request.metaEvents,
5599
+ nodeName: (_a = request.agentSession) == null ? void 0 : _a.nodeName
5542
5600
  });
5543
5601
  const configuredActions = typeof this.actions === "function" ? this.actions({
5544
5602
  properties: graphqlContext.properties,
@@ -5547,7 +5605,7 @@ please use an LLM adapter instead.`
5547
5605
  const requestSpecificMCPActions = [];
5548
5606
  if (this.createMCPClientImpl) {
5549
5607
  const baseEndpoints = this.mcpServersConfig || [];
5550
- const requestEndpoints = ((_a = graphqlContext.properties) == null ? void 0 : _a.mcpServers) || ((_b = graphqlContext.properties) == null ? void 0 : _b.mcpEndpoints) || [];
5608
+ const requestEndpoints = ((_b = graphqlContext.properties) == null ? void 0 : _b.mcpServers) || ((_c = graphqlContext.properties) == null ? void 0 : _c.mcpEndpoints) || [];
5551
5609
  const effectiveEndpointsMap = /* @__PURE__ */ new Map();
5552
5610
  [
5553
5611
  ...baseEndpoints
@@ -5620,18 +5678,18 @@ please use an LLM adapter instead.`
5620
5678
  code: import_shared18.CopilotKitErrorCode.UNKNOWN
5621
5679
  });
5622
5680
  }
5623
- async trace(type, context, error, publicApiKey) {
5624
- if (!this.onTrace)
5681
+ async error(type, context, error, publicApiKey) {
5682
+ if (!this.onError)
5625
5683
  return;
5626
5684
  if (!publicApiKey) {
5627
- if (!this.hasWarnedAboutTracing) {
5628
- console.warn("CopilotKit: onTrace handler provided but requires publicApiKey to be defined for tracing to work.");
5629
- this.hasWarnedAboutTracing = true;
5685
+ if (!this.hasWarnedAboutError) {
5686
+ console.warn("CopilotKit: onError handler provided but requires publicApiKey to be defined for error handling to work.");
5687
+ this.hasWarnedAboutError = true;
5630
5688
  }
5631
5689
  return;
5632
5690
  }
5633
5691
  try {
5634
- const traceEvent = {
5692
+ const errorEvent = {
5635
5693
  type,
5636
5694
  timestamp: Date.now(),
5637
5695
  context,
@@ -5639,20 +5697,20 @@ please use an LLM adapter instead.`
5639
5697
  error
5640
5698
  }
5641
5699
  };
5642
- await this.onTrace(traceEvent);
5643
- } catch (traceError) {
5644
- console.error("Error in onTrace handler:", traceError);
5700
+ await this.onError(errorEvent);
5701
+ } catch (errorHandlerError) {
5702
+ console.error("Error in onError handler:", errorHandlerError);
5645
5703
  }
5646
5704
  }
5647
5705
  /**
5648
- * Public method to trace GraphQL validation errors
5649
- * This allows the GraphQL resolver to send validation errors through the trace system
5706
+ * Public method to handle GraphQL validation errors
5707
+ * This allows the GraphQL resolver to send validation errors through the error system
5650
5708
  */
5651
- async traceGraphQLError(error, context) {
5652
- if (!this.onTrace)
5709
+ async errorGraphQLError(error, context) {
5710
+ if (!this.onError)
5653
5711
  return;
5654
5712
  try {
5655
- await this.onTrace({
5713
+ await this.onError({
5656
5714
  type: "error",
5657
5715
  timestamp: Date.now(),
5658
5716
  context: {
@@ -5672,8 +5730,8 @@ please use an LLM adapter instead.`
5672
5730
  },
5673
5731
  error
5674
5732
  });
5675
- } catch (traceError) {
5676
- console.error("Error in onTrace handler:", traceError);
5733
+ } catch (errorHandlerError) {
5734
+ console.error("Error in onError handler:", errorHandlerError);
5677
5735
  }
5678
5736
  }
5679
5737
  };
@@ -6281,7 +6339,7 @@ var import_shared26 = require("@copilotkit/shared");
6281
6339
 
6282
6340
  // src/lib/runtime/agui-action.ts
6283
6341
  var import_shared24 = require("@copilotkit/shared");
6284
- function constructAGUIRemoteAction({ logger: logger2, messages, agentStates, agent, metaEvents }) {
6342
+ function constructAGUIRemoteAction({ logger: logger2, messages, agentStates, agent, metaEvents, threadMetadata, nodeName }) {
6285
6343
  const action = {
6286
6344
  name: agent.agentId,
6287
6345
  description: agent.description,
@@ -6316,11 +6374,19 @@ function constructAGUIRemoteAction({ logger: logger2, messages, agentStates, age
6316
6374
  parameters: JSON.parse(input.jsonSchema)
6317
6375
  };
6318
6376
  });
6319
- const forwardedProps = metaEvents.length ? {
6320
- command: {
6321
- resume: (_a = metaEvents[0]) == null ? void 0 : _a.response
6322
- }
6323
- } : void 0;
6377
+ const forwardedProps = {
6378
+ ...(metaEvents == null ? void 0 : metaEvents.length) ? {
6379
+ command: {
6380
+ resume: (_a = metaEvents[0]) == null ? void 0 : _a.response
6381
+ }
6382
+ } : {},
6383
+ ...threadMetadata ? {
6384
+ threadMetadata
6385
+ } : {},
6386
+ ...nodeName ? {
6387
+ nodeName
6388
+ } : {}
6389
+ };
6324
6390
  return agent.legacy_to_be_removed_runAgentBridged({
6325
6391
  tools,
6326
6392
  forwardedProps
@@ -6434,13 +6500,15 @@ async function fetchRemoteInfo({ url, onBeforeRequest, graphqlContext, logger: l
6434
6500
  }
6435
6501
  }
6436
6502
  __name(fetchRemoteInfo, "fetchRemoteInfo");
6437
- async function setupRemoteActions({ remoteEndpointDefinitions, graphqlContext, messages, agentStates, frontendUrl, agents, metaEvents }) {
6503
+ async function setupRemoteActions({ remoteEndpointDefinitions, graphqlContext, messages, agentStates, frontendUrl, agents, metaEvents, nodeName }) {
6504
+ var _a;
6438
6505
  const logger2 = graphqlContext.logger.child({
6439
6506
  component: "remote-actions.fetchRemoteActions"
6440
6507
  });
6441
6508
  logger2.debug({
6442
6509
  remoteEndpointDefinitions
6443
6510
  }, "Fetching from remote endpoints");
6511
+ const threadMetadata = ((_a = graphqlContext.properties) == null ? void 0 : _a.threadMetadata) || {};
6444
6512
  const filtered = remoteEndpointDefinitions.filter((value, index, self) => {
6445
6513
  if (value.type === "langgraph-platform") {
6446
6514
  return value;
@@ -6497,7 +6565,9 @@ async function setupRemoteActions({ remoteEndpointDefinitions, graphqlContext, m
6497
6565
  messages,
6498
6566
  agentStates,
6499
6567
  agent,
6500
- metaEvents
6568
+ metaEvents,
6569
+ threadMetadata,
6570
+ nodeName
6501
6571
  }));
6502
6572
  }
6503
6573
  return result.flat();
@@ -6620,6 +6690,12 @@ __name(RuntimeEventSubject, "RuntimeEventSubject");
6620
6690
  var RuntimeEventSource = class {
6621
6691
  eventStream$ = new RuntimeEventSubject();
6622
6692
  callback;
6693
+ errorHandler;
6694
+ errorContext;
6695
+ constructor(params) {
6696
+ this.errorHandler = params == null ? void 0 : params.errorHandler;
6697
+ this.errorContext = params == null ? void 0 : params.errorContext;
6698
+ }
6623
6699
  async stream(callback) {
6624
6700
  this.callback = callback;
6625
6701
  }
@@ -6634,8 +6710,15 @@ var RuntimeEventSource = class {
6634
6710
  }
6635
6711
  }
6636
6712
  processRuntimeEvents({ serverSideActions, guardrailsResult$, actionInputsWithoutAgents, threadId }) {
6637
- this.callback(this.eventStream$).catch((error) => {
6713
+ this.callback(this.eventStream$).catch(async (error) => {
6638
6714
  const structuredError = (0, import_shared27.ensureStructuredError)(error, convertStreamingErrorToStructured2);
6715
+ if (this.errorHandler && this.errorContext) {
6716
+ try {
6717
+ await this.errorHandler(structuredError, this.errorContext);
6718
+ } catch (errorHandlerError) {
6719
+ console.error("Error in streaming error handler:", errorHandlerError);
6720
+ }
6721
+ }
6639
6722
  this.eventStream$.error(structuredError);
6640
6723
  this.eventStream$.complete();
6641
6724
  });
@@ -6674,6 +6757,19 @@ var RuntimeEventSource = class {
6674
6757
  telemetry_client_default.capture("oss.runtime.server_action_executed", {});
6675
6758
  return (0, import_rxjs3.concat)((0, import_rxjs3.of)(eventWithState.event), toolCallEventStream$).pipe((0, import_rxjs3.catchError)((error) => {
6676
6759
  const structuredError = (0, import_shared27.ensureStructuredError)(error, convertStreamingErrorToStructured2);
6760
+ if (this.errorHandler && this.errorContext) {
6761
+ (0, import_rxjs3.from)(this.errorHandler(structuredError, {
6762
+ ...this.errorContext,
6763
+ action: {
6764
+ name: eventWithState.action.name,
6765
+ executionId: eventWithState.actionExecutionId
6766
+ }
6767
+ })).subscribe({
6768
+ error: (errorHandlerError) => {
6769
+ console.error("Error in action execution error handler:", errorHandlerError);
6770
+ }
6771
+ });
6772
+ }
6677
6773
  toolCallEventStream$.sendActionExecutionResult({
6678
6774
  actionExecutionId: eventWithState.actionExecutionId,
6679
6775
  actionName: eventWithState.action.name,
@@ -7018,7 +7114,7 @@ var CopilotResolver = class {
7018
7114
  logger2.debug("Cloud configuration provided, checking for public API key in headers");
7019
7115
  if (!copilotCloudPublicApiKey) {
7020
7116
  logger2.error("Public API key not found in headers");
7021
- await copilotRuntime.traceGraphQLError({
7117
+ await copilotRuntime.errorGraphQLError({
7022
7118
  message: "X-CopilotCloud-Public-API-Key header is required",
7023
7119
  code: "MISSING_PUBLIC_API_KEY",
7024
7120
  type: "GraphQLError"