@databricks/ai-sdk-provider 0.2.3 → 0.4.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.
@@ -46,26 +46,6 @@ const chatAgentResponseSchema = z.object({
46
46
  messages: z.array(chatAgentMessageSchema)
47
47
  });
48
48
 
49
- //#endregion
50
- //#region src/tools.ts
51
- const DATABRICKS_TOOL_CALL_ID = "databricks-tool-call";
52
- /**
53
- * The AI-SDK requires that tools used by the model are defined ahead of time.
54
- *
55
- * Since tool calls can be orchestrated by Databricks' agents we don't know the name, input, or output schemas
56
- * of the tools until the model is called.
57
- *
58
- * In the DatabricksProvider we transform all tool calls to fit this definition, and keep the
59
- * original name as part of the metadata. This allows us to parse any tool orchestrated by Databricks' agents,
60
- * while still being able to render the tool call and result in the UI, and pass it back to the model with the correct name.
61
- */
62
- const DATABRICKS_TOOL_DEFINITION = {
63
- name: DATABRICKS_TOOL_CALL_ID,
64
- description: "Databricks tool call",
65
- inputSchema: z.any(),
66
- outputSchema: z.any()
67
- };
68
-
69
49
  //#endregion
70
50
  //#region src/chat-agent-language-model/chat-agent-convert-to-message-parts.ts
71
51
  const convertChatAgentChunkToMessagePart = (chunk) => {
@@ -81,14 +61,16 @@ const convertChatAgentChunkToMessagePart = (chunk) => {
81
61
  type: "tool-call",
82
62
  toolCallId: toolCall.id,
83
63
  input: toolCall.function.arguments,
84
- toolName: toolCall.function.name
64
+ toolName: toolCall.function.name,
65
+ dynamic: true,
66
+ providerExecuted: true
85
67
  });
86
68
  });
87
69
  } else if (chunk.delta.role === "tool") parts.push({
88
70
  type: "tool-result",
89
71
  toolCallId: chunk.delta.tool_call_id,
90
72
  result: chunk.delta.content,
91
- toolName: DATABRICKS_TOOL_CALL_ID
73
+ toolName: chunk.delta.name ?? "unknown"
92
74
  });
93
75
  return parts;
94
76
  };
@@ -103,20 +85,22 @@ const convertChatAgentResponseToMessagePart = (response) => {
103
85
  type: "tool-call",
104
86
  toolCallId: part.id,
105
87
  input: part.function.arguments,
106
- toolName: part.function.name
88
+ toolName: part.function.name,
89
+ dynamic: true,
90
+ providerExecuted: true
107
91
  });
108
92
  } else if (message.role === "tool") parts.push({
109
93
  type: "tool-result",
110
94
  toolCallId: message.tool_call_id,
111
95
  result: message.content,
112
- toolName: DATABRICKS_TOOL_CALL_ID
96
+ toolName: message.name ?? "unknown"
113
97
  });
114
98
  return parts;
115
99
  };
116
100
 
117
101
  //#endregion
118
102
  //#region src/chat-agent-language-model/chat-agent-convert-to-input.ts
