@databricks/ai-sdk-provider 0.2.2 → 0.3.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.
- package/README.md +59 -49
- package/dist/index.cjs +457 -244
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -33
- package/dist/index.d.cts.map +1 -1
- package/dist/{index.d.ts → index.d.mts} +23 -34
- package/dist/index.d.mts.map +1 -0
- package/dist/{index.js → index.mjs} +418 -179
- package/dist/index.mjs.map +1 -0
- package/package.json +7 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -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:
|
|
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:
|
|
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
|
|
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
|
-
|
|
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 = "
|
|
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
|
-
...
|
|
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:
|
|
344
|
+
finishReason: {
|
|
345
|
+
raw: void 0,
|
|
346
|
+
unified: "stop"
|
|
347
|
+
},
|
|
370
348
|
usage: {
|
|
371
|
-
inputTokens:
|
|
372
|
-
|
|
373
|
-
|
|
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 =
|
|
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 =
|
|
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:
|
|
425
|
-
|
|
426
|
-
|
|
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:
|
|
440
|
+
messages: convertLanguageModelV3PromptToChatAgentResponse(options.prompt)
|
|
441
441
|
},
|
|
442
442
|
url: config.url({ path: "/completions" }),
|
|
443
443
|
headers: combineHeaders(config.headers(), options.headers),
|
|
@@ -668,7 +668,6 @@ function isMcpApprovalResponse(metadata) {
|
|
|
668
668
|
*/
|
|
669
669
|
function extractDatabricksMetadata(part) {
|
|
670
670
|
if ("callProviderMetadata" in part && part.callProviderMetadata?.databricks) return part.callProviderMetadata.databricks;
|
|
671
|
-
return void 0;
|
|
672
671
|
}
|
|
673
672
|
/**
|
|
674
673
|
* Extract the approval status boolean from an output object.
|
|
@@ -683,7 +682,6 @@ function extractDatabricksMetadata(part) {
|
|
|
683
682
|
*/
|
|
684
683
|
function extractApprovalStatus(output) {
|
|
685
684
|
if (isApprovalStatusOutput(output)) return output[MCP_APPROVAL_STATUS_KEY];
|
|
686
|
-
return void 0;
|
|
687
685
|
}
|
|
688
686
|
/**
|
|
689
687
|
* Extract approval status from a tool result's output value.
|
|
@@ -697,7 +695,6 @@ function extractApprovalStatusFromToolResult(output) {
|
|
|
697
695
|
const value = output.value[MCP_APPROVAL_STATUS_KEY];
|
|
698
696
|
if (typeof value === "boolean") return value;
|
|
699
697
|
}
|
|
700
|
-
return void 0;
|
|
701
698
|
}
|
|
702
699
|
/**
|
|
703
700
|
* Create an approval status output object.
|
|
@@ -733,7 +730,7 @@ function getMcpApprovalState(output) {
|
|
|
733
730
|
|
|
734
731
|
//#endregion
|
|
735
732
|
//#region src/responses-agent-language-model/responses-convert-to-message-parts.ts
|
|
736
|
-
const convertResponsesAgentChunkToMessagePart = (chunk) => {
|
|
733
|
+
const convertResponsesAgentChunkToMessagePart = (chunk, options = { useRemoteToolCalling: false }) => {
|
|
737
734
|
const parts = [];
|
|
738
735
|
if ("error" in chunk) {
|
|
739
736
|
parts.push({
|
|
@@ -763,12 +760,12 @@ const convertResponsesAgentChunkToMessagePart = (chunk) => {
|
|
|
763
760
|
parts.push({
|
|
764
761
|
type: "tool-result",
|
|
765
762
|
toolCallId: chunk.call_id,
|
|
766
|
-
result: chunk.output,
|
|
767
|
-
toolName:
|
|
763
|
+
result: chunk.output != null ? chunk.output : {},
|
|
764
|
+
toolName: options.toolNamesByCallId?.get(chunk.call_id) ?? "unknown"
|
|
768
765
|
});
|
|
769
766
|
break;
|
|
770
767
|
case "response.output_item.done":
|
|
771
|
-
parts.push(...convertOutputItemDone(chunk.item));
|
|
768
|
+
parts.push(...convertOutputItemDone(chunk.item, options));
|
|
772
769
|
break;
|
|
773
770
|
case "response.output_text.annotation.added":
|
|
774
771
|
parts.push({
|
|
@@ -789,7 +786,7 @@ const convertResponsesAgentChunkToMessagePart = (chunk) => {
|
|
|
789
786
|
}
|
|
790
787
|
return parts;
|
|
791
788
|
};
|
|
792
|
-
const convertOutputItemDone = (item) => {
|
|
789
|
+
const convertOutputItemDone = (item, options) => {
|
|
793
790
|
switch (item.type) {
|
|
794
791
|
case "message": {
|
|
795
792
|
const firstContent = item.content[0];
|
|
@@ -807,18 +804,19 @@ const convertOutputItemDone = (item) => {
|
|
|
807
804
|
case "function_call": return [{
|
|
808
805
|
type: "tool-call",
|
|
809
806
|
toolCallId: item.call_id,
|
|
810
|
-
toolName:
|
|
807
|
+
toolName: item.name,
|
|
811
808
|
input: item.arguments,
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
}
|
|
809
|
+
...options.useRemoteToolCalling && {
|
|
810
|
+
dynamic: true,
|
|
811
|
+
providerExecuted: true
|
|
812
|
+
},
|
|
813
|
+
providerMetadata: { databricks: { itemId: item.id } }
|
|
816
814
|
}];
|
|
817
815
|
case "function_call_output": return [{
|
|
818
816
|
type: "tool-result",
|
|
819
817
|
toolCallId: item.call_id,
|
|
820
|
-
result: item.output,
|
|
821
|
-
toolName:
|
|
818
|
+
result: item.output != null ? item.output : {},
|
|
819
|
+
toolName: options.toolNamesByCallId?.get(item.call_id) ?? "unknown"
|
|
822
820
|
}];
|
|
823
821
|
case "reasoning": {
|
|
824
822
|
const firstSummary = item.summary[0];
|
|
@@ -843,11 +841,14 @@ const convertOutputItemDone = (item) => {
|
|
|
843
841
|
case "mcp_approval_request": return [{
|
|
844
842
|
type: "tool-call",
|
|
845
843
|
toolCallId: item.id,
|
|
846
|
-
toolName:
|
|
844
|
+
toolName: item.name,
|
|
847
845
|
input: item.arguments,
|
|
846
|
+
...options.useRemoteToolCalling && {
|
|
847
|
+
dynamic: true,
|
|
848
|
+
providerExecuted: true
|
|
849
|
+
},
|
|
848
850
|
providerMetadata: { databricks: {
|
|
849
851
|
type: MCP_APPROVAL_REQUEST_TYPE,
|
|
850
|
-
toolName: item.name,
|
|
851
852
|
itemId: item.id,
|
|
852
853
|
serverLabel: item.server_label
|
|
853
854
|
} }
|
|
@@ -855,7 +856,7 @@ const convertOutputItemDone = (item) => {
|
|
|
855
856
|
case "mcp_approval_response": return [{
|
|
856
857
|
type: "tool-result",
|
|
857
858
|
toolCallId: item.approval_request_id,
|
|
858
|
-
toolName:
|
|
859
|
+
toolName: options.toolNamesByCallId?.get(item.approval_request_id) ?? "mcp_approval",
|
|
859
860
|
result: createApprovalStatusOutput(item.approve),
|
|
860
861
|
providerMetadata: { databricks: {
|
|
861
862
|
type: MCP_APPROVAL_RESPONSE_TYPE,
|
|
@@ -865,27 +866,30 @@ const convertOutputItemDone = (item) => {
|
|
|
865
866
|
default: return [];
|
|
866
867
|
}
|
|
867
868
|
};
|
|
868
|
-
const convertResponsesAgentResponseToMessagePart = (response) => {
|
|
869
|
+
const convertResponsesAgentResponseToMessagePart = (response, options = { useRemoteToolCalling: false }) => {
|
|
869
870
|
const parts = [];
|
|
871
|
+
const toolNamesByCallId = /* @__PURE__ */ new Map();
|
|
872
|
+
for (const output of response.output) if (output.type === "function_call") toolNamesByCallId.set(output.call_id, output.name);
|
|
873
|
+
else if (output.type === "mcp_approval_request") toolNamesByCallId.set(output.id, output.name);
|
|
870
874
|
for (const output of response.output) switch (output.type) {
|
|
871
|
-
case "message":
|
|
875
|
+
case "message":
|
|
872
876
|
for (const content of output.content) if (content.type === "output_text") parts.push({
|
|
873
877
|
type: "text",
|
|
874
878
|
text: content.text,
|
|
875
879
|
providerMetadata: { databricks: { itemId: output.id } }
|
|
876
880
|
});
|
|
877
881
|
break;
|
|
878
|
-
}
|
|
879
882
|
case "function_call":
|
|
880
883
|
parts.push({
|
|
881
884
|
type: "tool-call",
|
|
882
885
|
toolCallId: output.call_id,
|
|
883
|
-
toolName:
|
|
886
|
+
toolName: output.name,
|
|
884
887
|
input: output.arguments,
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
}
|
|
888
|
+
...options.useRemoteToolCalling && {
|
|
889
|
+
dynamic: true,
|
|
890
|
+
providerExecuted: true
|
|
891
|
+
},
|
|
892
|
+
providerMetadata: { databricks: { itemId: output.id } }
|
|
889
893
|
});
|
|
890
894
|
break;
|
|
891
895
|
case "reasoning":
|
|
@@ -900,18 +904,17 @@ const convertResponsesAgentResponseToMessagePart = (response) => {
|
|
|
900
904
|
type: "tool-result",
|
|
901
905
|
result: output.output,
|
|
902
906
|
toolCallId: output.call_id,
|
|
903
|
-
toolName:
|
|
907
|
+
toolName: toolNamesByCallId.get(output.call_id) ?? "unknown"
|
|
904
908
|
});
|
|
905
909
|
break;
|
|
906
910
|
case "mcp_approval_request":
|
|
907
911
|
parts.push({
|
|
908
912
|
type: "tool-call",
|
|
909
913
|
toolCallId: output.id,
|
|
910
|
-
toolName:
|
|
914
|
+
toolName: output.name,
|
|
911
915
|
input: output.arguments,
|
|
912
916
|
providerMetadata: { databricks: {
|
|
913
917
|
type: MCP_APPROVAL_REQUEST_TYPE,
|
|
914
|
-
toolName: output.name,
|
|
915
918
|
itemId: output.id,
|
|
916
919
|
serverLabel: output.server_label
|
|
917
920
|
} }
|
|
@@ -921,7 +924,7 @@ const convertResponsesAgentResponseToMessagePart = (response) => {
|
|
|
921
924
|
parts.push({
|
|
922
925
|
type: "tool-result",
|
|
923
926
|
toolCallId: output.approval_request_id,
|
|
924
|
-
toolName:
|
|
927
|
+
toolName: toolNamesByCallId.get(output.approval_request_id) ?? "mcp_approval",
|
|
925
928
|
result: createApprovalStatusOutput(output.approve),
|
|
926
929
|
providerMetadata: { databricks: {
|
|
927
930
|
type: MCP_APPROVAL_RESPONSE_TYPE,
|
|
@@ -944,7 +947,7 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
|
|
|
944
947
|
return reduction;
|
|
945
948
|
}, {});
|
|
946
949
|
for (const { role, content } of prompt) switch (role) {
|
|
947
|
-
case "system":
|
|
950
|
+
case "system":
|
|
948
951
|
switch (systemMessageMode) {
|
|
949
952
|
case "system":
|
|
950
953
|
input.push({
|
|
@@ -970,7 +973,6 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
|
|
|
970
973
|
}
|
|
971
974
|
}
|
|
972
975
|
break;
|
|
973
|
-
}
|
|
974
976
|
case "user":
|
|
975
977
|
input.push({
|
|
976
978
|
role: "user",
|
|
@@ -994,7 +996,7 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
|
|
|
994
996
|
});
|
|
995
997
|
const itemId = providerOptions?.itemId ?? void 0;
|
|
996
998
|
switch (part.type) {
|
|
997
|
-
case "text":
|
|
999
|
+
case "text":
|
|
998
1000
|
input.push({
|
|
999
1001
|
role: "assistant",
|
|
1000
1002
|
content: [{
|
|
@@ -1004,7 +1006,6 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
|
|
|
1004
1006
|
id: itemId
|
|
1005
1007
|
});
|
|
1006
1008
|
break;
|
|
1007
|
-
}
|
|
1008
1009
|
case "tool-call": {
|
|
1009
1010
|
const toolName = providerOptions?.toolName ?? part.toolName;
|
|
1010
1011
|
if (providerOptions?.type === MCP_APPROVAL_REQUEST_TYPE) {
|
|
@@ -1055,7 +1056,7 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
|
|
|
1055
1056
|
});
|
|
1056
1057
|
break;
|
|
1057
1058
|
}
|
|
1058
|
-
case "tool-result":
|
|
1059
|
+
case "tool-result":
|
|
1059
1060
|
if (providerOptions?.type === MCP_APPROVAL_RESPONSE_TYPE) {
|
|
1060
1061
|
const approvalRequestId = providerOptions?.approvalRequestId ?? part.toolCallId;
|
|
1061
1062
|
const approve = providerOptions?.approve ?? false;
|
|
@@ -1075,8 +1076,7 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
|
|
|
1075
1076
|
output: convertToolResultOutputToString(part.output)
|
|
1076
1077
|
});
|
|
1077
1078
|
break;
|
|
1078
|
-
|
|
1079
|
-
case "reasoning": {
|
|
1079
|
+
case "reasoning":
|
|
1080
1080
|
if (!itemId) break;
|
|
1081
1081
|
input.push({
|
|
1082
1082
|
type: "reasoning",
|
|
@@ -1087,7 +1087,6 @@ async function convertToResponsesInput({ prompt, systemMessageMode }) {
|
|
|
1087
1087
|
id: itemId
|
|
1088
1088
|
});
|
|
1089
1089
|
break;
|
|
1090
|
-
}
|
|
1091
1090
|
}
|
|
1092
1091
|
}
|
|
1093
1092
|
break;
|
|
@@ -1115,7 +1114,10 @@ const convertToolResultOutputToString = (output) => {
|
|
|
1115
1114
|
switch (output.type) {
|
|
1116
1115
|
case "text":
|
|
1117
1116
|
case "error-text": return output.value;
|
|
1118
|
-
|
|
1117
|
+
case "execution-denied": return output.reason ?? "Execution denied";
|
|
1118
|
+
case "json":
|
|
1119
|
+
case "error-json":
|
|
1120
|
+
case "content": return JSON.stringify(output.value);
|
|
1119
1121
|
}
|
|
1120
1122
|
};
|
|
1121
1123
|
|
|
@@ -1133,7 +1135,7 @@ function prepareResponsesTools({ tools, toolChoice }) {
|
|
|
1133
1135
|
};
|
|
1134
1136
|
const responsesTools = [];
|
|
1135
1137
|
for (const tool of tools) {
|
|
1136
|
-
if (tool.type === "provider
|
|
1138
|
+
if (tool.type === "provider") continue;
|
|
1137
1139
|
responsesTools.push({
|
|
1138
1140
|
type: "function",
|
|
1139
1141
|
name: tool.name,
|
|
@@ -1145,14 +1147,13 @@ function prepareResponsesTools({ tools, toolChoice }) {
|
|
|
1145
1147
|
tools: void 0,
|
|
1146
1148
|
toolChoice: void 0
|
|
1147
1149
|
};
|
|
1148
|
-
const convertedToolChoice = convertResponsesToolChoice(toolChoice);
|
|
1149
1150
|
return {
|
|
1150
1151
|
tools: responsesTools,
|
|
1151
|
-
toolChoice:
|
|
1152
|
+
toolChoice: convertResponsesToolChoice(toolChoice)
|
|
1152
1153
|
};
|
|
1153
1154
|
}
|
|
1154
1155
|
function convertResponsesToolChoice(toolChoice) {
|
|
1155
|
-
if (!toolChoice) return
|
|
1156
|
+
if (!toolChoice) return;
|
|
1156
1157
|
switch (toolChoice.type) {
|
|
1157
1158
|
case "auto": return "auto";
|
|
1158
1159
|
case "none": return "none";
|
|
@@ -1161,23 +1162,103 @@ function convertResponsesToolChoice(toolChoice) {
|
|
|
1161
1162
|
type: "function",
|
|
1162
1163
|
name: toolChoice.toolName
|
|
1163
1164
|
};
|
|
1164
|
-
default: return
|
|
1165
|
+
default: return;
|
|
1165
1166
|
}
|
|
1166
1167
|
}
|
|
1167
1168
|
|
|
1169
|
+
//#endregion
|
|
1170
|
+
//#region src/responses-agent-language-model/call-options-to-responses-args.ts
|
|
1171
|
+
/**
|
|
1172
|
+
* Converts AI SDK LanguageModelV3CallOptions to Databricks Responses API body parameters.
|
|
1173
|
+
*
|
|
1174
|
+
* Inspired by the getArgs method in:
|
|
1175
|
+
* https://github.com/vercel/ai/blob/main/packages/openai/src/responses/openai-responses-language-model.ts#L118
|
|
1176
|
+
*
|
|
1177
|
+
* Complies with the API described in:
|
|
1178
|
+
* https://docs.databricks.com/aws/en/machine-learning/foundation-model-apis/api-reference#responses-api-request
|
|
1179
|
+
*/
|
|
1180
|
+
function callOptionsToResponsesArgs(options) {
|
|
1181
|
+
const warnings = [];
|
|
1182
|
+
const databricksOptions = options.providerOptions?.databricks;
|
|
1183
|
+
if (options.topK != null) warnings.push({
|
|
1184
|
+
type: "unsupported",
|
|
1185
|
+
feature: "topK",
|
|
1186
|
+
details: "topK is not supported by the Databricks Responses API"
|
|
1187
|
+
});
|
|
1188
|
+
if (options.presencePenalty != null) warnings.push({
|
|
1189
|
+
type: "unsupported",
|
|
1190
|
+
feature: "presencePenalty",
|
|
1191
|
+
details: "presencePenalty is not supported by the Databricks Responses API"
|
|
1192
|
+
});
|
|
1193
|
+
if (options.frequencyPenalty != null) warnings.push({
|
|
1194
|
+
type: "unsupported",
|
|
1195
|
+
feature: "frequencyPenalty",
|
|
1196
|
+
details: "frequencyPenalty is not supported by the Databricks Responses API"
|
|
1197
|
+
});
|
|
1198
|
+
if (options.seed != null) warnings.push({
|
|
1199
|
+
type: "unsupported",
|
|
1200
|
+
feature: "seed",
|
|
1201
|
+
details: "seed is not supported by the Databricks Responses API"
|
|
1202
|
+
});
|
|
1203
|
+
if (options.stopSequences != null && options.stopSequences.length > 0) warnings.push({
|
|
1204
|
+
type: "unsupported",
|
|
1205
|
+
feature: "stopSequences",
|
|
1206
|
+
details: "stopSequences is not supported by the Databricks Responses API"
|
|
1207
|
+
});
|
|
1208
|
+
const args = {};
|
|
1209
|
+
if (options.maxOutputTokens != null) args.max_output_tokens = options.maxOutputTokens;
|
|
1210
|
+
if (options.temperature != null) args.temperature = options.temperature;
|
|
1211
|
+
if (options.topP != null) args.top_p = options.topP;
|
|
1212
|
+
if (options.responseFormat != null) switch (options.responseFormat.type) {
|
|
1213
|
+
case "text":
|
|
1214
|
+
args.text = { format: { type: "text" } };
|
|
1215
|
+
break;
|
|
1216
|
+
case "json":
|
|
1217
|
+
if (options.responseFormat.schema != null) args.text = { format: {
|
|
1218
|
+
type: "json_schema",
|
|
1219
|
+
json_schema: {
|
|
1220
|
+
name: options.responseFormat.name ?? "response",
|
|
1221
|
+
description: options.responseFormat.description,
|
|
1222
|
+
schema: options.responseFormat.schema,
|
|
1223
|
+
strict: true
|
|
1224
|
+
}
|
|
1225
|
+
} };
|
|
1226
|
+
else args.text = { format: { type: "json_object" } };
|
|
1227
|
+
break;
|
|
1228
|
+
}
|
|
1229
|
+
if (databricksOptions?.parallelToolCalls != null) args.parallel_tool_calls = databricksOptions.parallelToolCalls;
|
|
1230
|
+
if (databricksOptions?.metadata != null) args.metadata = databricksOptions.metadata;
|
|
1231
|
+
if (databricksOptions?.reasoning != null) args.reasoning = databricksOptions.reasoning;
|
|
1232
|
+
return {
|
|
1233
|
+
args,
|
|
1234
|
+
warnings
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1168
1238
|
//#endregion
|
|
1169
1239
|
//#region src/responses-agent-language-model/responses-agent-language-model.ts
|
|
1170
1240
|
function mapResponsesFinishReason({ finishReason, hasToolCalls }) {
|
|
1241
|
+
let unified;
|
|
1171
1242
|
switch (finishReason) {
|
|
1172
1243
|
case void 0:
|
|
1173
|
-
case null:
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1244
|
+
case null:
|
|
1245
|
+
unified = hasToolCalls ? "tool-calls" : "stop";
|
|
1246
|
+
break;
|
|
1247
|
+
case "max_output_tokens":
|
|
1248
|
+
unified = "length";
|
|
1249
|
+
break;
|
|
1250
|
+
case "content_filter":
|
|
1251
|
+
unified = "content-filter";
|
|
1252
|
+
break;
|
|
1253
|
+
default: unified = hasToolCalls ? "tool-calls" : "other";
|
|
1177
1254
|
}
|
|
1255
|
+
return {
|
|
1256
|
+
raw: finishReason ?? void 0,
|
|
1257
|
+
unified
|
|
1258
|
+
};
|
|
1178
1259
|
}
|
|
1179
1260
|
var DatabricksResponsesAgentLanguageModel = class {
|
|
1180
|
-
specificationVersion = "
|
|
1261
|
+
specificationVersion = "v3";
|
|
1181
1262
|
modelId;
|
|
1182
1263
|
config;
|
|
1183
1264
|
constructor(modelId, config) {
|
|
@@ -1189,7 +1270,7 @@ var DatabricksResponsesAgentLanguageModel = class {
|
|
|
1189
1270
|
}
|
|
1190
1271
|
supportedUrls = {};
|
|
1191
1272
|
async doGenerate(options) {
|
|
1192
|
-
const networkArgs = await this.getArgs({
|
|
1273
|
+
const { warnings, ...networkArgs } = await this.getArgs({
|
|
1193
1274
|
config: this.config,
|
|
1194
1275
|
options,
|
|
1195
1276
|
stream: false,
|
|
@@ -1213,15 +1294,23 @@ var DatabricksResponsesAgentLanguageModel = class {
|
|
|
1213
1294
|
hasToolCalls
|
|
1214
1295
|
}),
|
|
1215
1296
|
usage: {
|
|
1216
|
-
inputTokens:
|
|
1217
|
-
|
|
1218
|
-
|
|
1297
|
+
inputTokens: {
|
|
1298
|
+
total: response.usage?.input_tokens ?? 0,
|
|
1299
|
+
noCache: 0,
|
|
1300
|
+
cacheRead: 0,
|
|
1301
|
+
cacheWrite: 0
|
|
1302
|
+
},
|
|
1303
|
+
outputTokens: {
|
|
1304
|
+
total: response.usage?.output_tokens ?? 0,
|
|
1305
|
+
text: 0,
|
|
1306
|
+
reasoning: 0
|
|
1307
|
+
}
|
|
1219
1308
|
},
|
|
1220
|
-
warnings
|
|
1309
|
+
warnings
|
|
1221
1310
|
};
|
|
1222
1311
|
}
|
|
1223
1312
|
async doStream(options) {
|
|
1224
|
-
const networkArgs = await this.getArgs({
|
|
1313
|
+
const { warnings, ...networkArgs } = await this.getArgs({
|
|
1225
1314
|
config: this.config,
|
|
1226
1315
|
options,
|
|
1227
1316
|
stream: true,
|
|
@@ -1237,19 +1326,32 @@ var DatabricksResponsesAgentLanguageModel = class {
|
|
|
1237
1326
|
successfulResponseHandler: createEventSourceResponseHandler(looseResponseAgentChunkSchema),
|
|
1238
1327
|
abortSignal: options.abortSignal
|
|
1239
1328
|
});
|
|
1240
|
-
let finishReason =
|
|
1329
|
+
let finishReason = {
|
|
1330
|
+
raw: void 0,
|
|
1331
|
+
unified: "stop"
|
|
1332
|
+
};
|
|
1241
1333
|
const usage = {
|
|
1242
|
-
inputTokens:
|
|
1243
|
-
|
|
1244
|
-
|
|
1334
|
+
inputTokens: {
|
|
1335
|
+
total: 0,
|
|
1336
|
+
noCache: 0,
|
|
1337
|
+
cacheRead: 0,
|
|
1338
|
+
cacheWrite: 0
|
|
1339
|
+
},
|
|
1340
|
+
outputTokens: {
|
|
1341
|
+
total: 0,
|
|
1342
|
+
text: 0,
|
|
1343
|
+
reasoning: 0
|
|
1344
|
+
}
|
|
1245
1345
|
};
|
|
1246
1346
|
const allParts = [];
|
|
1347
|
+
const useRemoteToolCalling = this.config.useRemoteToolCalling ?? false;
|
|
1348
|
+
const toolNamesByCallId = /* @__PURE__ */ new Map();
|
|
1247
1349
|
return {
|
|
1248
1350
|
stream: response.pipeThrough(new TransformStream({
|
|
1249
1351
|
start(controller) {
|
|
1250
1352
|
controller.enqueue({
|
|
1251
1353
|
type: "stream-start",
|
|
1252
|
-
warnings
|
|
1354
|
+
warnings
|
|
1253
1355
|
});
|
|
1254
1356
|
},
|
|
1255
1357
|
transform(chunk, controller) {
|
|
@@ -1258,7 +1360,10 @@ var DatabricksResponsesAgentLanguageModel = class {
|
|
|
1258
1360
|
rawValue: chunk.rawValue
|
|
1259
1361
|
});
|
|
1260
1362
|
if (!chunk.success) {
|
|
1261
|
-
finishReason =
|
|
1363
|
+
finishReason = {
|
|
1364
|
+
raw: void 0,
|
|
1365
|
+
unified: "error"
|
|
1366
|
+
};
|
|
1262
1367
|
controller.enqueue({
|
|
1263
1368
|
type: "error",
|
|
1264
1369
|
error: chunk.error
|
|
@@ -1271,12 +1376,15 @@ var DatabricksResponsesAgentLanguageModel = class {
|
|
|
1271
1376
|
finishReason: chunk.value.response.incomplete_details?.reason,
|
|
1272
1377
|
hasToolCalls
|
|
1273
1378
|
});
|
|
1274
|
-
usage.inputTokens = chunk.value.response.usage.input_tokens;
|
|
1275
|
-
usage.outputTokens = chunk.value.response.usage.output_tokens;
|
|
1276
|
-
usage.totalTokens = chunk.value.response.usage.total_tokens;
|
|
1379
|
+
usage.inputTokens.total = chunk.value.response.usage.input_tokens;
|
|
1380
|
+
usage.outputTokens.total = chunk.value.response.usage.output_tokens;
|
|
1277
1381
|
return;
|
|
1278
1382
|
}
|
|
1279
|
-
|
|
1383
|
+
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);
|
|
1384
|
+
const parts = convertResponsesAgentChunkToMessagePart(chunk.value, {
|
|
1385
|
+
useRemoteToolCalling,
|
|
1386
|
+
toolNamesByCallId
|
|
1387
|
+
});
|
|
1280
1388
|
allParts.push(...parts);
|
|
1281
1389
|
/**
|
|
1282
1390
|
* Check if the last chunk was a tool result without a tool call
|
|
@@ -1291,19 +1399,33 @@ var DatabricksResponsesAgentLanguageModel = class {
|
|
|
1291
1399
|
if (!matchingToolCallInParts && !matchingToolCallInStream) {
|
|
1292
1400
|
const toolCallFromPreviousMessages = options.prompt.flatMap((message) => {
|
|
1293
1401
|
if (typeof message.content === "string") return [];
|
|
1294
|
-
return message.content;
|
|
1295
|
-
}).find((p) => p.
|
|
1402
|
+
return message.content.filter((p) => p.type === "tool-call");
|
|
1403
|
+
}).find((p) => p.toolCallId === part.toolCallId);
|
|
1296
1404
|
if (!toolCallFromPreviousMessages) throw new Error("No matching tool call found in previous message");
|
|
1297
|
-
|
|
1298
|
-
|
|
1405
|
+
controller.enqueue({
|
|
1406
|
+
type: "tool-call",
|
|
1407
|
+
toolCallId: toolCallFromPreviousMessages.toolCallId,
|
|
1408
|
+
toolName: toolCallFromPreviousMessages.toolName,
|
|
1299
1409
|
input: JSON.stringify(toolCallFromPreviousMessages.input)
|
|
1300
1410
|
});
|
|
1301
1411
|
}
|
|
1302
1412
|
}
|
|
1303
1413
|
if (shouldDedupeOutputItemDone(parts, allParts.slice(0, -parts.length))) return;
|
|
1304
|
-
for (const part
|
|
1414
|
+
for (const part of parts) controller.enqueue(part);
|
|
1305
1415
|
},
|
|
1306
1416
|
flush(controller) {
|
|
1417
|
+
if (!useRemoteToolCalling) {
|
|
1418
|
+
const toolCalls = allParts.filter((p) => p.type === "tool-call");
|
|
1419
|
+
const toolResults = allParts.filter((p) => p.type === "tool-result");
|
|
1420
|
+
for (const toolCall of toolCalls) {
|
|
1421
|
+
if (toolCall.providerMetadata?.databricks?.type === MCP_APPROVAL_REQUEST_TYPE) continue;
|
|
1422
|
+
if (!toolResults.some((r) => r.toolCallId === toolCall.toolCallId)) controller.enqueue({
|
|
1423
|
+
...toolCall,
|
|
1424
|
+
providerExecuted: true,
|
|
1425
|
+
dynamic: true
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1307
1429
|
controller.enqueue({
|
|
1308
1430
|
type: "finish",
|
|
1309
1431
|
finishReason,
|
|
@@ -1324,6 +1446,7 @@ var DatabricksResponsesAgentLanguageModel = class {
|
|
|
1324
1446
|
tools: options.tools,
|
|
1325
1447
|
toolChoice: options.toolChoice
|
|
1326
1448
|
});
|
|
1449
|
+
const { args: callArgs, warnings } = callOptionsToResponsesArgs(options);
|
|
1327
1450
|
return {
|
|
1328
1451
|
url: config.url({ path: "/responses" }),
|
|
1329
1452
|
headers: combineHeaders(config.headers(), options.headers),
|
|
@@ -1332,8 +1455,10 @@ var DatabricksResponsesAgentLanguageModel = class {
|
|
|
1332
1455
|
input,
|
|
1333
1456
|
stream,
|
|
1334
1457
|
...tools ? { tools } : {},
|
|
1335
|
-
...toolChoice && tools ? { tool_choice: toolChoice } : {}
|
|
1458
|
+
...toolChoice && tools ? { tool_choice: toolChoice } : {},
|
|
1459
|
+
...callArgs
|
|
1336
1460
|
},
|
|
1461
|
+
warnings,
|
|
1337
1462
|
fetch: config.fetch
|
|
1338
1463
|
};
|
|
1339
1464
|
}
|
|
@@ -1353,8 +1478,7 @@ function shouldDedupeOutputItemDone(incomingParts, previousParts) {
|
|
|
1353
1478
|
* corresponds to a specific message and we should only compare against text streamed for that message.
|
|
1354
1479
|
*/
|
|
1355
1480
|
const lastDoneIndex = previousParts.findLastIndex((part) => part.type === "text-delta" && part.providerMetadata?.databricks?.itemType === "response.output_item.done");
|
|
1356
|
-
const
|
|
1357
|
-
const { texts: reconstructuredTexts, current } = partsAfterLastDone.reduce((acc, part) => {
|
|
1481
|
+
const { texts: reconstructuredTexts, current } = previousParts.slice(lastDoneIndex + 1).reduce((acc, part) => {
|
|
1358
1482
|
if (part.type === "text-delta") return {
|
|
1359
1483
|
...acc,
|
|
1360
1484
|
current: acc.current + part.delta
|
|
@@ -1368,9 +1492,9 @@ function shouldDedupeOutputItemDone(incomingParts, previousParts) {
|
|
|
1368
1492
|
texts: [],
|
|
1369
1493
|
current: ""
|
|
1370
1494
|
});
|
|
1371
|
-
reconstructuredTexts.push(current);
|
|
1495
|
+
if (current.length > 0) reconstructuredTexts.push(current);
|
|
1372
1496
|
if (reconstructuredTexts.length === 0) return false;
|
|
1373
|
-
|
|
1497
|
+
return reconstructuredTexts.reduce((acc, text) => {
|
|
1374
1498
|
if (!acc.found) return acc;
|
|
1375
1499
|
const index = doneTextDelta.delta.indexOf(text, acc.lastIndex);
|
|
1376
1500
|
if (index === -1) return {
|
|
@@ -1384,8 +1508,7 @@ function shouldDedupeOutputItemDone(incomingParts, previousParts) {
|
|
|
1384
1508
|
}, {
|
|
1385
1509
|
found: true,
|
|
1386
1510
|
lastIndex: 0
|
|
1387
|
-
});
|
|
1388
|
-
return allTextsFoundInOrder.found;
|
|
1511
|
+
}).found;
|
|
1389
1512
|
}
|
|
1390
1513
|
|
|
1391
1514
|
//#endregion
|
|
@@ -1519,12 +1642,12 @@ const convertFmapiChunkToMessagePart = (chunk, toolCallIdsByIndex) => {
|
|
|
1519
1642
|
} else if (Array.isArray(choice.delta.content)) parts.push(...mapContentItemsToStreamParts(choice.delta.content, chunk.id));
|
|
1520
1643
|
return parts;
|
|
1521
1644
|
};
|
|
1522
|
-
const convertFmapiResponseToMessagePart = (response) => {
|
|
1645
|
+
const convertFmapiResponseToMessagePart = (response, options = { useRemoteToolCalling: false }) => {
|
|
1523
1646
|
const parts = [];
|
|
1524
1647
|
if (response.choices.length === 0) return parts;
|
|
1525
1648
|
const choice = response.choices[0];
|
|
1526
1649
|
if (choice.message.tool_calls && choice.message.tool_calls.length > 0) {
|
|
1527
|
-
for (const toolCall of choice.message.tool_calls) parts.push(convertToolCallToContent(toolCall));
|
|
1650
|
+
for (const toolCall of choice.message.tool_calls) parts.push(convertToolCallToContent(toolCall, options));
|
|
1528
1651
|
if (typeof choice.message.content === "string" && choice.message.content) parts.push({
|
|
1529
1652
|
type: "text",
|
|
1530
1653
|
text: choice.message.content
|
|
@@ -1538,13 +1661,16 @@ const convertFmapiResponseToMessagePart = (response) => {
|
|
|
1538
1661
|
else parts.push(...mapContentItemsToProviderContent(choice.message.content ?? []));
|
|
1539
1662
|
return parts;
|
|
1540
1663
|
};
|
|
1541
|
-
const convertToolCallToContent = (toolCall) => {
|
|
1664
|
+
const convertToolCallToContent = (toolCall, options) => {
|
|
1542
1665
|
return {
|
|
1543
1666
|
type: "tool-call",
|
|
1544
1667
|
toolCallId: toolCall.id,
|
|
1545
|
-
toolName:
|
|
1668
|
+
toolName: toolCall.function.name,
|
|
1546
1669
|
input: toolCall.function.arguments,
|
|
1547
|
-
|
|
1670
|
+
...options.useRemoteToolCalling && {
|
|
1671
|
+
dynamic: true,
|
|
1672
|
+
providerExecuted: true
|
|
1673
|
+
}
|
|
1548
1674
|
};
|
|
1549
1675
|
};
|
|
1550
1676
|
const mapContentItemsToStreamParts = (items, id) => {
|
|
@@ -1558,14 +1684,13 @@ const mapContentItemsToStreamParts = (items, id) => {
|
|
|
1558
1684
|
});
|
|
1559
1685
|
break;
|
|
1560
1686
|
case "image": break;
|
|
1561
|
-
case "reasoning":
|
|
1687
|
+
case "reasoning":
|
|
1562
1688
|
for (const summary of item.summary.filter((s) => s.type === "summary_text")) parts.push({
|
|
1563
1689
|
type: "reasoning-delta",
|
|
1564
1690
|
id,
|
|
1565
1691
|
delta: summary.text
|
|
1566
1692
|
});
|
|
1567
1693
|
break;
|
|
1568
|
-
}
|
|
1569
1694
|
}
|
|
1570
1695
|
return parts;
|
|
1571
1696
|
};
|
|
@@ -1579,13 +1704,12 @@ const mapContentItemsToProviderContent = (items) => {
|
|
|
1579
1704
|
});
|
|
1580
1705
|
break;
|
|
1581
1706
|
case "image": break;
|
|
1582
|
-
case "reasoning":
|
|
1707
|
+
case "reasoning":
|
|
1583
1708
|
for (const summary of item.summary.filter((s) => s.type === "summary_text")) parts.push({
|
|
1584
1709
|
type: "reasoning",
|
|
1585
1710
|
text: summary.text
|
|
1586
1711
|
});
|
|
1587
1712
|
break;
|
|
1588
|
-
}
|
|
1589
1713
|
}
|
|
1590
1714
|
return parts;
|
|
1591
1715
|
};
|
|
@@ -1721,31 +1845,108 @@ const convertToolResultOutputToContentValue = (output) => {
|
|
|
1721
1845
|
};
|
|
1722
1846
|
const ProviderOptionsSchema = z.object({ toolName: z.string().nullish() });
|
|
1723
1847
|
const getToolNameFromPart = async (part) => {
|
|
1724
|
-
|
|
1848
|
+
return (await parseProviderOptions({
|
|
1725
1849
|
provider: "databricks",
|
|
1726
1850
|
providerOptions: part.providerOptions,
|
|
1727
1851
|
schema: ProviderOptionsSchema
|
|
1728
|
-
});
|
|
1729
|
-
return providerOptions?.toolName ?? part.toolName;
|
|
1852
|
+
}))?.toolName ?? part.toolName;
|
|
1730
1853
|
};
|
|
1731
1854
|
|
|
1732
1855
|
//#endregion
|
|
1733
1856
|
//#region src/fmapi-language-model/fmapi-finish-reason.ts
|
|
1734
1857
|
function mapFmapiFinishReason(finishReason) {
|
|
1735
1858
|
switch (finishReason) {
|
|
1736
|
-
case "stop": return
|
|
1737
|
-
|
|
1738
|
-
|
|
1859
|
+
case "stop": return {
|
|
1860
|
+
raw: finishReason,
|
|
1861
|
+
unified: "stop"
|
|
1862
|
+
};
|
|
1863
|
+
case "length": return {
|
|
1864
|
+
raw: finishReason,
|
|
1865
|
+
unified: "length"
|
|
1866
|
+
};
|
|
1867
|
+
case "content_filter": return {
|
|
1868
|
+
raw: finishReason,
|
|
1869
|
+
unified: "content-filter"
|
|
1870
|
+
};
|
|
1739
1871
|
case "function_call":
|
|
1740
|
-
case "tool_calls": return
|
|
1741
|
-
|
|
1872
|
+
case "tool_calls": return {
|
|
1873
|
+
raw: finishReason,
|
|
1874
|
+
unified: "tool-calls"
|
|
1875
|
+
};
|
|
1876
|
+
default: return {
|
|
1877
|
+
raw: finishReason ?? void 0,
|
|
1878
|
+
unified: "other"
|
|
1879
|
+
};
|
|
1742
1880
|
}
|
|
1743
1881
|
}
|
|
1744
1882
|
|
|
1883
|
+
//#endregion
|
|
1884
|
+
//#region src/fmapi-language-model/call-options-to-fmapi-args.ts
|
|
1885
|
+
/**
|
|
1886
|
+
* Converts AI SDK LanguageModelV3CallOptions to Databricks FMAPI body parameters.
|
|
1887
|
+
*
|
|
1888
|
+
* Inspired by the getArgs method in:
|
|
1889
|
+
* https://github.com/vercel/ai/blob/main/packages/openai/src/chat/openai-chat-language-model.ts#L71
|
|
1890
|
+
*
|
|
1891
|
+
* Complies with the API described in:
|
|
1892
|
+
* https://docs.databricks.com/aws/en/machine-learning/foundation-model-apis/api-reference#chat-request
|
|
1893
|
+
*/
|
|
1894
|
+
function callOptionsToFmapiArgs(options) {
|
|
1895
|
+
const warnings = [];
|
|
1896
|
+
const databricksOptions = options.providerOptions?.databricks;
|
|
1897
|
+
if (options.presencePenalty != null) warnings.push({
|
|
1898
|
+
type: "unsupported",
|
|
1899
|
+
feature: "presencePenalty",
|
|
1900
|
+
details: "presencePenalty is not supported by the Databricks FMAPI"
|
|
1901
|
+
});
|
|
1902
|
+
if (options.frequencyPenalty != null) warnings.push({
|
|
1903
|
+
type: "unsupported",
|
|
1904
|
+
feature: "frequencyPenalty",
|
|
1905
|
+
details: "frequencyPenalty is not supported by the Databricks FMAPI"
|
|
1906
|
+
});
|
|
1907
|
+
if (options.seed != null) warnings.push({
|
|
1908
|
+
type: "unsupported",
|
|
1909
|
+
feature: "seed",
|
|
1910
|
+
details: "seed is not supported by the Databricks FMAPI"
|
|
1911
|
+
});
|
|
1912
|
+
const args = {};
|
|
1913
|
+
if (options.maxOutputTokens != null) args.max_tokens = options.maxOutputTokens;
|
|
1914
|
+
if (options.temperature != null) args.temperature = options.temperature;
|
|
1915
|
+
if (options.topP != null) args.top_p = options.topP;
|
|
1916
|
+
if (options.topK != null) args.top_k = options.topK;
|
|
1917
|
+
if (options.stopSequences != null && options.stopSequences.length > 0) args.stop = options.stopSequences;
|
|
1918
|
+
if (options.responseFormat != null) switch (options.responseFormat.type) {
|
|
1919
|
+
case "text":
|
|
1920
|
+
args.response_format = { type: "text" };
|
|
1921
|
+
break;
|
|
1922
|
+
case "json":
|
|
1923
|
+
if (options.responseFormat.schema != null) args.response_format = {
|
|
1924
|
+
type: "json_schema",
|
|
1925
|
+
json_schema: {
|
|
1926
|
+
name: options.responseFormat.name ?? "response",
|
|
1927
|
+
description: options.responseFormat.description,
|
|
1928
|
+
schema: options.responseFormat.schema,
|
|
1929
|
+
strict: true
|
|
1930
|
+
}
|
|
1931
|
+
};
|
|
1932
|
+
else args.response_format = { type: "json_object" };
|
|
1933
|
+
break;
|
|
1934
|
+
}
|
|
1935
|
+
if (databricksOptions?.topK != null) args.top_k = databricksOptions.topK;
|
|
1936
|
+
if (databricksOptions?.n != null) args.n = databricksOptions.n;
|
|
1937
|
+
if (databricksOptions?.logprobs != null) args.logprobs = databricksOptions.logprobs;
|
|
1938
|
+
if (databricksOptions?.topLogprobs != null) args.top_logprobs = databricksOptions.topLogprobs;
|
|
1939
|
+
if (databricksOptions?.reasoningEffort != null) args.reasoning_effort = databricksOptions.reasoningEffort;
|
|
1940
|
+
return {
|
|
1941
|
+
args,
|
|
1942
|
+
warnings
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1745
1946
|
//#endregion
|
|
1746
1947
|
//#region src/fmapi-language-model/fmapi-language-model.ts
|
|
1747
1948
|
var DatabricksFmapiLanguageModel = class {
|
|
1748
|
-
specificationVersion = "
|
|
1949
|
+
specificationVersion = "v3";
|
|
1749
1950
|
modelId;
|
|
1750
1951
|
config;
|
|
1751
1952
|
constructor(modelId, config) {
|
|
@@ -1757,7 +1958,7 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1757
1958
|
}
|
|
1758
1959
|
supportedUrls = {};
|
|
1759
1960
|
async doGenerate(options) {
|
|
1760
|
-
const networkArgs = await this.getArgs({
|
|
1961
|
+
const { warnings, ...networkArgs } = await this.getArgs({
|
|
1761
1962
|
config: this.config,
|
|
1762
1963
|
options,
|
|
1763
1964
|
stream: false,
|
|
@@ -1775,18 +1976,26 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1775
1976
|
const choice = response.choices[0];
|
|
1776
1977
|
const finishReason = mapFmapiFinishReason(choice?.finish_reason);
|
|
1777
1978
|
return {
|
|
1778
|
-
content: convertFmapiResponseToMessagePart(response),
|
|
1979
|
+
content: convertFmapiResponseToMessagePart(response, { useRemoteToolCalling: this.config.useRemoteToolCalling ?? false }),
|
|
1779
1980
|
finishReason,
|
|
1780
1981
|
usage: {
|
|
1781
|
-
inputTokens:
|
|
1782
|
-
|
|
1783
|
-
|
|
1982
|
+
inputTokens: {
|
|
1983
|
+
total: response.usage?.prompt_tokens ?? 0,
|
|
1984
|
+
noCache: 0,
|
|
1985
|
+
cacheRead: 0,
|
|
1986
|
+
cacheWrite: 0
|
|
1987
|
+
},
|
|
1988
|
+
outputTokens: {
|
|
1989
|
+
total: response.usage?.completion_tokens ?? 0,
|
|
1990
|
+
text: 0,
|
|
1991
|
+
reasoning: 0
|
|
1992
|
+
}
|
|
1784
1993
|
},
|
|
1785
|
-
warnings
|
|
1994
|
+
warnings
|
|
1786
1995
|
};
|
|
1787
1996
|
}
|
|
1788
1997
|
async doStream(options) {
|
|
1789
|
-
const networkArgs = await this.getArgs({
|
|
1998
|
+
const { warnings, ...networkArgs } = await this.getArgs({
|
|
1790
1999
|
config: this.config,
|
|
1791
2000
|
options,
|
|
1792
2001
|
stream: true,
|
|
@@ -1802,21 +2011,33 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1802
2011
|
successfulResponseHandler: createEventSourceResponseHandler(fmapiChunkSchema),
|
|
1803
2012
|
abortSignal: options.abortSignal
|
|
1804
2013
|
});
|
|
1805
|
-
let finishReason =
|
|
2014
|
+
let finishReason = {
|
|
2015
|
+
raw: void 0,
|
|
2016
|
+
unified: "other"
|
|
2017
|
+
};
|
|
1806
2018
|
let usage = {
|
|
1807
|
-
inputTokens:
|
|
1808
|
-
|
|
1809
|
-
|
|
2019
|
+
inputTokens: {
|
|
2020
|
+
total: 0,
|
|
2021
|
+
noCache: 0,
|
|
2022
|
+
cacheRead: 0,
|
|
2023
|
+
cacheWrite: 0
|
|
2024
|
+
},
|
|
2025
|
+
outputTokens: {
|
|
2026
|
+
total: 0,
|
|
2027
|
+
text: 0,
|
|
2028
|
+
reasoning: 0
|
|
2029
|
+
}
|
|
1810
2030
|
};
|
|
1811
|
-
const toolCallIdsByIndex = new Map();
|
|
1812
|
-
const toolCallNamesById = new Map();
|
|
1813
|
-
const toolCallInputsById = new Map();
|
|
2031
|
+
const toolCallIdsByIndex = /* @__PURE__ */ new Map();
|
|
2032
|
+
const toolCallNamesById = /* @__PURE__ */ new Map();
|
|
2033
|
+
const toolCallInputsById = /* @__PURE__ */ new Map();
|
|
2034
|
+
const useRemoteToolCalling = this.config.useRemoteToolCalling ?? false;
|
|
1814
2035
|
return {
|
|
1815
2036
|
stream: response.pipeThrough(new TransformStream({
|
|
1816
2037
|
start(controller) {
|
|
1817
2038
|
controller.enqueue({
|
|
1818
2039
|
type: "stream-start",
|
|
1819
|
-
warnings
|
|
2040
|
+
warnings
|
|
1820
2041
|
});
|
|
1821
2042
|
},
|
|
1822
2043
|
transform(chunk, controller) {
|
|
@@ -1825,7 +2046,10 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1825
2046
|
rawValue: chunk.rawValue
|
|
1826
2047
|
});
|
|
1827
2048
|
if (!chunk.success) {
|
|
1828
|
-
finishReason =
|
|
2049
|
+
finishReason = {
|
|
2050
|
+
raw: void 0,
|
|
2051
|
+
unified: "error"
|
|
2052
|
+
};
|
|
1829
2053
|
controller.enqueue({
|
|
1830
2054
|
type: "error",
|
|
1831
2055
|
error: chunk.error
|
|
@@ -1835,9 +2059,17 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1835
2059
|
const choice = chunk.value.choices[0];
|
|
1836
2060
|
finishReason = mapFmapiFinishReason(choice?.finish_reason);
|
|
1837
2061
|
if (chunk.value.usage) usage = {
|
|
1838
|
-
inputTokens:
|
|
1839
|
-
|
|
1840
|
-
|
|
2062
|
+
inputTokens: {
|
|
2063
|
+
total: chunk.value.usage.prompt_tokens ?? 0,
|
|
2064
|
+
noCache: 0,
|
|
2065
|
+
cacheRead: 0,
|
|
2066
|
+
cacheWrite: 0
|
|
2067
|
+
},
|
|
2068
|
+
outputTokens: {
|
|
2069
|
+
total: chunk.value.usage.completion_tokens ?? 0,
|
|
2070
|
+
text: 0,
|
|
2071
|
+
reasoning: 0
|
|
2072
|
+
}
|
|
1841
2073
|
};
|
|
1842
2074
|
const parts = convertFmapiChunkToMessagePart(chunk.value, toolCallIdsByIndex);
|
|
1843
2075
|
for (const part of parts) {
|
|
@@ -1862,9 +2094,12 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1862
2094
|
controller.enqueue({
|
|
1863
2095
|
type: "tool-call",
|
|
1864
2096
|
toolCallId,
|
|
1865
|
-
toolName
|
|
2097
|
+
toolName,
|
|
1866
2098
|
input: inputText,
|
|
1867
|
-
|
|
2099
|
+
...useRemoteToolCalling && {
|
|
2100
|
+
dynamic: true,
|
|
2101
|
+
providerExecuted: true
|
|
2102
|
+
}
|
|
1868
2103
|
});
|
|
1869
2104
|
}
|
|
1870
2105
|
}
|
|
@@ -1883,6 +2118,7 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1883
2118
|
const tools = options.tools?.map((tool) => convertToolToOpenAIFormat(tool)).filter((tool) => tool !== void 0);
|
|
1884
2119
|
const toolChoice = options.toolChoice ? convertToolChoiceToOpenAIFormat(options.toolChoice) : void 0;
|
|
1885
2120
|
const { messages } = await convertPromptToFmapiMessages(options.prompt);
|
|
2121
|
+
const { args: callArgs, warnings } = callOptionsToFmapiArgs(options);
|
|
1886
2122
|
return {
|
|
1887
2123
|
url: config.url({ path: "/chat/completions" }),
|
|
1888
2124
|
headers: combineHeaders(config.headers(), options.headers),
|
|
@@ -1892,10 +2128,9 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1892
2128
|
model: modelId,
|
|
1893
2129
|
...tools && tools.length > 0 ? { tools } : {},
|
|
1894
2130
|
...toolChoice && tools && tools.length > 0 ? { tool_choice: toolChoice } : {},
|
|
1895
|
-
...
|
|
1896
|
-
...options.maxOutputTokens !== void 0 ? { max_tokens: options.maxOutputTokens } : {},
|
|
1897
|
-
...options.stopSequences && options.stopSequences.length > 0 ? { stop: options.stopSequences } : {}
|
|
2131
|
+
...callArgs
|
|
1898
2132
|
},
|
|
2133
|
+
warnings,
|
|
1899
2134
|
fetch: config.fetch
|
|
1900
2135
|
};
|
|
1901
2136
|
}
|
|
@@ -1904,7 +2139,7 @@ var DatabricksFmapiLanguageModel = class {
|
|
|
1904
2139
|
* Convert AI SDK tool to OpenAI format
|
|
1905
2140
|
*/
|
|
1906
2141
|
function convertToolToOpenAIFormat(tool) {
|
|
1907
|
-
if (tool.type === "provider
|
|
2142
|
+
if (tool.type === "provider") return;
|
|
1908
2143
|
return {
|
|
1909
2144
|
type: "function",
|
|
1910
2145
|
function: {
|
|
@@ -1949,13 +2184,15 @@ const createDatabricksProvider = (settings) => {
|
|
|
1949
2184
|
url: formatUrl,
|
|
1950
2185
|
headers: getHeaders,
|
|
1951
2186
|
fetch,
|
|
1952
|
-
provider
|
|
2187
|
+
provider,
|
|
2188
|
+
useRemoteToolCalling: settings.useRemoteToolCalling
|
|
1953
2189
|
});
|
|
1954
2190
|
const createFmapi = (modelId) => new DatabricksFmapiLanguageModel(modelId, {
|
|
1955
2191
|
url: formatUrl,
|
|
1956
2192
|
headers: getHeaders,
|
|
1957
2193
|
fetch,
|
|
1958
|
-
provider
|
|
2194
|
+
provider,
|
|
2195
|
+
useRemoteToolCalling: settings.useRemoteToolCalling
|
|
1959
2196
|
});
|
|
1960
2197
|
const notImplemented = (name) => {
|
|
1961
2198
|
return () => {
|
|
@@ -1963,15 +2200,17 @@ const createDatabricksProvider = (settings) => {
|
|
|
1963
2200
|
};
|
|
1964
2201
|
};
|
|
1965
2202
|
return {
|
|
2203
|
+
specificationVersion: "v3",
|
|
1966
2204
|
responses: createResponsesAgent,
|
|
1967
2205
|
chatCompletions: createFmapi,
|
|
1968
2206
|
chatAgent: createChatAgent,
|
|
1969
2207
|
imageModel: notImplemented("ImageModel"),
|
|
1970
2208
|
textEmbeddingModel: notImplemented("TextEmbeddingModel"),
|
|
2209
|
+
embeddingModel: notImplemented("EmbeddingModel"),
|
|
1971
2210
|
languageModel: notImplemented("LanguageModel")
|
|
1972
2211
|
};
|
|
1973
2212
|
};
|
|
1974
2213
|
|
|
1975
2214
|
//#endregion
|
|
1976
|
-
export {
|
|
1977
|
-
//# sourceMappingURL=index.
|
|
2215
|
+
export { MCP_APPROVAL_REQUEST_TYPE, MCP_APPROVAL_RESPONSE_TYPE, MCP_APPROVAL_STATUS_KEY, createApprovalStatusOutput, createDatabricksProvider, extractApprovalStatus, extractApprovalStatusFromToolResult, extractDatabricksMetadata, getMcpApprovalState, isApprovalStatusOutput, isMcpApprovalRequest, isMcpApprovalResponse };
|
|
2216
|
+
//# sourceMappingURL=index.mjs.map
|