@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.
- package/README.md +58 -64
- package/dist/index.cjs +363 -426
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -145
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +58 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/{index.js → index.mjs} +335 -361
- package/dist/index.mjs.map +1 -0
- package/package.json +7 -7
- package/dist/index.d.ts +0 -181
- 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),
|
|
@@ -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:
|
|
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:
|
|
694
|
+
toolName: item.name,
|
|
811
695
|
input: item.arguments,
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
859
|
-
result:
|
|
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:
|
|
772
|
+
toolName: output.name,
|
|
884
773
|
input: output.arguments,
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
925
|
-
result:
|
|
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
|
-
|
|
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:
|
|
1016
|
-
id,
|
|
907
|
+
type: "mcp_approval_request",
|
|
908
|
+
id: approvalRequestId,
|
|
1017
909
|
name: toolName,
|
|
1018
|
-
arguments:
|
|
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":
|
|
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
|
-
|
|
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
|
|
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:
|
|
1020
|
+
toolChoice: convertResponsesToolChoice(toolChoice)
|
|
1152
1021
|
};
|
|
1153
1022
|
}
|
|
1154
1023
|
function convertResponsesToolChoice(toolChoice) {
|
|
1155
|
-
if (!toolChoice) return
|
|
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
|
|
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
|
|
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
|
|
1184
|
-
|
|
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
|
|
1189
|
-
|
|
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
|
|
1194
|
-
|
|
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
|
|
1199
|
-
|
|
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
|
|
1204
|
-
|
|
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:
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
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 = "
|
|
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
|
|
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:
|
|
1286
|
-
|
|
1287
|
-
|
|
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
|
|
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 =
|
|
1197
|
+
let finishReason = {
|
|
1198
|
+
raw: void 0,
|
|
1199
|
+
unified: "stop"
|
|
1200
|
+
};
|
|
1310
1201
|
const usage = {
|
|
1311
|
-
inputTokens:
|
|
1312
|
-
|
|
1313
|
-
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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:
|
|
1538
|
+
toolName: toolCall.function.name,
|
|
1618
1539
|
input: toolCall.function.arguments,
|
|
1619
|
-
|
|
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
|
-
|
|
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
|
|
1809
|
-
|
|
1810
|
-
|
|
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
|
|
1813
|
-
|
|
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
|
|
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
|
|
1833
|
-
|
|
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
|
|
1838
|
-
|
|
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
|
|
1843
|
-
|
|
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 = "
|
|
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
|
|
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:
|
|
1917
|
-
|
|
1918
|
-
|
|
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
|
|
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 =
|
|
1884
|
+
let finishReason = {
|
|
1885
|
+
raw: void 0,
|
|
1886
|
+
unified: "other"
|
|
1887
|
+
};
|
|
1941
1888
|
let usage = {
|
|
1942
|
-
inputTokens:
|
|
1943
|
-
|
|
1944
|
-
|
|
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 =
|
|
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:
|
|
1974
|
-
|
|
1975
|
-
|
|
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
|
|
1967
|
+
toolName,
|
|
2001
1968
|
input: inputText,
|
|
2002
|
-
|
|
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
|
|
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 {
|
|
2112
|
-
//# sourceMappingURL=index.
|
|
2085
|
+
export { createDatabricksProvider };
|
|
2086
|
+
//# sourceMappingURL=index.mjs.map
|