119
- const convertLanguageModelV2PromptToChatAgentResponse = (prompt) => {
103
+ const convertLanguageModelV3PromptToChatAgentResponse = (prompt) => {
120
104
  const messages = [];
121
105
  let messageIndex = 0;
122
106
  for (const msg of prompt) switch (msg.role) {
@@ -143,10 +127,9 @@ const convertLanguageModelV2PromptToChatAgentResponse = (prompt) => {
143
127
  return messages;
144
128
  };
145
129
  const convertUserMessage$1 = (msg, messageIndex) => {
146
- const text = (msg.content ?? []).filter((part) => part.type === "text").map((part) => part.text).join("\n");
147
130
  return {
148
131
  role: "user",
149
- content: text,
132
+ content: (msg.content ?? []).filter((part) => part.type === "text").map((part) => part.text).join("\n"),
150
133
  id: `user-${messageIndex}`
151
134
  };
152
135
  };
@@ -219,10 +202,7 @@ const convertToolResultOutput = (output) => {
219
202
  function composeDatabricksStreamPartTransformers(...transformers) {
220
203
  return (initialParts, last = null) => {
221
204
  let currentParts = initialParts;
222
- for (const fn of transformers) {
223
- const result = fn(currentParts, last);
224
- currentParts = result.out;
225
- }
205
+ for (const fn of transformers) currentParts = fn(currentParts, last).out;
226
206
  return { out: currentParts };
227
207
  };
228
208
  }
@@ -239,8 +219,7 @@ const applyDeltaBoundaryTransform = (parts, last) => {
239
219
  const incomingDeltaType = maybeGetDeltaType(incoming);
240
220
  const incomingId = getPartId$1(incoming);
241
221
  const lastId = getPartId$1(last);
242
- const incomingMatchesLast = Boolean(isDeltaPart(last) && isDeltaPart(incoming)) && Boolean(lastDeltaType && incomingDeltaType) && Boolean(lastDeltaType === incomingDeltaType) && Boolean(incomingId && lastId && incomingId === lastId);
243
- if (incomingMatchesLast) {
222
+ if (Boolean(isDeltaPart(last) && isDeltaPart(incoming)) && Boolean(lastDeltaType && incomingDeltaType) && Boolean(lastDeltaType === incomingDeltaType) && Boolean(incomingId && lastId && incomingId === lastId)) {
244
223
  out.push(incoming);
245
224
  continue;
246
225
  }
@@ -256,7 +235,6 @@ const applyDeltaBoundaryTransform = (parts, last) => {
256
235
  continue;
257
236
  }
258
237
  out.push(incoming);
259
- continue;
260
238
  }
261
239
  return { out };
262
240
  };
@@ -275,7 +253,6 @@ const getDeltaType = (part) => {
275
253
  const isDeltaPart = (part) => part?.type === "text-delta" || part?.type === "reasoning-delta";
276
254
  const getPartId$1 = (part) => {
277
255
  if (part && "id" in part) return part.id;
278
- return void 0;
279
256
  };
280
257
 
281
258
  //#endregion
@@ -288,7 +265,7 @@ const getPartId$1 = (part) => {
288
265
  */
289
266
  const getDatabricksLanguageModelTransformStream = () => {
290
267
  let lastChunk = null;
291
- const deltaEndByTypeAndId = new Set();
268
+ const deltaEndByTypeAndId = /* @__PURE__ */ new Set();
292
269
  const transformerStreamParts = composeDatabricksStreamPartTransformers(applyDeltaBoundaryTransform);
293
270
  return new TransformStream({
294
271
  transform(chunk, controller) {
@@ -330,14 +307,13 @@ const getDeltaGroup = (type) => {
330
307
  };
331
308
  const getPartId = (part) => {
332
309
  if ("id" in part) return part.id;
333
- return void 0;
334
310
  };
335
311
  const makeEndKey = (id, group) => id && group ? `${group}:${id}` : null;
336
312
 
337
313
  //#endregion
338
314
  //#region src/chat-agent-language-model/chat-agent-language-model.ts
339
315
  var DatabricksChatAgentLanguageModel = class {
340
- specificationVersion = "v2";
316
+ specificationVersion = "v3";
341
317
  modelId;
342
318
  config;
343
319
  constructor(modelId, config) {
@@ -349,14 +325,13 @@ var DatabricksChatAgentLanguageModel = class {
349
325
  }
350
326
  supportedUrls = {};
351
327
  async doGenerate(options) {
352
- const networkArgs = this.getArgs({
353
- config: this.config,
354
- options,
355
- stream: false,
356
- modelId: this.modelId
357
- });
358
328
  const { value: response } = await postJsonToApi({
359
- ...networkArgs,
329
+ ...this.getArgs({
330
+ config: this.config,
331
+ options,
332
+ stream: false,
333
+ modelId: this.modelId
334
+ }),
360
335
  successfulResponseHandler: createJsonResponseHandler(chatAgentResponseSchema),
361
336
  failedResponseHandler: createJsonErrorResponseHandler({
362
337
  errorSchema: z.any(),
@@ -366,11 +341,22 @@ var DatabricksChatAgentLanguageModel = class {
366
341
  });
367
342
  return {
368
343
  content: convertChatAgentResponseToMessagePart(response),
369
- finishReason: "stop",
344
+ finishReason: {
345
+ raw: void 0,
346
+ unified: "stop"
347
+ },
370
348
  usage: {
371
- inputTokens: 0,
372
- outputTokens: 0,
373
- totalTokens: 0
349
+ inputTokens: {
350
+ total: 0,
351
+ noCache: 0,
352
+ cacheRead: 0,
353
+ cacheWrite: 0
354
+ },
355
+ outputTokens: {
356
+ total: 0,
357
+ text: 0,
358
+ reasoning: 0
359
+ }
374
360
  },
375
361
  warnings: []
376
362
  };
@@ -391,7 +377,10 @@ var DatabricksChatAgentLanguageModel = class {
391
377
  }),
392
378
  successfulResponseHandler: createEventSourceResponseHandler(chatAgentChunkSchema)
393
379
  });
394
- let finishReason = "unknown";
380
+ let finishReason = {
381
+ raw: void 0,
382
+ unified: "other"
383
+ };
395
384
  return {
396
385
  stream: response.pipeThrough(new TransformStream({
397
386
  start(controller) {
@@ -406,7 +395,10 @@ var DatabricksChatAgentLanguageModel = class {
406
395
  rawValue: chunk.rawValue
407
396
  });
408
397
  if (!chunk.success) {
409
- finishReason = "error";
398
+ finishReason = {
399
+ raw: void 0,
400
+ unified: "error"
401
+ };
410
402
  controller.enqueue({
411
403
  type: "error",
412
404
  error: chunk.error
@@ -421,9 +413,17 @@ var DatabricksChatAgentLanguageModel = class {
421
413
  type: "finish",
422
414
  finishReason,
423
415
  usage: {
424
- inputTokens: 0,
425
- outputTokens: 0,
426
- totalTokens: 0
416
+ inputTokens: {
417
+ total: 0,
418
+ noCache: 0,
419
+ cacheRead: 0,
420
+ cacheWrite: 0
421
+ },
422
+ outputTokens: {
423
+ total: 0,
424
+ text: 0,
425
+ reasoning: 0
426
+ }
427
427
  }
428
428
  });
429
429
  }
@@ -437,7 +437,7 @@ var DatabricksChatAgentLanguageModel = class {
437
437
  body: {
438
438
  model: modelId,
439
439
  stream,
440
- messages: convertLanguageModelV2PromptToChatAgentResponse(options.prompt)
440
+ messages: convertLanguageModelV3PromptToChatAgentResponse(options.prompt)
441
441
  },
442
442
  url: config.url({ path: "/completions" }),
443
443
  headers: combineHeaders(config.headers(), options.headers),
@@ -615,125 +615,9 @@ const responsesAgentChunkSchema = z.union([
615
615
  */
616
616
  const looseResponseAgentChunkSchema = z.union([responsesAgentChunkSchema, z.object({ type: 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
- return void 0;
672
- }
673
- /**
674
- * Extract the approval status boolean from an output object.
675
- *
676
- * @returns `true` if approved, `false` if denied, `undefined` if not an approval output
677
- *
678
- * @example
679
- * const status = extractApprovalStatus(output);
680
- * if (status !== undefined) {
681
- * console.log(status ? 'Approved' : 'Denied');
682
- * }
683
- */
684
- function extractApprovalStatus(output) {
685
- if (isApprovalStatusOutput(output)) return output[MCP_APPROVAL_STATUS_KEY];
686
- return void 0;
687
- }
688
- /**
689
- * Extract approval status from a tool result's output value.
690
- * Handles the nested structure where output.type === 'json' and value contains the status.
691
- *
692
- * @example
693
- * const status = extractApprovalStatusFromToolResult(toolResult.output);
694
- */
695
- function extractApprovalStatusFromToolResult(output) {
696
- if (output.type === "json" && output.value && typeof output.value === "object" && MCP_APPROVAL_STATUS_KEY in output.value) {
697
- const value = output.value[MCP_APPROVAL_STATUS_KEY];
698
- if (typeof value === "boolean") return value;
699
- }
700
- return void 0;
701
- }
702
- /**
703
- * Create an approval status output object.
704
- *
705
- * @example
706
- * await addToolResult({
707
- * toolCallId,
708
- * output: createApprovalStatusOutput(true), // Approve
709
- * });
710
- */
711
- function createApprovalStatusOutput(approve) {
712
- return { [MCP_APPROVAL_STATUS_KEY]: approve };
713
- }
714
- /**
715
- * Determine the MCP approval state from a tool output.
716
- *
717
- * Logic:
718
- * - No output → 'awaiting-approval' (user hasn't responded yet)
719
- * - Output with __approvalStatus__: true → 'approved'
720
- * - Output with __approvalStatus__: false → 'denied'
721
- * - Output without __approvalStatus__ → 'approved' (tool executed, so it was approved)
722
- *
723
- * @example
724
- * const approvalState = getMcpApprovalState(part.output);
725
- * // 'awaiting-approval' | 'approved' | 'denied'
726
- */
727
- function getMcpApprovalState(output) {
728
- if (!output) return "awaiting-approval";
729
- const status = extractApprovalStatus(output);
730
- if (status === void 0) return "approved";
731
- return status ? "approved" : "denied";
732
- }
733
-
734
618
  //#endregion
735
619
  //#region src/responses-agent-language-model/responses-convert-to-message-parts.ts
736
- const convertResponsesAgentChunkToMessagePart = (chunk) => {
620
+ const convertResponsesAgentChunkToMessagePart = (chunk, options = { useRemoteToolCalling: false }) => {
737
621
  const parts = [];
738
622
  if ("error" in chunk) {
739
623
  parts.push({
@@ -763,12 +647,12 @@ const convertResponsesAgentChunkToMessagePart = (chunk) => {
763
647
  parts.push({
764
648
  type: "tool-result",
765
649
  toolCallId: chunk.call_id,
766
- result: chunk.output,
767
- toolName: DATABRICKS_TOOL_CALL_ID
650
+ result: chunk.output != null ? chunk.output : {},
651
+ toolName: options.toolNamesByCallId?.get(chunk.call_id) ?? "unknown"
768
652
  });
769
653
  break;
770
654
  case "response.output_item.done":
771
- parts.push(...convertOutputItemDone(chunk.item));
655
+ parts.push(...convertOutputItemDone(chunk.item, options));
772
656
  break;
773
657
  case "response.output_text.annotation.added":
774
658
  parts.push({
@@ -789,7 +673,7 @@ const convertResponsesAgentChunkToMessagePart = (chunk) => {
789
673
  }
790
674
  return parts;
791
675
  };
792
- const convertOutputItemDone = (item) => {
676
+ const convertOutputItemDone = (item, options) => {
793
677
  switch (item.type) {
794
678
  case "message": {
795
679
  const firstContent = item.content[0];
@@ -807,18 +691,19 @@ const convertOutputItemDone = (item) => {
807
691
  case "function_call": return [{
808
692
  type: "tool-call",
809
693
  toolCallId: item.call_id,
810
- toolName: DATABRICKS_TOOL_CALL_ID,
694
+ toolName: item.name,
811
695
  input: item.arguments,
812
- providerMetadata: { databricks: {
813
- toolName: item.name,
814
- itemId: item.id
815
- } }
696
+ ...options.useRemoteToolCalling && {
697
+ dynamic: true,
698
+ providerExecuted: true
699
+ },
700
+ providerMetadata: { databricks: { itemId: item.id } }
816
701
  }];
817
702
  case "function_call_output": return [{
818
703
  type: "tool-result",
819
704
  toolCallId: item.call_id,
820
- result: item.output,
821
- toolName: DATABRICKS_TOOL_CALL_ID
705
+ result: item.output != null ? item.output : {},
706
+ toolName: options.toolNamesByCallId?.get(item.call_id) ?? "unknown"
822
707
  }];
823
708
  case "reasoning": {
824
709
  const firstSummary = item.summary[0];
@@ -843,49 +728,54 @@ const convertOutputItemDone = (item) => {
843
728
  case "mcp_approval_request": return [{
844
729
  type: "tool-call",
845
730
  toolCallId: item.id,
846
- toolName: DATABRICKS_TOOL_CALL_ID,
731
+ toolName: item.name,
847
732
  input: item.arguments,
733
+ providerExecuted: true,
734
+ dynamic: true,
848
735
  providerMetadata: { databricks: {
849
- type: MCP_APPROVAL_REQUEST_TYPE,
850
- toolName: item.name,
851
736
  itemId: item.id,
852
- serverLabel: item.server_label
737
+ serverLabel: item.server_label,
738
+ approvalRequestId: item.id
853
739
  } }
740
+ }, {
741
+ type: "tool-approval-request",
742
+ approvalId: item.id,
743
+ toolCallId: item.id
854
744
  }];
855
745
  case "mcp_approval_response": return [{
856
746
  type: "tool-result",
857
747
  toolCallId: item.approval_request_id,
858
- toolName: DATABRICKS_TOOL_CALL_ID,
859
- result: createApprovalStatusOutput(item.approve),
860
- providerMetadata: { databricks: {
861
- type: MCP_APPROVAL_RESPONSE_TYPE,
862
- ...item.id != null && { itemId: item.id }
863
- } }
748
+ toolName: options.toolNamesByCallId?.get(item.approval_request_id) ?? "mcp_approval",
749
+ result: { approved: item.approve },
750
+ providerMetadata: { databricks: { itemId: item.id ?? item.approval_request_id } }
864
751
  }];
865
752
  default: return [];
866
753
  }
867
754
  };
868
- const convertResponsesAgentResponseToMessagePart = (response) => {
755
+ const convertResponsesAgentResponseToMessagePart = (response, options = { useRemoteToolCalling: false }) => {
869
756
  const parts = [];
757
+ const toolNamesByCallId = /* @__PURE__ */ new Map();
758
+ for (const output of response.output) if (output.type === "function_call") toolNamesByCallId.set(output.call_id, output.name);
759
+ else if (output.type === "mcp_approval_request") toolNamesByCallId.set(output.id, output.name);
870
760
  for (const output of response.output) switch (output.type) {
871
- case "message": {
761
+ case "message":
872
762
  for (const content of output.content) if (content.type === "output_text") parts.push({
873
763
  type: "text",
874
764
  text: content.text,
875
765
  providerMetadata: { databricks: { itemId: output.id } }
876
766
  });
877
767
  break;
878
- }
879
768
  case "function_call":
880
769
  parts.push({
881
770
  type: "tool-call",
882
771
  toolCallId: output.call_id,
883
- toolName: DATABRICKS_TOOL_CALL_ID,
772
+ toolName: output.name,
884
773
  input: output.arguments,
885
- providerMetadata: { databricks: {
886
- toolName: output.name,
887
- itemId: output.id
888
- } }
774
+ ...options.useRemoteToolCalling && {
775
+ dynamic: true,
776
+ providerExecuted: true
777
+ },
778
+ providerMetadata: { databricks: { itemId: output.id } }
889
779
  });
890
780
  break;
891
781
  case "reasoning":
@@ -900,33 +790,36 @@ const convertResponsesAgentResponseToMessagePart = (response) => {
900
790
  type: "tool-result",
901
791
  result: output.output,
902
792
  toolCallId: output.call_id,
903
- toolName: DATABRICKS_TOOL_CALL_ID
793
+ toolName: toolNamesByCallId.get(output.call_id) ?? "unknown"
904
794
  });
905
795
  break;
906
796
  case "mcp_approval_request":
907
797
  parts.push({
908
798
  type: "tool-call",
909
799
  toolCallId: output.id,
910
- toolName: DATABRICKS_TOOL_CALL_ID,
800
+ toolName: output.name,
911
801
  input: output.arguments,
802
+ providerExecuted: true,
803
+ dynamic: true,
912
804
  providerMetadata: { databricks: {
913
- type: MCP_APPROVAL_REQUEST_TYPE,
914
- toolName: output.name,
915
805
  itemId: output.id,
916
- serverLabel: output.server_label
806
+ serverLabel: output.server_label,
807
+ approvalRequestId: output.id
917
808
  } }
918
809
  });
810
+ parts.push({
811
+ type: "tool-approval-request",
812
+ approvalId: output.id,
813
+ toolCallId: output.id
814
+ });
919
815
  break;
920
816
  case "mcp_approval_response":
921
817
  parts.push({
922
818
  type: "tool-result",
923
819
  toolCallId: output.approval_request_id,
924
- toolName: DATABRICKS_TOOL_CALL_ID,
925
- result: createApprovalStatusOutput(output.approve),
926
- providerMetadata: { databricks: {
927
- type: MCP_APPROVAL_RESPONSE_TYPE,
928
- ...output.id != null && { itemId: output.id }
929
- } }
820
+ toolName: toolNamesByCallId.get(output.approval_request_id) ?? "mcp_approval",
821
+ result: { approved: output.approve },
822
+ providerMetadata: { databricks: { itemId: output.id ?? output.approval_request_id } }
930
823
  });
931
824
  break;
932
825
  default: break;
@@ -939,12 +832,14 @@ const convertResponsesAgentResponseToMessagePart = (response) => {
939
832
  async function convertToResponsesInput({ prompt, systemMessageMode }) {
940
833
  const input = [];
941
834
  const warnings = [];
835
+ const processedApprovalIds = /* @__PURE__ */ new Set();
836
+ const approvalIdsWithToolResult = /* @__PURE__ */ new Set();
942
837
  const toolCallResultsByToolCallId = prompt.filter((p) => p.role === "tool").flatMap((p) => p.content).reduce((reduction, toolCallResult) => {
943
838
  if (toolCallResult.type === "tool-result") reduction[toolCallResult.toolCallId] = toolCallResult;
944
839
  return reduction;
945
840
  }, {});
946
841
  for (const { role, content } of prompt) switch (role) {
947
- case "system": {
842
+ case "system":
948
843
  switch (systemMessageMode) {
949
844
  case "system":
950
845
  input.push({
@@ -970,7 +865,6 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
970
865
  }
971
866
  }
972
867
  break;
973
- }
974
868
  case "user":
975
869
  input.push({
976
870
  role: "user",
@@ -994,7 +888,7 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
994
888
  });
995
889
  const itemId = providerOptions?.itemId ?? void 0;
996
890
  switch (part.type) {
997
- case "text": {
891
+ case "text":
998
892
  input.push({
999
893
  role: "assistant",
1000
894
  content: [{
@@ -1004,40 +898,18 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
1004
898
  id: itemId
1005
899
  });
1006
900
  break;
1007
- }
1008
901
  case "tool-call": {
1009
902
  const toolName = providerOptions?.toolName ?? part.toolName;
1010
- if (providerOptions?.type === MCP_APPROVAL_REQUEST_TYPE) {
903
+ const approvalRequestId = providerOptions?.approvalRequestId;
904
+ if (approvalRequestId) {
1011
905
  const serverLabel = providerOptions?.serverLabel ?? "";
1012
- const argumentsString = JSON.stringify(part.input);
1013
- const id = part.toolCallId;
1014
906
  input.push({
1015
- type: MCP_APPROVAL_REQUEST_TYPE,
1016
- id,
907
+ type: "mcp_approval_request",
908
+ id: approvalRequestId,
1017
909
  name: toolName,
1018
- arguments: argumentsString,
910
+ arguments: JSON.stringify(part.input),
1019
911
  server_label: serverLabel
1020
912
  });
1021
- const toolResult = toolCallResultsByToolCallId[part.toolCallId];
1022
- if (toolResult) {
1023
- /**
1024
- * The tool call result is either the approval status or the actual output from the tool call.
1025
- * If it's the approval status, we need to add an approval response part.
1026
- * If it's the tool call output, we don't include the approval response part but we do include the tool call output part.
1027
- */
1028
- const approvalStatus = extractApprovalStatusFromToolResult(toolResult.output);
1029
- if (approvalStatus !== void 0) input.push({
1030
- type: MCP_APPROVAL_RESPONSE_TYPE,
1031
- id: toolResult.toolCallId,
1032
- approval_request_id: toolResult.toolCallId,
1033
- approve: approvalStatus
1034
- });
1035
- else input.push({
1036
- type: "function_call_output",
1037
- call_id: toolResult.toolCallId,
1038
- output: convertToolResultOutputToString(toolResult.output)
1039
- });
1040
- }
1041
913
  break;
1042
914
  }
1043
915
  input.push({
@@ -1055,28 +927,15 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
1055
927
  });
1056
928
  break;
1057
929
  }
1058
- case "tool-result": {
1059
- if (providerOptions?.type === MCP_APPROVAL_RESPONSE_TYPE) {
1060
- const approvalRequestId = providerOptions?.approvalRequestId ?? part.toolCallId;
1061
- const approve = providerOptions?.approve ?? false;
1062
- const reason = providerOptions?.reason ?? "";
1063
- input.push({
1064
- type: MCP_APPROVAL_RESPONSE_TYPE,
1065
- id: approvalRequestId,
1066
- approval_request_id: approvalRequestId,
1067
- approve,
1068
- reason
1069
- });
1070
- break;
1071
- }
930
+ case "tool-result":
1072
931
  input.push({
1073
932
  type: "function_call_output",
1074
933
  call_id: part.toolCallId,
1075
934
  output: convertToolResultOutputToString(part.output)
1076
935
  });
936
+ approvalIdsWithToolResult.add(part.toolCallId);
1077
937
  break;
1078
- }
1079
- case "reasoning": {
938
+ case "reasoning":
1080
939
  if (!itemId) break;
1081
940
  input.push({
1082
941
  type: "reasoning",
@@ -1087,11 +946,22 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
1087
946
  id: itemId
1088
947
  });
1089
948
  break;
1090
- }
1091
949
  }
1092
950
  }
1093
951
  break;
1094
- 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
+ approval_request_id: part.approvalId,
960
+ approve: part.approved,
961
+ ...part.reason && { reason: part.reason }
962
+ });
963
+ }
964
+ break;
1095
965
  default: {
1096
966
  const _exhaustiveCheck = role;
1097
967
  throw new Error(`Unsupported role: ${String(_exhaustiveCheck)}`);
@@ -1105,17 +975,17 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
1105
975
  const ProviderOptionsSchema$1 = z.object({
1106
976
  itemId: z.string().nullish(),
1107
977
  toolName: z.string().nullish(),
1108
- type: z.enum(["mcp_approval_request", "mcp_approval_response"]).nullish(),
1109
978
  serverLabel: z.string().nullish(),
1110
- approvalRequestId: z.string().nullish(),
1111
- approve: z.boolean().nullish(),
1112
- reason: z.string().nullish()
979
+ approvalRequestId: z.string().nullish()
1113
980
  });
1114
981
  const convertToolResultOutputToString = (output) => {
1115
982
  switch (output.type) {
1116
983
  case "text":
1117
984
  case "error-text": return output.value;
1118
- default: return JSON.stringify(output.value);
985
+ case "execution-denied": return output.reason ?? "Execution denied";
986
+ case "json":
987
+ case "error-json":
988
+ case "content": return JSON.stringify(output.value);
1119
989
  }
1120
990
  };
1121
991
 
@@ -1133,7 +1003,7 @@ function prepareResponsesTools({ tools, toolChoice }) {
1133
1003
  };
1134
1004
  const responsesTools = [];
1135
1005
  for (const tool of tools) {
1136
- if (tool.type === "provider-defined" || tool.name === DATABRICKS_TOOL_CALL_ID) continue;
1006
+ if (tool.type === "provider") continue;
1137
1007
  responsesTools.push({
1138
1008
  type: "function",
1139
1009
  name: tool.name,
@@ -1145,14 +1015,13 @@ function prepareResponsesTools({ tools, toolChoice }) {
1145
1015
  tools: void 0,
1146
1016
  toolChoice: void 0
1147
1017
  };
1148
- const convertedToolChoice = convertResponsesToolChoice(toolChoice);
1149
1018
  return {
1150
1019
  tools: responsesTools,
1151
- toolChoice: convertedToolChoice
1020
+ toolChoice: convertResponsesToolChoice(toolChoice)
1152
1021
  };
1153
1022
  }
1154
1023
  function convertResponsesToolChoice(toolChoice) {
1155
- if (!toolChoice) return void 0;
1024
+ if (!toolChoice) return;
1156
1025
  switch (toolChoice.type) {
1157
1026
  case "auto": return "auto";
1158
1027
  case "none": return "none";
@@ -1161,14 +1030,14 @@ function convertResponsesToolChoice(toolChoice) {
1161
1030
  type: "function",
1162
1031
  name: toolChoice.toolName
1163
1032
  };
1164
- default: return void 0;
1033
+ default: return;
1165
1034
  }
1166
1035
  }
1167
1036
 
1168
1037
  //#endregion
1169
1038
  //#region src/responses-agent-language-model/call-options-to-responses-args.ts
1170
1039
  /**
1171
- * Converts AI SDK LanguageModelV2CallOptions to Databricks Responses API body parameters.
1040
+ * Converts AI SDK LanguageModelV3CallOptions to Databricks Responses API body parameters.
1172
1041
  *
1173
1042
  * Inspired by the getArgs method in:
1174
1043
  * https://github.com/vercel/ai/blob/main/packages/openai/src/responses/openai-responses-language-model.ts#L118
@@ -1180,28 +1049,28 @@ function callOptionsToResponsesArgs(options) {
1180
1049
  const warnings = [];
1181
1050
  const databricksOptions = options.providerOptions?.databricks;
1182
1051
  if (options.topK != null) warnings.push({
1183
- type: "unsupported-setting",
1184
- setting: "topK",
1052
+ type: "unsupported",
1053
+ feature: "topK",
1185
1054
  details: "topK is not supported by the Databricks Responses API"
1186
1055
  });
1187
1056
  if (options.presencePenalty != null) warnings.push({
1188
- type: "unsupported-setting",
1189
- setting: "presencePenalty",
1057
+ type: "unsupported",
1058
+ feature: "presencePenalty",
1190
1059
  details: "presencePenalty is not supported by the Databricks Responses API"
1191
1060
  });
1192
1061
  if (options.frequencyPenalty != null) warnings.push({
1193
- type: "unsupported-setting",
1194
- setting: "frequencyPenalty",
1062
+ type: "unsupported",
1063
+ feature: "frequencyPenalty",
1195
1064
  details: "frequencyPenalty is not supported by the Databricks Responses API"
1196
1065
  });
1197
1066
  if (options.seed != null) warnings.push({
1198
- type: "unsupported-setting",
1199
- setting: "seed",
1067
+ type: "unsupported",
1068
+ feature: "seed",
1200
1069
  details: "seed is not supported by the Databricks Responses API"
1201
1070
  });
1202
1071
  if (options.stopSequences != null && options.stopSequences.length > 0) warnings.push({
1203
- type: "unsupported-setting",
1204
- setting: "stopSequences",
1072
+ type: "unsupported",
1073
+ feature: "stopSequences",
1205
1074
  details: "stopSequences is not supported by the Databricks Responses API"
1206
1075
  });
1207
1076
  const args = {};
@@ -1237,16 +1106,27 @@ function callOptionsToResponsesArgs(options) {
1237
1106
  //#endregion
1238
1107
  //#region src/responses-agent-language-model/responses-agent-language-model.ts
1239
1108
  function mapResponsesFinishReason({ finishReason, hasToolCalls }) {
1109
+ let unified;
1240
1110
  switch (finishReason) {
1241
1111
  case void 0:
1242
- case null: return hasToolCalls ? "tool-calls" : "stop";
1243
- case "max_output_tokens": return "length";
1244
- case "content_filter": return "content-filter";
1245
- default: return hasToolCalls ? "tool-calls" : "other";
1112
+ case null:
1113
+ unified = hasToolCalls ? "tool-calls" : "stop";
1114
+ break;
1115
+ case "max_output_tokens":
1116
+ unified = "length";
1117
+ break;
1118
+ case "content_filter":
1119
+ unified = "content-filter";
1120
+ break;
1121
+ default: unified = hasToolCalls ? "tool-calls" : "other";
1246
1122
  }
1123
+ return {
1124
+ raw: finishReason ?? void 0,
1125
+ unified
1126
+ };
1247
1127
  }
1248
1128
  var DatabricksResponsesAgentLanguageModel = class {
1249
- specificationVersion = "v2";
1129
+ specificationVersion = "v3";
1250
1130
  modelId;
1251
1131
  config;
1252
1132
  constructor(modelId, config) {
@@ -1258,7 +1138,7 @@ var DatabricksResponsesAgentLanguageModel = class {
1258
1138
  }
1259
1139
  supportedUrls = {};
1260
1140
  async doGenerate(options) {
1261
- const { warnings,...networkArgs } = await this.getArgs({
1141
+ const { warnings, ...networkArgs } = await this.getArgs({
1262
1142
  config: this.config,
1263
1143
  options,
1264
1144
  stream: false,
@@ -1282,15 +1162,23 @@ var DatabricksResponsesAgentLanguageModel = class {
1282
1162
  hasToolCalls
1283
1163
  }),
1284
1164
  usage: {
1285
- inputTokens: response.usage?.input_tokens ?? 0,
1286
- outputTokens: response.usage?.output_tokens ?? 0,
1287
- totalTokens: response.usage?.total_tokens ?? 0
1165
+ inputTokens: {
1166
+ total: response.usage?.input_tokens ?? 0,
1167
+ noCache: 0,
1168
+ cacheRead: 0,
1169
+ cacheWrite: 0
1170
+ },
1171
+ outputTokens: {
1172
+ total: response.usage?.output_tokens ?? 0,
1173
+ text: 0,
1174
+ reasoning: 0
1175
+ }
1288
1176
  },
1289
1177
  warnings
1290
1178
  };
1291
1179
  }
1292
1180
  async doStream(options) {
1293
- const { warnings,...networkArgs } = await this.getArgs({
1181
+ const { warnings, ...networkArgs } = await this.getArgs({
1294
1182
  config: this.config,
1295
1183
  options,
1296
1184
  stream: true,
@@ -1306,13 +1194,26 @@ var DatabricksResponsesAgentLanguageModel = class {
1306
1194
  successfulResponseHandler: createEventSourceResponseHandler(looseResponseAgentChunkSchema),
1307
1195
  abortSignal: options.abortSignal
1308
1196
  });
1309
- let finishReason = "unknown";
1197
+ let finishReason = {
1198
+ raw: void 0,
1199
+ unified: "stop"
1200
+ };
1310
1201
  const usage = {
1311
- inputTokens: 0,
1312
- outputTokens: 0,
1313
- totalTokens: 0
1202
+ inputTokens: {
1203
+ total: 0,
1204
+ noCache: 0,
1205
+ cacheRead: 0,
1206
+ cacheWrite: 0
1207
+ },
1208
+ outputTokens: {
1209
+ total: 0,
1210
+ text: 0,
1211
+ reasoning: 0
1212
+ }
1314
1213
  };
1315
1214
  const allParts = [];
1215
+ const useRemoteToolCalling = this.config.useRemoteToolCalling ?? false;
1216
+ const toolNamesByCallId = /* @__PURE__ */ new Map();
1316
1217
  return {
1317
1218
  stream: response.pipeThrough(new TransformStream({
1318
1219
  start(controller) {
@@ -1327,7 +1228,10 @@ var DatabricksResponsesAgentLanguageModel = class {
1327
1228
  rawValue: chunk.rawValue
1328
1229
  });
1329
1230
  if (!chunk.success) {
1330
- finishReason = "error";
1231
+ finishReason = {
1232
+ raw: void 0,
1233
+ unified: "error"
1234
+ };
1331
1235
  controller.enqueue({
1332
1236
  type: "error",
1333
1237
  error: chunk.error
@@ -1340,12 +1244,15 @@ var DatabricksResponsesAgentLanguageModel = class {
1340
1244
  finishReason: chunk.value.response.incomplete_details?.reason,
1341
1245
  hasToolCalls
1342
1246
  });
1343
- usage.inputTokens = chunk.value.response.usage.input_tokens;
1344
- usage.outputTokens = chunk.value.response.usage.output_tokens;
1345
- usage.totalTokens = chunk.value.response.usage.total_tokens;
1247
+ usage.inputTokens.total = chunk.value.response.usage.input_tokens;
1248
+ usage.outputTokens.total = chunk.value.response.usage.output_tokens;
1346
1249
  return;
1347
1250
  }
1348
- const parts = convertResponsesAgentChunkToMessagePart(chunk.value);
1251
+ if (chunk.value.type === "response.output_item.done" && chunk.value.item.type === "function_call") toolNamesByCallId.set(chunk.value.item.call_id, chunk.value.item.name);
1252
+ const parts = convertResponsesAgentChunkToMessagePart(chunk.value, {
1253
+ useRemoteToolCalling,
1254
+ toolNamesByCallId
1255
+ });
1349
1256
  allParts.push(...parts);
1350
1257
  /**
1351
1258
  * Check if the last chunk was a tool result without a tool call
@@ -1360,19 +1267,35 @@ var DatabricksResponsesAgentLanguageModel = class {
1360
1267
  if (!matchingToolCallInParts && !matchingToolCallInStream) {
1361
1268
  const toolCallFromPreviousMessages = options.prompt.flatMap((message) => {
1362
1269
  if (typeof message.content === "string") return [];
1363
- return message.content;
1364
- }).find((p) => p.type === "tool-call" && p.toolCallId === part.toolCallId);
1270
+ return message.content.filter((p) => p.type === "tool-call");
1271
+ }).find((p) => p.toolCallId === part.toolCallId);
1365
1272
  if (!toolCallFromPreviousMessages) throw new Error("No matching tool call found in previous message");
1366
- if (toolCallFromPreviousMessages.type === "tool-call") controller.enqueue({
1367
- ...toolCallFromPreviousMessages,
1368
- input: JSON.stringify(toolCallFromPreviousMessages.input)
1273
+ controller.enqueue({
1274
+ type: "tool-call",
1275
+ toolCallId: toolCallFromPreviousMessages.toolCallId,
1276
+ toolName: toolCallFromPreviousMessages.toolName,
1277
+ input: JSON.stringify(toolCallFromPreviousMessages.input),
1278
+ providerExecuted: true,
1279
+ dynamic: true
1369
1280
  });
1370
1281
  }
1371
1282
  }
1372
1283
  if (shouldDedupeOutputItemDone(parts, allParts.slice(0, -parts.length))) return;
1373
- for (const part$1 of parts) controller.enqueue(part$1);
1284
+ for (const part of parts) controller.enqueue(part);
1374
1285
  },
1375
1286
  flush(controller) {
1287
+ if (!useRemoteToolCalling) {
1288
+ const toolCalls = allParts.filter((p) => p.type === "tool-call");
1289
+ const toolResults = allParts.filter((p) => p.type === "tool-result");
1290
+ for (const toolCall of toolCalls) {
1291
+ if (toolCall.providerMetadata?.databricks?.approvalRequestId != null) continue;
1292
+ if (!toolResults.some((r) => r.toolCallId === toolCall.toolCallId)) controller.enqueue({
1293
+ ...toolCall,
1294
+ providerExecuted: true,
1295
+ dynamic: true
1296
+ });
1297
+ }
1298
+ }
1376
1299
  controller.enqueue({
1377
1300
  type: "finish",
1378
1301
  finishReason,
@@ -1425,8 +1348,7 @@ function shouldDedupeOutputItemDone(incomingParts, previousParts) {
1425
1348
  * corresponds to a specific message and we should only compare against text streamed for that message.
1426
1349
  */
1427
1350
  const lastDoneIndex = previousParts.findLastIndex((part) => part.type === "text-delta" && part.providerMetadata?.databricks?.itemType === "response.output_item.done");
1428
- const partsAfterLastDone = previousParts.slice(lastDoneIndex + 1);
1429
- const { texts: reconstructuredTexts, current } = partsAfterLastDone.reduce((acc, part) => {
1351
+ const { texts: reconstructuredTexts, current } = previousParts.slice(lastDoneIndex + 1).reduce((acc, part) => {
1430
1352
  if (part.type === "text-delta") return {
1431
1353
  ...acc,
1432
1354
  current: acc.current + part.delta
@@ -1440,9 +1362,9 @@ function shouldDedupeOutputItemDone(incomingParts, previousParts) {
1440
1362
  texts: [],
1441
1363
  current: ""
1442
1364
  });
1443
- reconstructuredTexts.push(current);
1365
+ if (current.length > 0) reconstructuredTexts.push(current);
1444
1366
  if (reconstructuredTexts.length === 0) return false;
1445
- const allTextsFoundInOrder = reconstructuredTexts.reduce((acc, text) => {
1367
+ return reconstructuredTexts.reduce((acc, text) => {
1446
1368
  if (!acc.found) return acc;
1447
1369
  const index = doneTextDelta.delta.indexOf(text, acc.lastIndex);
1448
1370
  if (index === -1) return {
@@ -1456,8 +1378,7 @@ function shouldDedupeOutputItemDone(incomingParts, previousParts) {
1456
1378
  }, {
1457
1379
  found: true,
1458
1380
  lastIndex: 0
1459
- });
1460
- return allTextsFoundInOrder.found;
1381
+ }).found;
1461
1382
  }
1462
1383
 
1463
1384
  //#endregion
@@ -1591,12 +1512,12 @@ const convertFmapiChunkToMessagePart = (chunk, toolCallIdsByIndex) => {
1591
1512
  } else if (Array.isArray(choice.delta.content)) parts.push(...mapContentItemsToStreamParts(choice.delta.content, chunk.id));
1592
1513
  return parts;
1593
1514
  };
1594
- const convertFmapiResponseToMessagePart = (response) => {
1515
+ const convertFmapiResponseToMessagePart = (response, options = { useRemoteToolCalling: false }) => {
1595
1516
  const parts = [];
1596
1517
  if (response.choices.length === 0) return parts;
1597
1518
  const choice = response.choices[0];
1598
1519
  if (choice.message.tool_calls && choice.message.tool_calls.length > 0) {
1599
- for (const toolCall of choice.message.tool_calls) parts.push(convertToolCallToContent(toolCall));
1520
+ for (const toolCall of choice.message.tool_calls) parts.push(convertToolCallToContent(toolCall, options));
1600
1521
  if (typeof choice.message.content === "string" && choice.message.content) parts.push({
1601
1522
  type: "text",
1602
1523
  text: choice.message.content
@@ -1610,13 +1531,16 @@ const convertFmapiResponseToMessagePart = (response) => {
1610
1531
  else parts.push(...mapContentItemsToProviderContent(choice.message.content ?? []));
1611
1532
  return parts;
1612
1533
  };
1613
- const convertToolCallToContent = (toolCall) => {
1534
+ const convertToolCallToContent = (toolCall, options) => {
1614
1535
  return {
1615
1536
  type: "tool-call",
1616
1537
  toolCallId: toolCall.id,
1617
- toolName: DATABRICKS_TOOL_CALL_ID,
1538
+ toolName: toolCall.function.name,
1618
1539
  input: toolCall.function.arguments,
1619
- providerMetadata: { databricks: { toolName: toolCall.function.name } }
1540
+ ...options.useRemoteToolCalling && {
1541
+ dynamic: true,
1542
+ providerExecuted: true
1543
+ }
1620
1544
  };
1621
1545
  };
1622
1546
  const mapContentItemsToStreamParts = (items, id) => {
@@ -1630,14 +1554,13 @@ const mapContentItemsToStreamParts = (items, id) => {
1630
1554
  });
1631
1555
  break;
1632
1556
  case "image": break;
1633
- case "reasoning": {
1557
+ case "reasoning":
1634
1558
  for (const summary of item.summary.filter((s) => s.type === "summary_text")) parts.push({
1635
1559
  type: "reasoning-delta",
1636
1560
  id,
1637
1561
  delta: summary.text
1638
1562
  });
1639
1563
  break;
1640
- }
1641
1564
  }
1642
1565
  return parts;
1643
1566
  };
@@ -1651,13 +1574,12 @@ const mapContentItemsToProviderContent = (items) => {
1651
1574
  });
1652
1575
  break;
1653
1576
  case "image": break;
1654
- case "reasoning": {
1577
+ case "reasoning":
1655
1578
  for (const summary of item.summary.filter((s) => s.type === "summary_text")) parts.push({
1656
1579
  type: "reasoning",
1657
1580
  text: summary.text
1658
1581
  });
1659
1582
  break;
1660
- }
1661
1583
  }
1662
1584
  return parts;
1663
1585
  };
@@ -1793,31 +1715,45 @@ const convertToolResultOutputToContentValue = (output) => {
1793
1715
  };
1794
1716
  const ProviderOptionsSchema = z.object({ toolName: z.string().nullish() });
1795
1717
  const getToolNameFromPart = async (part) => {
1796
- const providerOptions = await parseProviderOptions({
1718
+ return (await parseProviderOptions({
1797
1719
  provider: "databricks",
1798
1720
  providerOptions: part.providerOptions,
1799
1721
  schema: ProviderOptionsSchema
1800
- });
1801
- return providerOptions?.toolName ?? part.toolName;
1722
+ }))?.toolName ?? part.toolName;
1802
1723
  };
1803
1724
 
1804
1725
  //#endregion
1805
1726
  //#region src/fmapi-language-model/fmapi-finish-reason.ts
1806
1727
  function mapFmapiFinishReason(finishReason) {
1807
1728
  switch (finishReason) {
1808
- case "stop": return "stop";
1809
- case "length": return "length";
1810
- case "content_filter": return "content-filter";
1729
+ case "stop": return {
1730
+ raw: finishReason,
1731
+ unified: "stop"
1732
+ };
1733
+ case "length": return {
1734
+ raw: finishReason,
1735
+ unified: "length"
1736
+ };
1737
+ case "content_filter": return {
1738
+ raw: finishReason,
1739
+ unified: "content-filter"
1740
+ };
1811
1741
  case "function_call":
1812
- case "tool_calls": return "tool-calls";
1813
- default: return "other";
1742
+ case "tool_calls": return {
1743
+ raw: finishReason,
1744
+ unified: "tool-calls"
1745
+ };
1746
+ default: return {
1747
+ raw: finishReason ?? void 0,
1748
+ unified: "other"
1749
+ };
1814
1750
  }
1815
1751
  }
1816
1752
 
1817
1753
  //#endregion
1818
1754
  //#region src/fmapi-language-model/call-options-to-fmapi-args.ts
1819
1755
  /**
1820
- * Converts AI SDK LanguageModelV2CallOptions to Databricks FMAPI body parameters.
1756
+ * Converts AI SDK LanguageModelV3CallOptions to Databricks FMAPI body parameters.
1821
1757
  *
1822
1758
  * Inspired by the getArgs method in:
1823
1759
  * https://github.com/vercel/ai/blob/main/packages/openai/src/chat/openai-chat-language-model.ts#L71
@@ -1829,18 +1765,18 @@ function callOptionsToFmapiArgs(options) {
1829
1765
  const warnings = [];
1830
1766
  const databricksOptions = options.providerOptions?.databricks;
1831
1767
  if (options.presencePenalty != null) warnings.push({
1832
- type: "unsupported-setting",
1833
- setting: "presencePenalty",
1768
+ type: "unsupported",
1769
+ feature: "presencePenalty",
1834
1770
  details: "presencePenalty is not supported by the Databricks FMAPI"
1835
1771
  });
1836
1772
  if (options.frequencyPenalty != null) warnings.push({
1837
- type: "unsupported-setting",
1838
- setting: "frequencyPenalty",
1773
+ type: "unsupported",
1774
+ feature: "frequencyPenalty",
1839
1775
  details: "frequencyPenalty is not supported by the Databricks FMAPI"
1840
1776
  });
1841
1777
  if (options.seed != null) warnings.push({
1842
- type: "unsupported-setting",
1843
- setting: "seed",
1778
+ type: "unsupported",
1779
+ feature: "seed",
1844
1780
  details: "seed is not supported by the Databricks FMAPI"
1845
1781
  });
1846
1782
  const args = {};
@@ -1880,7 +1816,7 @@ function callOptionsToFmapiArgs(options) {
1880
1816
  //#endregion
1881
1817
  //#region src/fmapi-language-model/fmapi-language-model.ts
1882
1818
  var DatabricksFmapiLanguageModel = class {
1883
- specificationVersion = "v2";
1819
+ specificationVersion = "v3";
1884
1820
  modelId;
1885
1821
  config;
1886
1822
  constructor(modelId, config) {
@@ -1892,7 +1828,7 @@ var DatabricksFmapiLanguageModel = class {
1892
1828
  }
1893
1829
  supportedUrls = {};
1894
1830
  async doGenerate(options) {
1895
- const { warnings,...networkArgs } = await this.getArgs({
1831
+ const { warnings, ...networkArgs } = await this.getArgs({
1896
1832
  config: this.config,
1897
1833
  options,
1898
1834
  stream: false,
@@ -1910,18 +1846,26 @@ var DatabricksFmapiLanguageModel = class {
1910
1846
  const choice = response.choices[0];
1911
1847
  const finishReason = mapFmapiFinishReason(choice?.finish_reason);
1912
1848
  return {
1913
- content: convertFmapiResponseToMessagePart(response),
1849
+ content: convertFmapiResponseToMessagePart(response, { useRemoteToolCalling: this.config.useRemoteToolCalling ?? false }),
1914
1850
  finishReason,
1915
1851
  usage: {
1916
- inputTokens: response.usage?.prompt_tokens ?? 0,
1917
- outputTokens: response.usage?.completion_tokens ?? 0,
1918
- totalTokens: response.usage?.total_tokens ?? 0
1852
+ inputTokens: {
1853
+ total: response.usage?.prompt_tokens ?? 0,
1854
+ noCache: 0,
1855
+ cacheRead: 0,
1856
+ cacheWrite: 0
1857
+ },
1858
+ outputTokens: {
1859
+ total: response.usage?.completion_tokens ?? 0,
1860
+ text: 0,
1861
+ reasoning: 0
1862
+ }
1919
1863
  },
1920
1864
  warnings
1921
1865
  };
1922
1866
  }
1923
1867
  async doStream(options) {
1924
- const { warnings,...networkArgs } = await this.getArgs({
1868
+ const { warnings, ...networkArgs } = await this.getArgs({
1925
1869
  config: this.config,
1926
1870
  options,
1927
1871
  stream: true,
@@ -1937,15 +1881,27 @@ var DatabricksFmapiLanguageModel = class {
1937
1881
  successfulResponseHandler: createEventSourceResponseHandler(fmapiChunkSchema),
1938
1882
  abortSignal: options.abortSignal
1939
1883
  });
1940
- let finishReason = "unknown";
1884
+ let finishReason = {
1885
+ raw: void 0,
1886
+ unified: "other"
1887
+ };
1941
1888
  let usage = {
1942
- inputTokens: 0,
1943
- outputTokens: 0,
1944
- totalTokens: 0
1889
+ inputTokens: {
1890
+ total: 0,
1891
+ noCache: 0,
1892
+ cacheRead: 0,
1893
+ cacheWrite: 0
1894
+ },
1895
+ outputTokens: {
1896
+ total: 0,
1897
+ text: 0,
1898
+ reasoning: 0
1899
+ }
1945
1900
  };
1946
- const toolCallIdsByIndex = new Map();
1947
- const toolCallNamesById = new Map();
1948
- const toolCallInputsById = new Map();
1901
+ const toolCallIdsByIndex = /* @__PURE__ */ new Map();
1902
+ const toolCallNamesById = /* @__PURE__ */ new Map();
1903
+ const toolCallInputsById = /* @__PURE__ */ new Map();
1904
+ const useRemoteToolCalling = this.config.useRemoteToolCalling ?? false;
1949
1905
  return {
1950
1906
  stream: response.pipeThrough(new TransformStream({
1951
1907
  start(controller) {
@@ -1960,7 +1916,10 @@ var DatabricksFmapiLanguageModel = class {
1960
1916
  rawValue: chunk.rawValue
1961
1917
  });
1962
1918
  if (!chunk.success) {
1963
- finishReason = "error";
1919
+ finishReason = {
1920
+ raw: void 0,
1921
+ unified: "error"
1922
+ };
1964
1923
  controller.enqueue({
1965
1924
  type: "error",
1966
1925
  error: chunk.error
@@ -1970,9 +1929,17 @@ var DatabricksFmapiLanguageModel = class {
1970
1929
  const choice = chunk.value.choices[0];
1971
1930
  finishReason = mapFmapiFinishReason(choice?.finish_reason);
1972
1931
  if (chunk.value.usage) usage = {
1973
- inputTokens: chunk.value.usage.prompt_tokens ?? 0,
1974
- outputTokens: chunk.value.usage.completion_tokens ?? 0,
1975
- totalTokens: chunk.value.usage.total_tokens ?? 0
1932
+ inputTokens: {
1933
+ total: chunk.value.usage.prompt_tokens ?? 0,
1934
+ noCache: 0,
1935
+ cacheRead: 0,
1936
+ cacheWrite: 0
1937
+ },
1938
+ outputTokens: {
1939
+ total: chunk.value.usage.completion_tokens ?? 0,
1940
+ text: 0,
1941
+ reasoning: 0
1942
+ }
1976
1943
  };
1977
1944
  const parts = convertFmapiChunkToMessagePart(chunk.value, toolCallIdsByIndex);
1978
1945
  for (const part of parts) {
@@ -1997,9 +1964,12 @@ var DatabricksFmapiLanguageModel = class {
1997
1964
  controller.enqueue({
1998
1965
  type: "tool-call",
1999
1966
  toolCallId,
2000
- toolName: DATABRICKS_TOOL_CALL_ID,
1967
+ toolName,
2001
1968
  input: inputText,
2002
- providerMetadata: { databricks: { toolName } }
1969
+ ...useRemoteToolCalling && {
1970
+ dynamic: true,
1971
+ providerExecuted: true
1972
+ }
2003
1973
  });
2004
1974
  }
2005
1975
  }
@@ -2039,7 +2009,7 @@ var DatabricksFmapiLanguageModel = class {
2039
2009
  * Convert AI SDK tool to OpenAI format
2040
2010
  */
2041
2011
  function convertToolToOpenAIFormat(tool) {
2042
- if (tool.type === "provider-defined" || tool.name === DATABRICKS_TOOL_CALL_ID) return void 0;
2012
+ if (tool.type === "provider") return;
2043
2013
  return {
2044
2014
  type: "function",
2045
2015
  function: {
@@ -2084,13 +2054,15 @@ const createDatabricksProvider = (settings) => {
2084
2054
  url: formatUrl,
2085
2055
  headers: getHeaders,
2086
2056
  fetch,
2087
- provider
2057
+ provider,
2058
+ useRemoteToolCalling: settings.useRemoteToolCalling
2088
2059
  });
2089
2060
  const createFmapi = (modelId) => new DatabricksFmapiLanguageModel(modelId, {
2090
2061
  url: formatUrl,
2091
2062
  headers: getHeaders,
2092
2063
  fetch,
2093
- provider
2064
+ provider,
2065
+ useRemoteToolCalling: settings.useRemoteToolCalling
2094
2066
  });
2095
2067
  const notImplemented = (name) => {
2096
2068
  return () => {
@@ -2098,15 +2070,17 @@ const createDatabricksProvider = (settings) => {
2098
2070
  };
2099
2071
  };
2100
2072
  return {
2073
+ specificationVersion: "v3",
2101
2074
  responses: createResponsesAgent,
2102
2075
  chatCompletions: createFmapi,
2103
2076
  chatAgent: createChatAgent,
2104
2077
  imageModel: notImplemented("ImageModel"),
2105
2078
  textEmbeddingModel: notImplemented("TextEmbeddingModel"),
2079
+ embeddingModel: notImplemented("EmbeddingModel"),
2106
2080
  languageModel: notImplemented("LanguageModel")
2107
2081
  };
2108
2082
  };
2109
2083
 
2110
2084
  //#endregion
2111
- export { DATABRICKS_TOOL_CALL_ID, DATABRICKS_TOOL_DEFINITION, MCP_APPROVAL_REQUEST_TYPE, MCP_APPROVAL_RESPONSE_TYPE, MCP_APPROVAL_STATUS_KEY, createApprovalStatusOutput, createDatabricksProvider, extractApprovalStatus, extractApprovalStatusFromToolResult, extractDatabricksMetadata, getMcpApprovalState, isApprovalStatusOutput, isMcpApprovalRequest, isMcpApprovalResponse };
2112
- //# sourceMappingURL=index.js.map
2085
+ export { createDatabricksProvider };
2086
+ //# sourceMappingURL=index.mjs.map