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