@mastra/client-js 1.22.0-alpha.5 → 1.22.0-alpha.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.js CHANGED
@@ -857,173 +857,216 @@ var Agent = class extends BaseResource {
857
857
  throw new Error("No response body");
858
858
  }
859
859
  const agent = this;
860
+ streamResponse.abort = async () => (await agent.abortThread({ resourceId, threadId })).aborted;
861
+ let unsubscribed = false;
862
+ let processAbortController;
863
+ let processStarted = false;
864
+ streamResponse.unsubscribe = () => {
865
+ if (unsubscribed) return;
866
+ unsubscribed = true;
867
+ processAbortController?.abort();
868
+ if (!processStarted) {
869
+ void streamResponse.body?.cancel().catch(() => {
870
+ });
871
+ }
872
+ };
860
873
  streamResponse.processDataStream = async ({ onChunk, reconnect }) => {
861
- const pendingToolCallsByRunId = /* @__PURE__ */ new Map();
862
- const handleSubscribedChunk = async (chunk) => {
863
- if (chunk.type === "tool-call") {
864
- const payload = chunk.payload;
865
- const toolCallId = payload?.toolCallId;
866
- const toolName = payload?.toolName;
867
- const runId2 = chunk.runId;
868
- if (!toolCallId || !toolName || !runId2) return;
869
- const pendingToolCalls2 = pendingToolCallsByRunId.get(runId2) ?? [];
870
- pendingToolCalls2.push({ toolCallId, toolName, args: payload.args, observability: payload.observability });
871
- pendingToolCallsByRunId.set(runId2, pendingToolCalls2);
872
- return;
873
- }
874
- if (chunk.type !== "finish") return;
875
- const runId = chunk.runId;
876
- const finishPayload = chunk;
877
- if (!runId) return;
878
- if (finishPayload.payload?.stepResult?.reason !== "tool-calls") {
879
- agent.deleteSignalRuntimeOptions(runId);
880
- return;
881
- }
882
- const pendingToolCalls = pendingToolCallsByRunId.get(runId);
883
- pendingToolCallsByRunId.delete(runId);
884
- if (!pendingToolCalls?.length) {
885
- agent.deleteSignalRuntimeOptions(runId);
886
- return;
887
- }
888
- const activeRuntimeOptions = agent.getSignalRuntimeOptions({ runId, resourceId, threadId });
889
- const activeClientTools = activeRuntimeOptions?.clientTools;
890
- if (!activeClientTools) {
891
- agent.deleteSignalRuntimeOptions(runId);
892
- return;
893
- }
894
- const activeRequestContext = activeRuntimeOptions.requestContext;
895
- const processedClientTools = processClientTools(activeClientTools);
896
- const processedRequestContext = parseClientRequestContext(activeRequestContext);
897
- const toolResultMessages = [];
898
- for (const toolCall of pendingToolCalls) {
899
- const clientTool = activeClientTools[toolCall.toolName];
900
- if (!clientTool || typeof clientTool.execute !== "function") continue;
901
- let result;
902
- let observability;
903
- try {
904
- const execution = await executeClientToolWithObservability({
905
- clientTool,
906
- args: toolCall.args,
907
- toolName: toolCall.toolName,
908
- parentContext: toolCall.observability,
909
- executeContext: {
910
- requestContext: activeRequestContext,
911
- tracingContext: { currentSpan: void 0 },
912
- agent: {
913
- agentId: agent.agentId,
914
- messages: finishPayload.payload?.messages?.nonUser ?? [],
915
- toolCallId: toolCall.toolCallId,
916
- suspend: async () => {
917
- },
918
- threadId,
919
- resourceId
920
- }
921
- }
922
- });
923
- result = execution.result;
924
- observability = execution.observability;
925
- } catch (error) {
926
- result = { error: String(error) };
874
+ if (unsubscribed) return;
875
+ processStarted = true;
876
+ processAbortController = new AbortController();
877
+ const abortProcessStream = () => processAbortController?.abort();
878
+ const isClosed = () => unsubscribed || processAbortController?.signal.aborted || this.options.abortSignal?.aborted;
879
+ if (this.options.abortSignal?.aborted) {
880
+ abortProcessStream();
881
+ } else {
882
+ this.options.abortSignal?.addEventListener("abort", abortProcessStream, { once: true });
883
+ }
884
+ try {
885
+ const pendingToolCallsByRunId = /* @__PURE__ */ new Map();
886
+ const handleSubscribedChunk = async (chunk) => {
887
+ if (chunk.type === "tool-call") {
888
+ const payload = chunk.payload;
889
+ const toolCallId = payload?.toolCallId;
890
+ const toolName = payload?.toolName;
891
+ const runId2 = chunk.runId;
892
+ if (!toolCallId || !toolName || !runId2) return;
893
+ const pendingToolCalls2 = pendingToolCallsByRunId.get(runId2) ?? [];
894
+ pendingToolCalls2.push({ toolCallId, toolName, args: payload.args, observability: payload.observability });
895
+ pendingToolCallsByRunId.set(runId2, pendingToolCalls2);
896
+ return;
927
897
  }
928
- const toolResultContent = {
929
- type: "tool-result",
930
- toolCallId: toolCall.toolCallId,
931
- toolName: toolCall.toolName,
932
- result
933
- };
934
- if (observability) {
935
- toolResultContent.__mastraObservability = observability;
898
+ if (chunk.type !== "finish") return;
899
+ const runId = chunk.runId;
900
+ const finishPayload = chunk;
901
+ if (!runId) return;
902
+ if (finishPayload.payload?.stepResult?.reason !== "tool-calls") {
903
+ agent.deleteSignalRuntimeOptions(runId);
904
+ return;
936
905
  }
937
- await onChunk({
938
- type: "tool-result",
939
- runId,
940
- payload: toolResultContent
941
- });
942
- toolResultMessages.push({
943
- role: "tool",
944
- content: [toolResultContent]
945
- });
946
- }
947
- if (toolResultMessages.length === 0) {
948
- agent.deleteSignalRuntimeOptions(runId);
949
- return;
950
- }
951
- try {
952
- const continuation = await agent.streamUntilIdle(
953
- [...finishPayload.payload?.messages?.nonUser ?? [], ...toolResultMessages],
954
- {
955
- ...activeRuntimeOptions,
956
- runId: v4(),
957
- requestContext: processedRequestContext,
958
- memory: threadId ? { thread: threadId, resource: resourceId } : void 0,
959
- clientTools: processedClientTools
960
- }
961
- );
962
- try {
963
- void continuation.body?.cancel?.();
964
- } catch {
906
+ const pendingToolCalls = pendingToolCallsByRunId.get(runId);
907
+ pendingToolCallsByRunId.delete(runId);
908
+ if (!pendingToolCalls?.length) {
909
+ agent.deleteSignalRuntimeOptions(runId);
910
+ return;
965
911
  }
966
- } catch (error) {
967
- console.error("Error running client-tool continuation:", error);
968
- } finally {
969
- agent.deleteSignalRuntimeOptions(runId);
970
- }
971
- };
972
- const reconnectOptions = reconnect === true ? { maxRetries: Infinity, delayMs: 1e3 } : reconnect ? { maxRetries: reconnect.maxRetries ?? Infinity, delayMs: reconnect.delayMs ?? 1e3 } : null;
973
- let response = streamResponse;
974
- let attempts = 0;
975
- const onChunkErrorSentinel = /* @__PURE__ */ Symbol("onChunkErrorSentinel");
976
- const guardedOnChunk = async (chunk) => {
977
- try {
978
- await onChunk(chunk);
979
- await handleSubscribedChunk(chunk);
980
- } catch (cause) {
981
- throw { [onChunkErrorSentinel]: true, cause };
982
- }
983
- };
984
- while (true) {
985
- if (!response.body) {
986
- throw new Error("No response body");
987
- }
988
- try {
989
- await processMastraStream({
990
- stream: response.body,
991
- onChunk: guardedOnChunk,
992
- signal: this.options.abortSignal
993
- });
994
- } catch (error) {
995
- if (typeof error === "object" && error !== null && error[onChunkErrorSentinel]) {
996
- throw error.cause;
912
+ const activeRuntimeOptions = agent.getSignalRuntimeOptions({ runId, resourceId, threadId });
913
+ const activeClientTools = activeRuntimeOptions?.clientTools;
914
+ if (!activeClientTools) {
915
+ agent.deleteSignalRuntimeOptions(runId);
916
+ return;
997
917
  }
998
- if (!reconnectOptions || this.options.abortSignal?.aborted || attempts >= reconnectOptions.maxRetries) {
999
- throw error;
918
+ const activeRequestContext = activeRuntimeOptions.requestContext;
919
+ const processedClientTools = processClientTools(activeClientTools);
920
+ const processedRequestContext = parseClientRequestContext(activeRequestContext);
921
+ const toolResultMessages = [];
922
+ for (const toolCall of pendingToolCalls) {
923
+ const clientTool = activeClientTools[toolCall.toolName];
924
+ if (!clientTool || typeof clientTool.execute !== "function") continue;
925
+ let result;
926
+ let observability;
927
+ try {
928
+ const execution = await executeClientToolWithObservability({
929
+ clientTool,
930
+ args: toolCall.args,
931
+ toolName: toolCall.toolName,
932
+ parentContext: toolCall.observability,
933
+ executeContext: {
934
+ requestContext: activeRequestContext,
935
+ tracingContext: { currentSpan: void 0 },
936
+ agent: {
937
+ agentId: agent.agentId,
938
+ messages: finishPayload.payload?.messages?.nonUser ?? [],
939
+ toolCallId: toolCall.toolCallId,
940
+ suspend: async () => {
941
+ },
942
+ threadId,
943
+ resourceId
944
+ }
945
+ }
946
+ });
947
+ result = execution.result;
948
+ observability = execution.observability;
949
+ } catch (error) {
950
+ result = { error: String(error) };
951
+ }
952
+ const toolResultContent = {
953
+ type: "tool-result",
954
+ toolCallId: toolCall.toolCallId,
955
+ toolName: toolCall.toolName,
956
+ result
957
+ };
958
+ if (observability) {
959
+ toolResultContent.__mastraObservability = observability;
960
+ }
961
+ await onChunk({
962
+ type: "tool-result",
963
+ runId,
964
+ payload: toolResultContent
965
+ });
966
+ toolResultMessages.push({
967
+ role: "tool",
968
+ content: [toolResultContent]
969
+ });
1000
970
  }
1001
- }
1002
- if (!reconnectOptions || this.options.abortSignal?.aborted || attempts >= reconnectOptions.maxRetries) {
1003
- return;
1004
- }
1005
- while (attempts < reconnectOptions.maxRetries) {
1006
- attempts++;
1007
- if (this.options.abortSignal?.aborted) {
971
+ if (toolResultMessages.length === 0) {
972
+ agent.deleteSignalRuntimeOptions(runId);
1008
973
  return;
1009
974
  }
1010
- await new Promise((resolve) => setTimeout(resolve, reconnectOptions.delayMs));
1011
- if (this.options.abortSignal?.aborted) {
1012
- return;
975
+ try {
976
+ const continuation = await agent.streamUntilIdle(
977
+ [...finishPayload.payload?.messages?.nonUser ?? [], ...toolResultMessages],
978
+ {
979
+ ...activeRuntimeOptions,
980
+ runId: v4(),
981
+ requestContext: processedRequestContext,
982
+ memory: threadId ? { thread: threadId, resource: resourceId } : void 0,
983
+ clientTools: processedClientTools
984
+ }
985
+ );
986
+ try {
987
+ void continuation.body?.cancel?.();
988
+ } catch {
989
+ }
990
+ } catch (error) {
991
+ console.error("Error running client-tool continuation:", error);
992
+ } finally {
993
+ agent.deleteSignalRuntimeOptions(runId);
1013
994
  }
995
+ };
996
+ const reconnectOptions = reconnect === true ? { maxRetries: Infinity, delayMs: 1e3 } : reconnect ? { maxRetries: reconnect.maxRetries ?? Infinity, delayMs: reconnect.delayMs ?? 1e3 } : null;
997
+ let response = streamResponse;
998
+ let attempts = 0;
999
+ const onChunkErrorSentinel = /* @__PURE__ */ Symbol("onChunkErrorSentinel");
1000
+ const guardedOnChunk = async (chunk) => {
1014
1001
  try {
1015
- response = await requestSubscription();
1016
- break;
1002
+ await onChunk(chunk);
1003
+ await handleSubscribedChunk(chunk);
1004
+ } catch (cause) {
1005
+ throw { [onChunkErrorSentinel]: true, cause };
1006
+ }
1007
+ };
1008
+ while (true) {
1009
+ if (!response.body) {
1010
+ throw new Error("No response body");
1011
+ }
1012
+ try {
1013
+ await processMastraStream({
1014
+ stream: response.body,
1015
+ onChunk: guardedOnChunk,
1016
+ signal: processAbortController.signal
1017
+ });
1017
1018
  } catch (error) {
1018
- if (this.options.abortSignal?.aborted || attempts >= reconnectOptions.maxRetries) {
1019
+ if (typeof error === "object" && error !== null && error[onChunkErrorSentinel]) {
1020
+ throw error.cause;
1021
+ }
1022
+ if (!reconnectOptions || isClosed() || attempts >= reconnectOptions.maxRetries) {
1023
+ if (isClosed()) return;
1019
1024
  throw error;
1020
1025
  }
1021
1026
  }
1027
+ if (!reconnectOptions || isClosed() || attempts >= reconnectOptions.maxRetries) {
1028
+ return;
1029
+ }
1030
+ while (attempts < reconnectOptions.maxRetries) {
1031
+ attempts++;
1032
+ if (isClosed()) {
1033
+ return;
1034
+ }
1035
+ await new Promise((resolve) => setTimeout(resolve, reconnectOptions.delayMs));
1036
+ if (isClosed()) {
1037
+ return;
1038
+ }
1039
+ try {
1040
+ response = await requestSubscription();
1041
+ break;
1042
+ } catch (error) {
1043
+ if (isClosed() || attempts >= reconnectOptions.maxRetries) {
1044
+ if (isClosed()) return;
1045
+ throw error;
1046
+ }
1047
+ }
1048
+ }
1049
+ }
1050
+ } finally {
1051
+ this.options.abortSignal?.removeEventListener("abort", abortProcessStream);
1052
+ if (processAbortController?.signal.aborted) {
1053
+ unsubscribed = true;
1022
1054
  }
1055
+ processAbortController = void 0;
1023
1056
  }
1024
1057
  };
1025
1058
  return streamResponse;
1026
1059
  }
1060
+ /**
1061
+ * @experimental Agent signals are experimental and may change in a future release.
1062
+ */
1063
+ async abortThread(params) {
1064
+ const { resourceId, threadId } = params;
1065
+ return this.request(`/agents/${this.agentId}/threads/abort`, {
1066
+ method: "POST",
1067
+ body: { resourceId, threadId }
1068
+ });
1069
+ }
1027
1070
  /**
1028
1071
  * Clones this agent to a new stored agent in the database
1029
1072
  * @param params - Clone parameters including optional newId, newName, metadata, authorId, and requestContext
@@ -2215,6 +2258,16 @@ var Agent = class extends BaseResource {
2215
2258
  };
2216
2259
  return streamResponse;
2217
2260
  }
2261
+ async sendToolApproval(params) {
2262
+ const { requestContext, ...rest } = params;
2263
+ return this.request(
2264
+ `/agents/${this.agentId}/send-tool-approval`,
2265
+ {
2266
+ method: "POST",
2267
+ body: { ...rest, requestContext: parseClientRequestContext(requestContext) }
2268
+ }
2269
+ );
2270
+ }
2218
2271
  async declineToolCall(params) {
2219
2272
  const { requestContext, ...rest } = params;
2220
2273
  const processedParams = { ...rest, requestContext: parseClientRequestContext(requestContext) };