@databricks/ai-sdk-provider 0.3.0 → 0.4.1

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/README.md CHANGED
@@ -178,22 +178,6 @@ for await (const part of result.fullStream) {
178
178
  }
179
179
  ```
180
180
 
181
- ### MCP Utilities
182
-
183
- ```typescript
184
- import {
185
- MCP_APPROVAL_STATUS_KEY,
186
- MCP_APPROVAL_REQUEST_TYPE,
187
- MCP_APPROVAL_RESPONSE_TYPE,
188
- isMcpApprovalRequest,
189
- isMcpApprovalResponse,
190
- createApprovalStatusOutput,
191
- getMcpApprovalState,
192
- } from '@databricks/ai-sdk-provider'
193
- ```
194
-
195
- MCP (Model Context Protocol) approval utilities for handling approval workflows.
196
-
197
181
  ## Examples
198
182
 
199
183
  ### Responses Endpoint
package/dist/index.cjs CHANGED
@@ -615,119 +615,6 @@ const responsesAgentChunkSchema = zod_v4.z.union([
615
615
  */
616
616
  const looseResponseAgentChunkSchema = zod_v4.z.union([responsesAgentChunkSchema, zod_v4.z.object({ type: zod_v4.z.string() }).loose()]);
617
617
 
618
- //#endregion
619
- //#region src/mcp.ts
620
- /**
621
- * MCP Approval Utility Functions
622
- *
623
- * Shared utilities for handling MCP (Model Context Protocol) approval requests
624
- * and responses across client and server code.
625
- */
626
- /** Key used in tool output to indicate approval status */
627
- const MCP_APPROVAL_STATUS_KEY = "__approvalStatus__";
628
- /** Type string for MCP approval requests in provider metadata */
629
- const MCP_APPROVAL_REQUEST_TYPE = "mcp_approval_request";
630
- /** Type string for MCP approval responses in provider metadata */
631
- const MCP_APPROVAL_RESPONSE_TYPE = "mcp_approval_response";
632
- /**
633
- * Check if output contains an approval status marker.
634
- *
635
- * @example
636
- * if (isApprovalStatusOutput(output)) {
637
- * console.log(output.__approvalStatus__); // TypeScript knows this is boolean
638
- * }
639
- */
640
- function isApprovalStatusOutput(output) {
641
- return typeof output === "object" && output !== null && MCP_APPROVAL_STATUS_KEY in output && typeof output[MCP_APPROVAL_STATUS_KEY] === "boolean";
642
- }
643
- /**
644
- * Check if provider metadata indicates an MCP approval request.
645
- *
646
- * @example
647
- * const metadata = extractDatabricksMetadata(part);
648
- * if (isMcpApprovalRequest(metadata)) {
649
- * // Handle MCP approval request
650
- * }
651
- */
652
- function isMcpApprovalRequest(metadata) {
653
- return metadata?.type?.toString() === MCP_APPROVAL_REQUEST_TYPE;
654
- }
655
- /**
656
- * Check if provider metadata indicates an MCP approval response.
657
- */
658
- function isMcpApprovalResponse(metadata) {
659
- return metadata?.type?.toString() === MCP_APPROVAL_RESPONSE_TYPE;
660
- }
661
- /**
662
- * Extract Databricks metadata from a tool call part's callProviderMetadata.
663
- *
664
- * @example
665
- * const metadata = extractDatabricksMetadata(part);
666
- * const toolName = metadata?.toolName;
667
- * const isMcp = isMcpApprovalRequest(metadata);
668
- */
669
- function extractDatabricksMetadata(part) {
670
- if ("callProviderMetadata" in part && part.callProviderMetadata?.databricks) return part.callProviderMetadata.databricks;
671
- }
672
- /**
673
- * Extract the approval status boolean from an output object.
674
- *
675
- * @returns `true` if approved, `false` if denied, `undefined` if not an approval output
676
- *
677
- * @example
678
- * const status = extractApprovalStatus(output);
679
- * if (status !== undefined) {
680
- * console.log(status ? 'Approved' : 'Denied');
681
- * }
682
- */
683
- function extractApprovalStatus(output) {
684
- if (isApprovalStatusOutput(output)) return output[MCP_APPROVAL_STATUS_KEY];
685
- }
686
- /**
687
- * Extract approval status from a tool result's output value.
688
- * Handles the nested structure where output.type === 'json' and value contains the status.
689
- *
690
- * @example
691
- * const status = extractApprovalStatusFromToolResult(toolResult.output);
692
- */
693
- function extractApprovalStatusFromToolResult(output) {
694
- if (output.type === "json" && output.value && typeof output.value === "object" && MCP_APPROVAL_STATUS_KEY in output.value) {
695
- const value = output.value[MCP_APPROVAL_STATUS_KEY];
696
- if (typeof value === "boolean") return value;
697
- }
698
- }
699
- /**
700
- * Create an approval status output object.
701
- *
702
- * @example
703
- * await addToolResult({
704
- * toolCallId,
705
- * output: createApprovalStatusOutput(true), // Approve
706
- * });
707
- */
708
- function createApprovalStatusOutput(approve) {
709
- return { [MCP_APPROVAL_STATUS_KEY]: approve };
710
- }
711
- /**
712
- * Determine the MCP approval state from a tool output.
713
- *
714
- * Logic:
715
- * - No output → 'awaiting-approval' (user hasn't responded yet)
716
- * - Output with __approvalStatus__: true → 'approved'
717
- * - Output with __approvalStatus__: false → 'denied'
718
- * - Output without __approvalStatus__ → 'approved' (tool executed, so it was approved)
719
- *
720
- * @example
721
- * const approvalState = getMcpApprovalState(part.output);
722
- * // 'awaiting-approval' | 'approved' | 'denied'
723
- */
724
- function getMcpApprovalState(output) {
725
- if (!output) return "awaiting-approval";
726
- const status = extractApprovalStatus(output);
727
- if (status === void 0) return "approved";
728
- return status ? "approved" : "denied";
729
- }
730
-
731
618
  //#endregion
732
619
  //#region src/responses-agent-language-model/responses-convert-to-message-parts.ts
733
620
  const convertResponsesAgentChunkToMessagePart = (chunk, options = { useRemoteToolCalling: false }) => {
@@ -843,25 +730,24 @@ const convertOutputItemDone = (item, options) => {
843
730
  toolCallId: item.id,
844
731
  toolName: item.name,
845
732
  input: item.arguments,
846
- ...options.useRemoteToolCalling && {
847
- dynamic: true,
848
- providerExecuted: true
849
- },
733
+ providerExecuted: true,
734
+ dynamic: true,
850
735
  providerMetadata: { databricks: {
851
- type: MCP_APPROVAL_REQUEST_TYPE,
852
736
  itemId: item.id,
853
- serverLabel: item.server_label
737
+ serverLabel: item.server_label,
738
+ approvalRequestId: item.id
854
739
  } }
740
+ }, {
741
+ type: "tool-approval-request",
742
+ approvalId: item.id,
743
+ toolCallId: item.id
855
744
  }];
856
745
  case "mcp_approval_response": return [{
857
746
  type: "tool-result",
858
747
  toolCallId: item.approval_request_id,
859
748
  toolName: options.toolNamesByCallId?.get(item.approval_request_id) ?? "mcp_approval",
860
- result: createApprovalStatusOutput(item.approve),
861
- providerMetadata: { databricks: {
862
- type: MCP_APPROVAL_RESPONSE_TYPE,
863
- ...item.id != null && { itemId: item.id }
864
- } }
749
+ result: { approved: item.approve },
750
+ providerMetadata: { databricks: { itemId: item.id ?? item.approval_request_id } }
865
751
  }];
866
752
  default: return [];
867
753
  }
@@ -913,23 +799,27 @@ const convertResponsesAgentResponseToMessagePart = (response, options = { useRem
913
799
  toolCallId: output.id,
914
800
  toolName: output.name,
915
801
  input: output.arguments,
802
+ providerExecuted: true,
803
+ dynamic: true,
916
804
  providerMetadata: { databricks: {
917
- type: MCP_APPROVAL_REQUEST_TYPE,
918
805
  itemId: output.id,
919
- serverLabel: output.server_label
806
+ serverLabel: output.server_label,
807
+ approvalRequestId: output.id
920
808
  } }
921
809
  });
810
+ parts.push({
811
+ type: "tool-approval-request",
812
+ approvalId: output.id,
813
+ toolCallId: output.id
814
+ });
922
815
  break;
923
816
  case "mcp_approval_response":
924
817
  parts.push({
925
818
  type: "tool-result",
926
819
  toolCallId: output.approval_request_id,
927
820
  toolName: toolNamesByCallId.get(output.approval_request_id) ?? "mcp_approval",
928
- result: createApprovalStatusOutput(output.approve),
929
- providerMetadata: { databricks: {
930
- type: MCP_APPROVAL_RESPONSE_TYPE,
931
- ...output.id != null && { itemId: output.id }
932
- } }
821
+ result: { approved: output.approve },
822
+ providerMetadata: { databricks: { itemId: output.id ?? output.approval_request_id } }
933
823
  });
934
824
  break;
935
825
  default: break;
@@ -942,6 +832,8 @@ const convertResponsesAgentResponseToMessagePart = (response, options = { useRem
942
832
  async function convertToResponsesInput({ prompt, systemMessageMode }) {
943
833
  const input = [];
944
834
  const warnings = [];
835
+ const processedApprovalIds = /* @__PURE__ */ new Set();
836
+ const approvalIdsWithToolResult = /* @__PURE__ */ new Set();
945
837
  const toolCallResultsByToolCallId = prompt.filter((p) => p.role === "tool").flatMap((p) => p.content).reduce((reduction, toolCallResult) => {
946
838
  if (toolCallResult.type === "tool-result") reduction[toolCallResult.toolCallId] = toolCallResult;
947
839
  return reduction;
@@ -1008,37 +900,16 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
1008
900
  break;
1009
901
  case "tool-call": {
1010
902
  const toolName = providerOptions?.toolName ?? part.toolName;
1011
- if (providerOptions?.type === MCP_APPROVAL_REQUEST_TYPE) {
903
+ const approvalRequestId = providerOptions?.approvalRequestId;
904
+ if (approvalRequestId) {
1012
905
  const serverLabel = providerOptions?.serverLabel ?? "";
1013
- const argumentsString = JSON.stringify(part.input);
1014
- const id = part.toolCallId;
1015
906
  input.push({
1016
- type: MCP_APPROVAL_REQUEST_TYPE,
1017
- id,
907
+ type: "mcp_approval_request",
908
+ id: approvalRequestId,
1018
909
  name: toolName,
1019
- arguments: argumentsString,
910
+ arguments: JSON.stringify(part.input),
1020
911
  server_label: serverLabel
1021
912
  });
1022
- const toolResult = toolCallResultsByToolCallId[part.toolCallId];
1023
- if (toolResult) {
1024
- /**
1025
- * The tool call result is either the approval status or the actual output from the tool call.
1026
- * If it's the approval status, we need to add an approval response part.
1027
- * If it's the tool call output, we don't include the approval response part but we do include the tool call output part.
1028
- */
1029
- const approvalStatus = extractApprovalStatusFromToolResult(toolResult.output);
1030
- if (approvalStatus !== void 0) input.push({
1031
- type: MCP_APPROVAL_RESPONSE_TYPE,
1032
- id: toolResult.toolCallId,
1033
- approval_request_id: toolResult.toolCallId,
1034
- approve: approvalStatus
1035
- });
1036
- else input.push({
1037
- type: "function_call_output",
1038
- call_id: toolResult.toolCallId,
1039
- output: convertToolResultOutputToString(toolResult.output)
1040
- });
1041
- }
1042
913
  break;
1043
914
  }
1044
915
  input.push({
@@ -1057,24 +928,12 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
1057
928
  break;
1058
929
  }
1059
930
  case "tool-result":
1060
- if (providerOptions?.type === MCP_APPROVAL_RESPONSE_TYPE) {
1061
- const approvalRequestId = providerOptions?.approvalRequestId ?? part.toolCallId;
1062
- const approve = providerOptions?.approve ?? false;
1063
- const reason = providerOptions?.reason ?? "";
1064
- input.push({
1065
- type: MCP_APPROVAL_RESPONSE_TYPE,
1066
- id: approvalRequestId,
1067
- approval_request_id: approvalRequestId,
1068
- approve,
1069
- reason
1070
- });
1071
- break;
1072
- }
1073
931
  input.push({
1074
932
  type: "function_call_output",
1075
933
  call_id: part.toolCallId,
1076
934
  output: convertToolResultOutputToString(part.output)
1077
935
  });
936
+ approvalIdsWithToolResult.add(part.toolCallId);
1078
937
  break;
1079
938
  case "reasoning":
1080
939
  if (!itemId) break;
@@ -1090,7 +949,20 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
1090
949
  }
1091
950
  }
1092
951
  break;
1093
- case "tool": break;
952
+ case "tool":
953
+ for (const part of content) if (part.type === "tool-approval-response") {
954
+ if (processedApprovalIds.has(part.approvalId)) continue;
955
+ processedApprovalIds.add(part.approvalId);
956
+ if (approvalIdsWithToolResult.has(part.approvalId)) continue;
957
+ input.push({
958
+ type: "mcp_approval_response",
959
+ id: part.approvalId,
960
+ approval_request_id: part.approvalId,
961
+ approve: part.approved,
962
+ ...part.reason && { reason: part.reason }
963
+ });
964
+ }
965
+ break;
1094
966
  default: {
1095
967
  const _exhaustiveCheck = role;
1096
968
  throw new Error(`Unsupported role: ${String(_exhaustiveCheck)}`);
@@ -1104,11 +976,8 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
1104
976
  const ProviderOptionsSchema$1 = zod_v4.z.object({
1105
977
  itemId: zod_v4.z.string().nullish(),
1106
978
  toolName: zod_v4.z.string().nullish(),
1107
- type: zod_v4.z.enum(["mcp_approval_request", "mcp_approval_response"]).nullish(),
1108
979
  serverLabel: zod_v4.z.string().nullish(),
1109
- approvalRequestId: zod_v4.z.string().nullish(),
1110
- approve: zod_v4.z.boolean().nullish(),
1111
- reason: zod_v4.z.string().nullish()
980
+ approvalRequestId: zod_v4.z.string().nullish()
1112
981
  });
1113
982
  const convertToolResultOutputToString = (output) => {
1114
983
  switch (output.type) {
@@ -1406,7 +1275,9 @@ var DatabricksResponsesAgentLanguageModel = class {
1406
1275
  type: "tool-call",
1407
1276
  toolCallId: toolCallFromPreviousMessages.toolCallId,
1408
1277
  toolName: toolCallFromPreviousMessages.toolName,
1409
- input: JSON.stringify(toolCallFromPreviousMessages.input)
1278
+ input: JSON.stringify(toolCallFromPreviousMessages.input),
1279
+ providerExecuted: true,
1280
+ dynamic: true
1410
1281
  });
1411
1282
  }
1412
1283
  }
@@ -1418,7 +1289,7 @@ var DatabricksResponsesAgentLanguageModel = class {
1418
1289
  const toolCalls = allParts.filter((p) => p.type === "tool-call");
1419
1290
  const toolResults = allParts.filter((p) => p.type === "tool-result");
1420
1291
  for (const toolCall of toolCalls) {
1421
- if (toolCall.providerMetadata?.databricks?.type === MCP_APPROVAL_REQUEST_TYPE) continue;
1292
+ if (toolCall.providerMetadata?.databricks?.approvalRequestId != null) continue;
1422
1293
  if (!toolResults.some((r) => r.toolCallId === toolCall.toolCallId)) controller.enqueue({
1423
1294
  ...toolCall,
1424
1295
  providerExecuted: true,
@@ -2212,16 +2083,5 @@ const createDatabricksProvider = (settings) => {
2212
2083
  };
2213
2084
 
2214
2085
  //#endregion
2215
- exports.MCP_APPROVAL_REQUEST_TYPE = MCP_APPROVAL_REQUEST_TYPE;
2216
- exports.MCP_APPROVAL_RESPONSE_TYPE = MCP_APPROVAL_RESPONSE_TYPE;
2217
- exports.MCP_APPROVAL_STATUS_KEY = MCP_APPROVAL_STATUS_KEY;
2218
- exports.createApprovalStatusOutput = createApprovalStatusOutput;
2219
2086
  exports.createDatabricksProvider = createDatabricksProvider;
2220
- exports.extractApprovalStatus = extractApprovalStatus;
2221
- exports.extractApprovalStatusFromToolResult = extractApprovalStatusFromToolResult;
2222
- exports.extractDatabricksMetadata = extractDatabricksMetadata;
2223
- exports.getMcpApprovalState = getMcpApprovalState;
2224
- exports.isApprovalStatusOutput = isApprovalStatusOutput;
2225
- exports.isMcpApprovalRequest = isMcpApprovalRequest;
2226
- exports.isMcpApprovalResponse = isMcpApprovalResponse;
2227
2087
  //# sourceMappingURL=index.cjs.map