@copilotkitnext/core 1.54.0-next.5 → 1.54.0-next.6

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/dist/index.cjs CHANGED
@@ -749,6 +749,13 @@ var RunHandler = class {
749
749
  this.core = core;
750
750
  }
751
751
  /**
752
+ * Typed access to CopilotKitCore's internal ("friend") methods.
753
+ * Centralises the single unavoidable cast so call-sites stay clean.
754
+ */
755
+ get _internal() {
756
+ return this.core;
757
+ }
758
+ /**
752
759
  * Get all tools as a readonly array
753
760
  */
754
761
  get tools() {
@@ -806,9 +813,9 @@ var RunHandler = class {
806
813
  await agent.detachActiveRun();
807
814
  agent.setMessages([]);
808
815
  agent.setState({});
809
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this.core.headers };
816
+ if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
810
817
  const runAgentResult = await agent.connectAgent({
811
- forwardedProps: this.core.properties,
818
+ forwardedProps: this._internal.properties,
812
819
  tools: this.buildFrontendTools(agent.agentId)
813
820
  }, this.createAgentErrorSubscriber(agent));
814
821
  return this.processAgentResult({
@@ -819,7 +826,7 @@ var RunHandler = class {
819
826
  const connectError = error instanceof Error ? error : new Error(String(error));
820
827
  const context = {};
821
828
  if (agent.agentId) context.agentId = agent.agentId;
822
- await this.core.emitError({
829
+ await this._internal.emitError({
823
830
  error: connectError,
824
831
  code: CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED,
825
832
  context
@@ -831,16 +838,16 @@ var RunHandler = class {
831
838
  * Run an agent
832
839
  */
833
840
  async runAgent({ agent, forwardedProps }) {
834
- if (agent.agentId) this.core.suggestionEngine.clearSuggestions(agent.agentId);
835
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this.core.headers };
841
+ if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
842
+ if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
836
843
  try {
837
844
  const runAgentResult = await agent.runAgent({
838
845
  forwardedProps: {
839
- ...this.core.properties,
846
+ ...this._internal.properties,
840
847
  ...forwardedProps
841
848
  },
842
849
  tools: this.buildFrontendTools(agent.agentId),
843
- context: Object.values(this.core.context)
850
+ context: Object.values(this._internal.context)
844
851
  }, this.createAgentErrorSubscriber(agent));
845
852
  return this.processAgentResult({
846
853
  runAgentResult,
@@ -850,7 +857,7 @@ var RunHandler = class {
850
857
  const runError = error instanceof Error ? error : new Error(String(error));
851
858
  const context = {};
852
859
  if (agent.agentId) context.agentId = agent.agentId;
853
- await this.core.emitError({
860
+ await this._internal.emitError({
854
861
  error: runError,
855
862
  code: CopilotKitCoreErrorCode.AGENT_RUN_FAILED,
856
863
  context
@@ -885,77 +892,103 @@ var RunHandler = class {
885
892
  }
886
893
  }
887
894
  if (needsFollowUp) return await this.runAgent({ agent });
888
- this.core.suggestionEngine.reloadSuggestions(agentId);
895
+ this._internal.suggestionEngine.reloadSuggestions(agentId);
889
896
  return runAgentResult;
890
897
  }
891
898
  /**
892
- * Execute a specific tool
899
+ * Shared handler execution logic used by executeSpecificTool, executeWildcardTool, and runTool.
900
+ * Handles arg parsing, subscriber notifications, handler invocation, result stringification,
901
+ * and error handling.
893
902
  */
894
- async executeSpecificTool(tool, toolCall, message, agent, agentId) {
895
- if (tool?.agentId && tool.agentId !== agent.agentId) return false;
903
+ async executeToolHandler({ tool, toolCall, agent, agentId, handlerArgs, toolType, messageId }) {
896
904
  let toolCallResult = "";
897
905
  let errorMessage;
898
- if (tool?.handler) {
899
- let parsedArgs;
900
- try {
901
- parsedArgs = ensureObjectArgs(JSON.parse(toolCall.function.arguments), toolCall.function.name);
902
- } catch (error) {
903
- const parseError = error instanceof Error ? error : new Error(String(error));
904
- errorMessage = parseError.message;
905
- await this.core.emitError({
906
- error: parseError,
907
- code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,
908
- context: {
909
- agentId,
910
- toolCallId: toolCall.id,
911
- toolName: toolCall.function.name,
912
- rawArguments: toolCall.function.arguments,
913
- toolType: "specific",
914
- messageId: message.id
915
- }
916
- });
917
- }
918
- await this.core.notifySubscribers((subscriber) => subscriber.onToolExecutionStart?.({
919
- copilotkit: this.core,
920
- toolCallId: toolCall.id,
921
- agentId,
922
- toolName: toolCall.function.name,
923
- args: parsedArgs
924
- }), "Subscriber onToolExecutionStart error:");
925
- if (!errorMessage) try {
926
- const result = await tool.handler(parsedArgs, {
927
- toolCall,
928
- agent
929
- });
930
- if (result === void 0 || result === null) toolCallResult = "";
931
- else if (typeof result === "string") toolCallResult = result;
932
- else toolCallResult = JSON.stringify(result);
933
- } catch (error) {
934
- const handlerError = error instanceof Error ? error : new Error(String(error));
935
- errorMessage = handlerError.message;
936
- await this.core.emitError({
937
- error: handlerError,
938
- code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,
939
- context: {
940
- agentId,
941
- toolCallId: toolCall.id,
942
- toolName: toolCall.function.name,
943
- parsedArgs,
944
- toolType: "specific",
945
- messageId: message.id
946
- }
947
- });
948
- }
949
- if (errorMessage) toolCallResult = `Error: ${errorMessage}`;
950
- await this.core.notifySubscribers((subscriber) => subscriber.onToolExecutionEnd?.({
951
- copilotkit: this.core,
952
- toolCallId: toolCall.id,
953
- agentId,
954
- toolName: toolCall.function.name,
955
- result: errorMessage ? "" : toolCallResult,
956
- error: errorMessage
957
- }), "Subscriber onToolExecutionEnd error:");
906
+ let isArgumentError = false;
907
+ let parsedArgs;
908
+ try {
909
+ parsedArgs = ensureObjectArgs(typeof handlerArgs === "string" ? JSON.parse(handlerArgs) : handlerArgs, toolCall.function.name);
910
+ } catch (error) {
911
+ const parseError = error instanceof Error ? error : new Error(String(error));
912
+ errorMessage = parseError.message;
913
+ isArgumentError = true;
914
+ await this._internal.emitError({
915
+ error: parseError,
916
+ code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,
917
+ context: {
918
+ agentId,
919
+ toolCallId: toolCall.id,
920
+ toolName: toolCall.function.name,
921
+ rawArguments: handlerArgs,
922
+ toolType,
923
+ ...messageId ? { messageId } : {}
924
+ }
925
+ });
958
926
  }
927
+ await this._internal.notifySubscribers((subscriber) => subscriber.onToolExecutionStart?.({
928
+ copilotkit: this.core,
929
+ toolCallId: toolCall.id,
930
+ agentId,
931
+ toolName: toolCall.function.name,
932
+ args: parsedArgs
933
+ }), "Subscriber onToolExecutionStart error:");
934
+ if (!errorMessage) try {
935
+ const result = await tool.handler(parsedArgs, {
936
+ toolCall,
937
+ agent
938
+ });
939
+ if (result === void 0 || result === null) toolCallResult = "";
940
+ else if (typeof result === "string") toolCallResult = result;
941
+ else toolCallResult = JSON.stringify(result);
942
+ } catch (error) {
943
+ const handlerError = error instanceof Error ? error : new Error(String(error));
944
+ errorMessage = handlerError.message;
945
+ await this._internal.emitError({
946
+ error: handlerError,
947
+ code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,
948
+ context: {
949
+ agentId,
950
+ toolCallId: toolCall.id,
951
+ toolName: toolCall.function.name,
952
+ parsedArgs,
953
+ toolType,
954
+ ...messageId ? { messageId } : {}
955
+ }
956
+ });
957
+ }
958
+ if (errorMessage) toolCallResult = `Error: ${errorMessage}`;
959
+ await this._internal.notifySubscribers((subscriber) => subscriber.onToolExecutionEnd?.({
960
+ copilotkit: this.core,
961
+ toolCallId: toolCall.id,
962
+ agentId,
963
+ toolName: toolCall.function.name,
964
+ result: errorMessage ? "" : toolCallResult,
965
+ error: errorMessage
966
+ }), "Subscriber onToolExecutionEnd error:");
967
+ return {
968
+ result: toolCallResult,
969
+ error: errorMessage,
970
+ isArgumentError
971
+ };
972
+ }
973
+ /**
974
+ * Execute a specific tool
975
+ */
976
+ async executeSpecificTool(tool, toolCall, message, agent, agentId) {
977
+ if (tool?.agentId && tool.agentId !== agent.agentId) return false;
978
+ let handlerResult = {
979
+ result: "",
980
+ error: void 0,
981
+ isArgumentError: false
982
+ };
983
+ if (tool?.handler) handlerResult = await this.executeToolHandler({
984
+ tool,
985
+ toolCall,
986
+ agent,
987
+ agentId,
988
+ handlerArgs: toolCall.function.arguments,
989
+ toolType: "specific",
990
+ messageId: message.id
991
+ });
959
992
  {
960
993
  const messageIndex = agent.messages.findIndex((m) => m.id === message.id);
961
994
  if (messageIndex === -1) return false;
@@ -963,15 +996,18 @@ var RunHandler = class {
963
996
  id: (0, _copilotkitnext_shared.randomUUID)(),
964
997
  role: "tool",
965
998
  toolCallId: toolCall.id,
966
- content: toolCallResult
999
+ content: handlerResult.result
967
1000
  };
968
1001
  agent.messages.splice(messageIndex + 1, 0, toolMessage);
969
- if (!errorMessage && tool?.followUp !== false) return true;
1002
+ if (!handlerResult.error && tool?.followUp !== false) return true;
970
1003
  }
971
1004
  return false;
972
1005
  }
973
1006
  /**
974
- * Execute a wildcard tool
1007
+ * Execute a wildcard tool.
1008
+ * Wildcard tools receive args wrapped as `{toolName, args}`, which differs from
1009
+ * specific tools, so this method keeps its own arg-wrapping logic rather than
1010
+ * delegating to `executeToolHandler`.
975
1011
  */
976
1012
  async executeWildcardTool(wildcardTool, toolCall, message, agent, agentId) {
977
1013
  if (wildcardTool?.agentId && wildcardTool.agentId !== agent.agentId) return false;
@@ -984,7 +1020,7 @@ var RunHandler = class {
984
1020
  } catch (error) {
985
1021
  const parseError = error instanceof Error ? error : new Error(String(error));
986
1022
  errorMessage = parseError.message;
987
- await this.core.emitError({
1023
+ await this._internal.emitError({
988
1024
  error: parseError,
989
1025
  code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,
990
1026
  context: {
@@ -1001,7 +1037,7 @@ var RunHandler = class {
1001
1037
  toolName: toolCall.function.name,
1002
1038
  args: parsedArgs
1003
1039
  };
1004
- await this.core.notifySubscribers((subscriber) => subscriber.onToolExecutionStart?.({
1040
+ await this._internal.notifySubscribers((subscriber) => subscriber.onToolExecutionStart?.({
1005
1041
  copilotkit: this.core,
1006
1042
  toolCallId: toolCall.id,
1007
1043
  agentId,
@@ -1019,7 +1055,7 @@ var RunHandler = class {
1019
1055
  } catch (error) {
1020
1056
  const handlerError = error instanceof Error ? error : new Error(String(error));
1021
1057
  errorMessage = handlerError.message;
1022
- await this.core.emitError({
1058
+ await this._internal.emitError({
1023
1059
  error: handlerError,
1024
1060
  code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,
1025
1061
  context: {
@@ -1033,7 +1069,7 @@ var RunHandler = class {
1033
1069
  });
1034
1070
  }
1035
1071
  if (errorMessage) toolCallResult = `Error: ${errorMessage}`;
1036
- await this.core.notifySubscribers((subscriber) => subscriber.onToolExecutionEnd?.({
1072
+ await this._internal.notifySubscribers((subscriber) => subscriber.onToolExecutionEnd?.({
1037
1073
  copilotkit: this.core,
1038
1074
  toolCallId: toolCall.id,
1039
1075
  agentId,
@@ -1057,6 +1093,94 @@ var RunHandler = class {
1057
1093
  return false;
1058
1094
  }
1059
1095
  /**
1096
+ * Programmatically execute a registered frontend tool without going through an LLM turn.
1097
+ * The handler runs, render components show up in the UI, and both the tool call and
1098
+ * result messages are added to `agent.messages`.
1099
+ */
1100
+ async runTool(params) {
1101
+ const { name, agentId, parameters = {}, followUp = false } = params;
1102
+ const tool = this.getTool({
1103
+ toolName: name,
1104
+ agentId
1105
+ });
1106
+ if (!tool) {
1107
+ const error = /* @__PURE__ */ new Error(`Tool not found: ${name}`);
1108
+ await this._internal.emitError({
1109
+ error,
1110
+ code: CopilotKitCoreErrorCode.TOOL_NOT_FOUND,
1111
+ context: {
1112
+ toolName: name,
1113
+ agentId
1114
+ }
1115
+ });
1116
+ throw error;
1117
+ }
1118
+ const resolvedAgentId = agentId ?? "default";
1119
+ const agent = this._internal.getAgent(resolvedAgentId);
1120
+ if (!agent) {
1121
+ const error = /* @__PURE__ */ new Error(`Agent not found: ${resolvedAgentId}`);
1122
+ await this._internal.emitError({
1123
+ error,
1124
+ code: CopilotKitCoreErrorCode.AGENT_NOT_FOUND,
1125
+ context: { agentId: resolvedAgentId }
1126
+ });
1127
+ throw error;
1128
+ }
1129
+ const toolCallId = (0, _copilotkitnext_shared.randomUUID)();
1130
+ const assistantMessage = {
1131
+ id: (0, _copilotkitnext_shared.randomUUID)(),
1132
+ role: "assistant",
1133
+ content: "",
1134
+ toolCalls: [{
1135
+ id: toolCallId,
1136
+ type: "function",
1137
+ function: {
1138
+ name,
1139
+ arguments: JSON.stringify(parameters)
1140
+ }
1141
+ }]
1142
+ };
1143
+ agent.messages.push(assistantMessage);
1144
+ let handlerResult = {
1145
+ result: "",
1146
+ error: void 0,
1147
+ isArgumentError: false
1148
+ };
1149
+ if (tool.handler) handlerResult = await this.executeToolHandler({
1150
+ tool,
1151
+ toolCall: assistantMessage.toolCalls[0],
1152
+ agent,
1153
+ agentId: resolvedAgentId,
1154
+ handlerArgs: parameters,
1155
+ toolType: "runTool"
1156
+ });
1157
+ const toolResultMessage = {
1158
+ id: (0, _copilotkitnext_shared.randomUUID)(),
1159
+ role: "tool",
1160
+ toolCallId,
1161
+ content: handlerResult.result
1162
+ };
1163
+ const assistantIndex = agent.messages.findIndex((m) => m.id === assistantMessage.id);
1164
+ if (assistantIndex !== -1) agent.messages.splice(assistantIndex + 1, 0, toolResultMessage);
1165
+ else agent.messages.push(toolResultMessage);
1166
+ if (!handlerResult.error && followUp !== false) {
1167
+ if (typeof followUp === "string" && followUp !== "generate") {
1168
+ const userMessage = {
1169
+ id: (0, _copilotkitnext_shared.randomUUID)(),
1170
+ role: "user",
1171
+ content: followUp
1172
+ };
1173
+ agent.messages.push(userMessage);
1174
+ }
1175
+ await this.runAgent({ agent });
1176
+ }
1177
+ return {
1178
+ toolCallId,
1179
+ result: handlerResult.result,
1180
+ error: handlerResult.error
1181
+ };
1182
+ }
1183
+ /**
1060
1184
  * Build frontend tools for an agent
1061
1185
  */
1062
1186
  buildFrontendTools(agentId) {
@@ -1073,7 +1197,7 @@ var RunHandler = class {
1073
1197
  const emitAgentError = async (error, code, extraContext = {}) => {
1074
1198
  const context = { ...extraContext };
1075
1199
  if (agent.agentId) context.agentId = agent.agentId;
1076
- await this.core.emitError({
1200
+ await this._internal.emitError({
1077
1201
  error,
1078
1202
  code,
1079
1203
  context
@@ -1319,6 +1443,8 @@ let CopilotKitCoreErrorCode = /* @__PURE__ */ function(CopilotKitCoreErrorCode)
1319
1443
  CopilotKitCoreErrorCode["AGENT_RUN_ERROR_EVENT"] = "agent_run_error_event";
1320
1444
  CopilotKitCoreErrorCode["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
1321
1445
  CopilotKitCoreErrorCode["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
1446
+ CopilotKitCoreErrorCode["TOOL_NOT_FOUND"] = "tool_not_found";
1447
+ CopilotKitCoreErrorCode["AGENT_NOT_FOUND"] = "agent_not_found";
1322
1448
  CopilotKitCoreErrorCode["TRANSCRIPTION_FAILED"] = "transcription_failed";
1323
1449
  CopilotKitCoreErrorCode["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
1324
1450
  CopilotKitCoreErrorCode["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
@@ -1534,6 +1660,14 @@ var CopilotKitCore = class {
1534
1660
  return this.runHandler.runAgent(params);
1535
1661
  }
1536
1662
  /**
1663
+ * Programmatically execute a registered frontend tool without going through an LLM turn.
1664
+ * The handler runs, render components show up in the UI, and both the tool call and
1665
+ * result messages are added to `agent.messages`.
1666
+ */
1667
+ async runTool(params) {
1668
+ return this.runHandler.runTool(params);
1669
+ }
1670
+ /**
1537
1671
  * State management (delegated to StateManager)
1538
1672
  */
1539
1673
  getStateByRun(agentId, threadId, runId) {