@rama-adi/watsonx-unofficial-ai-provider
Version:
Unofficial Watsonx provider for the Vercel AI SDK
1,468 lines (1,445 loc) • 48.7 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// index.ts
var index_exports = {};
__export(index_exports, {
ChatModelLists: () => ChatModelLists,
CompletionModelLists: () => CompletionModelLists,
EmbedingModelLists: () => EmbedingModelLists,
FunctionCallingModelLists: () => FunctionCallingModelLists,
VisionModelLists: () => VisionModelLists,
WatsonxClusters: () => WatsonxClusters,
createWatsonx: () => createWatsonx,
watsonx: () => watsonx
});
module.exports = __toCommonJS(index_exports);
// src/provider.ts
var import_provider_utils6 = require("@ai-sdk/provider-utils");
// src/models/chat-models/watsonx-chat-model.ts
var import_provider2 = require("@ai-sdk/provider");
var import_provider_utils3 = require("@ai-sdk/provider-utils");
var import_v44 = require("zod/v4");
// src/models/chat-models/watsonx-chat-finish-reason.ts
function mapWatsonxChatFinishReason(reason) {
switch (reason) {
case "stop":
return "stop";
case "length":
return "length";
case "tool_calls":
return "tool-calls";
case "time_limit":
return "other";
case "cancelled":
return "other";
case "error":
return "error";
case null:
case void 0:
return "unknown";
default:
return "unknown";
}
}
// src/models/chat-models/convert-to-watsonx-chat-messages.ts
var import_provider = require("@ai-sdk/provider");
var import_provider_utils = require("@ai-sdk/provider-utils");
function convertToWatsonxChatMessages(prompt) {
const messages = [];
for (let i = 0; i < prompt.length; i++) {
const { role, content } = prompt[i];
const isLastMessage = i === prompt.length - 1;
switch (role) {
case "system": {
messages.push({ role: "system", content });
break;
}
case "user": {
messages.push({
role: "user",
content: content.map((part) => {
switch (part.type) {
case "text": {
return { type: "text", text: part.text };
}
case "file": {
throw new import_provider.UnsupportedFunctionalityError({
functionality: "File content in user messages is not supported by watsonx text chat"
});
}
}
})
});
break;
}
case "assistant": {
let text = "";
const toolCalls = [];
for (const part of content) {
switch (part.type) {
case "text": {
text += part.text;
break;
}
case "tool-call": {
toolCalls.push({
id: part.toolCallId,
type: "function",
function: {
name: part.toolName,
arguments: typeof part.input === "string" ? part.input : JSON.stringify(part.input)
}
});
break;
}
}
}
messages.push({
role: "assistant",
content: text,
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
});
break;
}
case "tool": {
for (const toolResponse of content) {
let resultContent = "";
switch (toolResponse.output.type) {
case "text":
case "error-text":
resultContent = toolResponse.output.value;
break;
case "json":
case "error-json":
resultContent = JSON.stringify(toolResponse.output.value);
break;
case "content":
resultContent = JSON.stringify(toolResponse.output.value);
break;
}
messages.push({
role: "tool",
content: resultContent,
tool_call_id: toolResponse.toolCallId
});
}
break;
}
default: {
throw new Error(`Unsupported role: ${role}`);
}
}
}
return messages;
}
// src/types/watsonx-response-schema.ts
var import_provider_utils2 = require("@ai-sdk/provider-utils");
var import_v4 = require("zod/v4");
var watsonxErrorResponseSchema = import_v4.z.object({
errors: import_v4.z.array(
import_v4.z.object({
code: import_v4.z.string(),
message: import_v4.z.string(),
more_info: import_v4.z.string()
})
),
trace: import_v4.z.string(),
status_code: import_v4.z.number()
});
var watsonxFailedResponseHandler = (0, import_provider_utils2.createJsonErrorResponseHandler)({
errorSchema: watsonxErrorResponseSchema,
errorToMessage: (data) => [
"watsonx API encountered error(s):",
data.errors.map((e) => "- " + e.message),
"Trace ID: " + data.trace
].join("\n")
});
// src/models/chat-models/watsonx-chat-model-settings.ts
var ChatModelLists = {
"ca-tor": [
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct"
],
"jp-tok": [
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"meta-llama/llama-guard-3-11b-vision",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503"
],
"eu-gb": [
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8"
],
"eu-de": [
"ibm/granite-3-3-8b-instruct",
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503"
],
"us-south": [
"ibm/granite-3-2-8b-instruct",
"ibm/granite-3-3-8b-instruct",
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct",
"meta-llama/llama-3-405b-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"meta-llama/llama-guard-3-11b-vision",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503",
"openai/gpt-oss-120b"
],
"au-syd": [
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct",
"meta-llama/llama-guard-3-11b-vision"
]
};
var VisionModelLists = {
"ca-tor": ["meta-llama/llama-3-2-11b-vision-instruct"],
"jp-tok": [
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"meta-llama/llama-guard-3-11b-vision",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503"
],
"eu-gb": [
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8"
],
"eu-de": [
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503"
],
"us-south": [
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"meta-llama/llama-guard-3-11b-vision",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503"
],
"au-syd": [
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct",
"meta-llama/llama-guard-3-11b-vision"
]
};
var FunctionCallingModelLists = {
"ca-tor": [
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct"
],
"jp-tok": [
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503"
],
"eu-gb": [
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8"
],
"eu-de": [
"ibm/granite-3-3-8b-instruct",
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503"
],
"us-south": [
"ibm/granite-3-2-8b-instruct",
"ibm/granite-3-3-8b-instruct",
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct",
"meta-llama/llama-3-3-70b-instruct",
"meta-llama/llama-3-405b-instruct",
"meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
"mistralai/mistral-medium-2505",
"mistralai/mistral-small-3-1-24b-instruct-2503",
"openai/gpt-oss-120b"
],
"au-syd": [
"ibm/granite-3-8b-instruct",
"meta-llama/llama-3-2-11b-vision-instruct",
"meta-llama/llama-3-2-90b-vision-instruct"
]
};
// src/models/chat-models/watsonx-chat-schema.ts
var import_v43 = require("zod/v4");
// src/types/watsonx-common-schema.ts
var import_v42 = require("zod/v4");
var WatsonxClusters = [
"ca-tor",
"jp-tok",
"eu-gb",
"eu-de",
"us-south",
"au-syd"
];
var systemDetailsSchema = import_v42.z.object({
warnings: import_v42.z.array(
import_v42.z.object({
message: import_v42.z.string().optional(),
id: import_v42.z.string().optional(),
more_info: import_v42.z.string().optional(),
additional_properties: import_v42.z.record(import_v42.z.string(), import_v42.z.unknown()).optional()
})
).optional()
}).optional();
var watsonxModerationsSchema = import_v42.z.object({
hap: import_v42.z.object({
input: import_v42.z.object({
enabled: import_v42.z.boolean(),
threshold: import_v42.z.number().min(0).max(1)
}),
output: import_v42.z.object({
enabled: import_v42.z.boolean(),
threshold: import_v42.z.number().min(0).max(1)
}),
mask: import_v42.z.object({
remove_entity_value: import_v42.z.boolean()
})
}),
pii: import_v42.z.object({
input: import_v42.z.object({
enabled: import_v42.z.boolean()
}),
output: import_v42.z.object({
enabled: import_v42.z.boolean()
}),
mask: import_v42.z.object({
remove_entity_value: import_v42.z.boolean()
})
})
}).optional();
// src/models/chat-models/watsonx-chat-schema.ts
var watsonxChatChunkSchema = import_v43.z.object({
id: import_v43.z.string().nullish(),
model_id: import_v43.z.string().nullish(),
created: import_v43.z.number().nullish(),
choices: import_v43.z.array(
import_v43.z.object({
delta: import_v43.z.object({
role: import_v43.z.enum(["assistant"]).optional(),
content: import_v43.z.string().nullish(),
tool_calls: import_v43.z.array(
import_v43.z.object({
index: import_v43.z.number(),
id: import_v43.z.string().optional(),
type: import_v43.z.literal("function").nullish(),
function: import_v43.z.object({
name: import_v43.z.string(),
arguments: import_v43.z.string()
})
})
).nullish()
}),
finish_reason: import_v43.z.enum([
"stop",
"length",
"tool_calls",
"time_limit",
"cancelled",
"error"
]).nullish(),
index: import_v43.z.number()
})
),
model_version: import_v43.z.string().nullish(),
created_at: import_v43.z.string().nullish(),
usage: import_v43.z.object({
prompt_tokens: import_v43.z.number(),
completion_tokens: import_v43.z.number(),
total_tokens: import_v43.z.number()
}).nullish(),
system: systemDetailsSchema
});
var watsonxChatResponseSchema = import_v43.z.object({
id: import_v43.z.string(),
model_id: import_v43.z.string(),
created: import_v43.z.number(),
choices: import_v43.z.array(
import_v43.z.object({
message: import_v43.z.object({
role: import_v43.z.literal("assistant"),
content: import_v43.z.string().nullish(),
refusal: import_v43.z.string().nullish(),
tool_calls: import_v43.z.array(
import_v43.z.object({
id: import_v43.z.string(),
type: import_v43.z.literal("function"),
function: import_v43.z.object({
name: import_v43.z.string(),
arguments: import_v43.z.string()
})
})
).nullish()
}),
index: import_v43.z.number(),
finish_reason: import_v43.z.enum([
"stop",
"length",
"tool_calls",
"time_limit",
"cancelled",
"error"
])
})
),
model_version: import_v43.z.string().nullish(),
created_at: import_v43.z.string(),
usage: import_v43.z.object({
prompt_tokens: import_v43.z.number(),
completion_tokens: import_v43.z.number(),
total_tokens: import_v43.z.number()
}),
system: systemDetailsSchema
});
// src/models/chat-models/watsonx-chat-model.ts
var WatsonxChatModel = class {
specificationVersion = "v2";
provider;
defaultObjectGenerationMode = "tool";
supportsImageUrls = false;
supportedUrls = {};
modelId;
settings;
config;
constructor(modelId, settings, config) {
this.modelId = modelId;
this.settings = settings;
this.config = config;
this.provider = config.provider;
}
sanityCheck(options) {
if (options.tools?.length && !Object.values(FunctionCallingModelLists).some(
(models) => models.includes(this.modelId)
)) {
throw new import_provider2.UnsupportedFunctionalityError({
functionality: "Tool calling",
message: `The model ${this.modelId} does not support tool calling`
});
}
}
getArgs({
prompt,
maxOutputTokens,
temperature,
topP,
topK,
frequencyPenalty,
presencePenalty,
stopSequences,
responseFormat,
seed,
tools,
toolChoice,
providerOptions
}) {
const warnings = [];
if (topK != null) {
warnings.push({
type: "unsupported-setting",
setting: "topK"
});
}
const requestedN = providerOptions?.watsonx?.n;
let nArg = void 0;
if (typeof requestedN === "number") {
if (requestedN !== 1) {
warnings.push({ type: "unsupported-setting", setting: "n" });
}
nArg = 1;
}
const topLogprobs = providerOptions?.watsonx?.topLogprobs;
const topLogprobsNum = typeof topLogprobs === "number" ? topLogprobs : void 0;
const requestedLogprobs = providerOptions?.watsonx?.logprobs;
const requestedLogprobsBool = typeof requestedLogprobs === "boolean" ? requestedLogprobs : void 0;
const requestedContext = providerOptions?.watsonx?.context;
const requestedContextStr = typeof requestedContext === "string" ? requestedContext : void 0;
const baseArgs = {
temperature,
model_id: this.modelId,
project_id: this.config.projectID,
frequency_penalty: frequencyPenalty,
// IBM watsonx prefers max_completion_tokens; max_tokens is deprecated
...maxOutputTokens != null ? { max_completion_tokens: maxOutputTokens } : {},
presence_penalty: presencePenalty,
top_p: topP,
seed,
messages: convertToWatsonxChatMessages(prompt),
time_limit: providerOptions?.watsonx?.timeLimit,
// OpenAPI optional parameters supported via providerOptions.watsonx
...typeof providerOptions?.watsonx?.maxCompletionTokens === "number" ? { max_completion_tokens: providerOptions.watsonx.maxCompletionTokens } : {},
...requestedLogprobsBool != null ? { logprobs: requestedLogprobsBool } : topLogprobsNum != null ? { logprobs: true } : {},
...topLogprobsNum != null ? { top_logprobs: topLogprobsNum } : {},
...providerOptions?.watsonx?.logitBias != null ? { logit_bias: providerOptions.watsonx.logitBias } : {},
...nArg != null ? { n: nArg } : {},
...providerOptions?.watsonx?.spaceId != null ? { space_id: providerOptions.watsonx.spaceId } : {},
...requestedContextStr != null ? { context: requestedContextStr } : {},
...stopSequences != null ? { stop: stopSequences } : {}
};
if (responseFormat?.type === "json") {
return {
args: {
...baseArgs,
response_format: { type: "json_object" }
},
warnings
};
}
if (tools && tools.length > 0) {
const mappedTools = tools.filter((tool) => tool.type === "function").map((tool) => ({
type: "function",
function: {
name: tool.name,
description: tool.description,
parameters: tool.inputSchema
}
}));
let tool_choice_option = void 0;
let tool_choice = void 0;
if (toolChoice?.type === "tool") {
tool_choice = {
type: "function",
function: {
name: toolChoice.toolName
}
};
} else if (toolChoice?.type === "auto") {
tool_choice_option = "auto";
} else if (toolChoice?.type === "required") {
if (mappedTools.length === 1) {
tool_choice = {
type: "function",
function: { name: mappedTools[0].function.name }
};
} else {
warnings.push({
type: "unsupported-setting",
setting: "toolChoice.required"
});
tool_choice_option = "auto";
}
}
return {
args: {
...baseArgs,
tools: mappedTools,
tool_choice_option,
tool_choice
},
warnings
};
}
return {
args: baseArgs,
warnings
};
}
async doGenerate(options) {
this.sanityCheck(options);
const { args, warnings } = this.getArgs(options);
const { value: response, responseHeaders } = await (0, import_provider_utils3.postJsonToApi)({
url: `${this.config.clusterURL}/text/chat?version=${this.config.version}`,
headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), options.headers),
body: args,
failedResponseHandler: watsonxFailedResponseHandler,
successfulResponseHandler: (0, import_provider_utils3.createJsonResponseHandler)(
watsonxChatResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const choice = response.choices[0];
if (!choice) {
throw new Error("No choice in response");
}
const content = [];
if (choice.message.content) {
content.push({
type: "text",
text: choice.message.content
});
}
if (choice.message.tool_calls) {
for (const toolCall of choice.message.tool_calls) {
content.push({
type: "tool-call",
toolCallId: toolCall.id,
toolName: toolCall.function.name,
input: toolCall.function.arguments
});
}
}
return {
content,
finishReason: mapWatsonxChatFinishReason(choice.finish_reason),
usage: {
inputTokens: response.usage.prompt_tokens,
outputTokens: response.usage.completion_tokens,
totalTokens: response.usage.total_tokens
},
warnings,
request: { body: args },
response: {
id: response.id,
modelId: response.model_id,
headers: responseHeaders
}
};
}
async doStream(options) {
this.sanityCheck(options);
const { args, warnings } = this.getArgs(options);
const url = `${this.config.clusterURL}/text/chat_stream?version=${this.config.version}`;
const body = { ...args };
const { value: response, responseHeaders } = await (0, import_provider_utils3.postJsonToApi)({
url,
headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), options.headers),
body,
failedResponseHandler: watsonxFailedResponseHandler,
successfulResponseHandler: (0, import_provider_utils3.createEventSourceResponseHandler)(
watsonxChatChunkSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const toolCalls = [];
let finishReason = "other";
const usage = {
inputTokens: Number.NaN,
outputTokens: Number.NaN,
totalTokens: Number.NaN
};
let chunkNumber = 0;
let textStarted = false;
let textId;
let watsonxResponseId;
let trimLeadingSpace = false;
return {
stream: response.pipeThrough(
new TransformStream({
transform(chunk, controller) {
if (!chunk.success) {
finishReason = "error";
controller.enqueue({ type: "error", error: chunk.error });
return;
}
chunkNumber++;
const value = chunk.value;
if (value.id) {
watsonxResponseId = value.id;
controller.enqueue({
type: "response-metadata",
id: value.id
});
}
if (value.model_id) {
controller.enqueue({
type: "response-metadata",
modelId: value.model_id
});
}
if (value.usage != null) {
usage.inputTokens = value.usage.prompt_tokens;
usage.outputTokens = value.usage.completion_tokens;
usage.totalTokens = value.usage.total_tokens;
}
const choice = value.choices[0];
if (!choice) {
return;
}
if (choice?.finish_reason != null) {
finishReason = mapWatsonxChatFinishReason(choice.finish_reason);
}
if (choice?.delta == null) {
return;
}
const delta = choice.delta;
const textContent = delta.content ?? "";
if (chunkNumber <= 2) {
const messages = convertToWatsonxChatMessages(options.prompt);
const lastMessage = messages[messages.length - 1];
if (lastMessage?.role === "assistant" && lastMessage.content && textContent === lastMessage.content.trimEnd()) {
if (textContent.length < lastMessage.content.length) {
trimLeadingSpace = true;
}
return;
}
}
if (textContent != null && textContent !== "") {
if (!textStarted) {
textId = watsonxResponseId || (0, import_provider_utils3.generateId)();
controller.enqueue({
type: "text-start",
id: textId
});
textStarted = true;
}
controller.enqueue({
type: "text-delta",
delta: trimLeadingSpace ? textContent.trimStart() : textContent,
id: textId || (0, import_provider_utils3.generateId)()
});
trimLeadingSpace = false;
}
if (delta.tool_calls != null) {
for (const toolCallDelta of delta.tool_calls) {
const index = toolCallDelta.index ?? toolCalls.length - 1;
if (toolCalls[index] == null) {
if (toolCallDelta.type !== "function") {
throw new import_provider2.InvalidResponseDataError({
data: toolCallDelta,
message: `Expected 'function' type.`
});
}
const toolCallId = toolCallDelta.id ?? (0, import_provider_utils3.generateId)();
if (toolCallDelta.function?.name == null) {
throw new import_provider2.InvalidResponseDataError({
data: toolCallDelta,
message: `Expected 'function.name' to be a string.`
});
}
toolCalls[index] = {
id: toolCallId,
type: "function",
function: {
name: toolCallDelta.function.name,
arguments: toolCallDelta.function.arguments ?? ""
},
inputStarted: false,
sent: false
};
const toolCall2 = toolCalls[index];
if (toolCall2 == null) {
throw new Error("Tool call is missing");
}
if (toolCall2.function?.name != null && toolCall2.function?.arguments != null && (0, import_provider_utils3.isParsableJson)(toolCall2.function.arguments)) {
toolCall2.inputStarted = true;
controller.enqueue({
type: "tool-input-start",
id: toolCall2.id,
toolName: toolCall2.function.name
});
controller.enqueue({
type: "tool-input-delta",
id: toolCall2.id,
delta: toolCall2.function.arguments
});
controller.enqueue({
type: "tool-input-end",
id: toolCall2.id
});
controller.enqueue({
type: "tool-call",
toolCallId: toolCall2.id,
toolName: toolCall2.function.name,
input: toolCall2.function.arguments
});
toolCall2.sent = true;
}
continue;
}
const toolCall = toolCalls[index];
if (toolCall == null) {
throw new Error("Tool call is missing");
}
if (!toolCall.inputStarted) {
toolCall.inputStarted = true;
controller.enqueue({
type: "tool-input-start",
id: toolCall.id,
toolName: toolCall.function.name
});
}
if (toolCallDelta.function?.arguments != null) {
toolCall.function.arguments += toolCallDelta.function?.arguments ?? "";
}
controller.enqueue({
type: "tool-input-delta",
id: toolCall.id,
delta: toolCallDelta.function.arguments ?? ""
});
if (toolCall.function?.name != null && toolCall.function?.arguments != null && (0, import_provider_utils3.isParsableJson)(toolCall.function.arguments)) {
controller.enqueue({
type: "tool-call",
toolCallId: toolCall.id ?? (0, import_provider_utils3.generateId)(),
toolName: toolCall.function.name,
input: toolCall.function.arguments
});
toolCall.sent = true;
}
}
}
},
flush(controller) {
if (finishReason === "tool-calls") {
for (const toolCall of toolCalls) {
if (toolCall && !toolCall.sent) {
controller.enqueue({
type: "tool-call",
toolCallId: toolCall.id ?? (0, import_provider_utils3.generateId)(),
toolName: toolCall.function.name,
// Coerce invalid arguments to an empty JSON object
input: (0, import_provider_utils3.isParsableJson)(toolCall.function.arguments) ? toolCall.function.arguments : "{}"
});
toolCall.sent = true;
}
}
}
if (textStarted) {
controller.enqueue({
type: "text-end",
id: textId || (0, import_provider_utils3.generateId)()
});
}
controller.enqueue({
type: "finish",
finishReason,
usage
});
}
})
),
warnings,
request: { body },
response: { headers: responseHeaders }
};
}
};
// src/models/embedding-models/watsonx-embedding-model.ts
var import_provider3 = require("@ai-sdk/provider");
var import_provider_utils4 = require("@ai-sdk/provider-utils");
var import_v45 = require("zod/v4");
var WatsonxEmbeddingModel = class {
config;
specificationVersion = "v2";
modelId;
settings;
get provider() {
return this.config.provider;
}
get maxEmbeddingsPerCall() {
return this.settings.maxEmbeddingsPerCall ?? 32;
}
get supportsParallelCalls() {
return this.settings.supportsParallelCalls ?? false;
}
constructor(modelId, settings, config) {
this.modelId = modelId;
this.settings = settings;
this.config = config;
}
#WatsonxTextEmbeddingResponseSchema = import_v45.z.object({
model_id: import_v45.z.string(),
results: import_v45.z.array(
import_v45.z.object({
embedding: import_v45.z.array(import_v45.z.number()),
input: import_v45.z.object({
text: import_v45.z.string()
}).nullish()
})
),
created_at: import_v45.z.string(),
input_token_count: import_v45.z.number(),
system: systemDetailsSchema
});
async doEmbed({
values,
abortSignal,
headers
}) {
if (values.length > this.maxEmbeddingsPerCall) {
throw new import_provider3.TooManyEmbeddingValuesForCallError({
provider: this.provider,
modelId: this.modelId,
maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
values
});
}
const { responseHeaders, value: response } = await (0, import_provider_utils4.postJsonToApi)({
url: `${this.config.clusterURL}/text/embeddings?version=${this.config.version}`,
headers: (0, import_provider_utils4.combineHeaders)(this.config.headers(), headers),
body: {
model_id: this.modelId,
project_id: this.config.projectID,
inputs: values,
encoding_format: "float",
...this.settings.truncate_input_tokens != null || this.settings.return_options != null ? {
parameters: {
...this.settings.truncate_input_tokens != null ? {
truncate_input_tokens: this.settings.truncate_input_tokens
} : {},
...this.settings.return_options != null ? { return_options: this.settings.return_options } : {}
}
} : {}
},
failedResponseHandler: watsonxFailedResponseHandler,
successfulResponseHandler: (0, import_provider_utils4.createJsonResponseHandler)(
this.#WatsonxTextEmbeddingResponseSchema
),
abortSignal,
fetch: this.config.fetch
});
return {
embeddings: response.results.map((r) => r.embedding),
usage: {
tokens: response.input_token_count
},
response: { headers: responseHeaders }
};
}
};
// src/models/completion-models/watsonx-completion-model.ts
var import_provider5 = require("@ai-sdk/provider");
var import_provider_utils5 = require("@ai-sdk/provider-utils");
var import_v47 = require("zod/v4");
// src/models/completion-models/convert-to-watsonx-completion.ts
var import_provider4 = require("@ai-sdk/provider");
function convertToWatsonxCompletion({
prompt,
inputFormat,
user = "user",
assistant = "assistant"
}) {
if (inputFormat === "prompt" && prompt.length === 1 && prompt[0].role === "user" && prompt[0].content.length === 1 && prompt[0].content[0].type === "text") {
return { prompt: prompt[0].content[0].text };
}
let text = "";
if (prompt[0].role === "system") {
text += `${prompt[0].content}
`;
prompt = prompt.slice(1);
}
for (const { role, content } of prompt) {
switch (role) {
case "system": {
throw new import_provider4.InvalidPromptError({
message: "Unexpected system message in prompt: ${content}",
prompt
});
}
case "user": {
const userMessage = content.map((part) => {
switch (part.type) {
case "text": {
return part.text;
}
case "file": {
throw new import_provider4.UnsupportedFunctionalityError({
functionality: "file"
});
}
}
}).join("");
text += `${user}:
${userMessage}
`;
break;
}
case "assistant": {
const assistantMessage = content.map((part) => {
switch (part.type) {
case "text": {
return part.text;
}
case "tool-call": {
throw new import_provider4.UnsupportedFunctionalityError({
functionality: "tool-call messages"
});
}
}
}).join("");
text += `${assistant}:
${assistantMessage}
`;
break;
}
case "tool": {
throw new import_provider4.UnsupportedFunctionalityError({
functionality: "tool messages"
});
}
default: {
throw new Error(`Unsupported role: ${role}`);
}
}
}
text += `${assistant}:
`;
return {
prompt: text,
stopSequences: [`
${user}:`]
};
}
// src/models/completion-models/watsonx-completion-schema.ts
var import_v46 = require("zod/v4");
var textgenTokenInfo = import_v46.z.array(
import_v46.z.object({
text: import_v46.z.string(),
logprob: import_v46.z.number(),
rank: import_v46.z.number(),
top_tokens: import_v46.z.array(
import_v46.z.object({
text: import_v46.z.string(),
logprob: import_v46.z.number()
})
)
})
);
var watsonxCompletionChunkSchema = import_v46.z.object({
id: import_v46.z.string().nullish(),
model_id: import_v46.z.string().nullish(),
created: import_v46.z.number().nullish(),
results: import_v46.z.array(
import_v46.z.object({
generated_text: import_v46.z.string(),
stop_reason: import_v46.z.string(),
generated_token_count: import_v46.z.number().nullish(),
input_token_count: import_v46.z.number().nullish(),
seed: import_v46.z.number().nullish(),
generated_tokens: textgenTokenInfo.optional(),
input_tokens: textgenTokenInfo.optional(),
moderations: watsonxModerationsSchema
})
),
model_version: import_v46.z.string().nullish(),
created_at: import_v46.z.string().nullish(),
usage: import_v46.z.object({
prompt_tokens: import_v46.z.number(),
completion_tokens: import_v46.z.number(),
total_tokens: import_v46.z.number()
}).nullish(),
system: systemDetailsSchema
});
var watsonxCompletionResponseSchema = import_v46.z.object({
id: import_v46.z.string().nullish(),
model_id: import_v46.z.string(),
model_version: import_v46.z.string().nullish(),
created_at: import_v46.z.string(),
results: import_v46.z.array(
import_v46.z.object({
generated_text: import_v46.z.string(),
stop_reason: import_v46.z.string(),
generated_token_count: import_v46.z.number(),
input_token_count: import_v46.z.number(),
seed: import_v46.z.number().nullish(),
generated_tokens: textgenTokenInfo.optional(),
input_tokens: textgenTokenInfo.optional(),
moderations: watsonxModerationsSchema
})
),
usage: import_v46.z.object({
prompt_tokens: import_v46.z.number(),
completion_tokens: import_v46.z.number(),
total_tokens: import_v46.z.number()
}).nullish(),
system: systemDetailsSchema
});
// src/models/completion-models/watsonx-completion-finish-reason.ts
function mapWatsonxCompletionFinishReason(reason) {
switch (reason) {
case "not_finished":
return "other";
case "max_tokens":
case "token_limit":
return "length";
case "eos_token":
case "stop_sequence":
return "stop";
case "cancelled":
return "stop";
case "time_limit":
return "unknown";
case "error":
return "error";
case null:
case void 0:
return "unknown";
default:
return "unknown";
}
}
// src/models/completion-models/watsonx-completion-model.ts
var WatsonxCompletionModel = class {
specificationVersion = "v2";
provider;
defaultObjectGenerationMode = void 0;
supportsImageUrls = false;
supportedUrls = {};
modelId;
settings;
config;
constructor(modelId, settings, config) {
this.modelId = modelId;
this.settings = settings;
this.config = config;
this.provider = config.provider;
}
getArgs(options) {
const {
prompt,
maxOutputTokens,
temperature,
topP,
topK,
frequencyPenalty,
presencePenalty,
stopSequences: userStopSequences,
responseFormat,
seed,
providerOptions
} = options;
const warnings = [];
if (responseFormat != null && responseFormat.type !== "text") {
warnings.push({
type: "unsupported-setting",
setting: "responseFormat"
});
}
const { prompt: completionPrompt, stopSequences } = convertToWatsonxCompletion({
prompt,
inputFormat: "prompt"
});
const stop = [...stopSequences ?? [], ...userStopSequences ?? []];
const baseArgs = {
model_id: this.modelId,
project_id: this.config.projectID,
input: completionPrompt,
parameters: {
// sampling & decoding
decoding_method: this.settings.decodingMethod ?? "greedy",
temperature,
top_p: topP,
top_k: topK,
// penalties and limits
frequency_penalty: frequencyPenalty,
presence_penalty: presencePenalty,
max_new_tokens: maxOutputTokens ?? this.settings.maxNewTokens,
min_new_tokens: this.settings.minNewTokens,
// control & misc
stop_sequences: stop,
random_seed: seed,
time_limit: providerOptions?.watsonx?.timeLimit,
...this.settings.textgenLengthPenalty !== void 0 ? {
length_penalty: {
decay_factor: this.settings.textgenLengthPenalty.decayFactor,
start_index: this.settings.textgenLengthPenalty.startIndex
}
} : {}
},
return_options: {
input_text: this.settings.returnOptions?.inputText ?? false,
generated_tokens: this.settings.returnOptions?.generatedTokens ?? false
}
};
return { args: baseArgs, warnings };
}
async doGenerate(options) {
const { args, warnings } = this.getArgs(options);
const {
responseHeaders,
value: response,
rawValue: rawResponse
} = await (0, import_provider_utils5.postJsonToApi)({
url: `${this.config.clusterURL}/text/generation?version=${this.config.version}`,
headers: (0, import_provider_utils5.combineHeaders)(this.config.headers(), options.headers),
body: args,
failedResponseHandler: watsonxFailedResponseHandler,
successfulResponseHandler: (0, import_provider_utils5.createJsonResponseHandler)(
watsonxCompletionResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const { messages: rawPrompt, ...rawSettings } = args;
const choice = response.results[0];
if (!choice) {
throw new Error("No choice in response");
}
return {
content: [
{
type: "text",
text: choice.generated_text
}
],
finishReason: mapWatsonxCompletionFinishReason(choice.stop_reason),
usage: {
inputTokens: response.usage?.prompt_tokens ?? NaN,
outputTokens: response.usage?.completion_tokens ?? NaN,
totalTokens: (response.usage?.prompt_tokens ?? 0) + (response.usage?.completion_tokens ?? 0)
},
warnings,
request: { body: args },
response: {
id: (0, import_provider_utils5.generateId)(),
modelId: response.model_id,
headers: responseHeaders,
body: rawResponse
}
};
}
async doStream(options) {
const url = `${this.config.clusterURL}/text/generation_stream?version=${this.config.version}`;
const { args, warnings } = this.getArgs(options);
const body = {
...args,
stream: true
};
const { value: response, responseHeaders } = await (0, import_provider_utils5.postJsonToApi)({
url,
headers: (0, import_provider_utils5.combineHeaders)(this.config.headers(), options.headers),
body,
failedResponseHandler: watsonxFailedResponseHandler,
successfulResponseHandler: (0, import_provider_utils5.createEventSourceResponseHandler)(
watsonxCompletionChunkSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
let finishReason = "other";
let usage = {
inputTokens: Number.NaN,
outputTokens: Number.NaN,
totalTokens: Number.NaN
};
let isFirstChunk = true;
return {
stream: response.pipeThrough(
new TransformStream({
transform(chunk, controller) {
if (!chunk.success) {
finishReason = "error";
controller.enqueue({ type: "error", error: chunk.error });
return;
}
const value = chunk.value;
if ("error" in value) {
finishReason = "error";
controller.enqueue({ type: "error", error: value.error });
return;
}
if (isFirstChunk) {
isFirstChunk = false;
controller.enqueue({
type: "response-metadata",
id: value.id ?? (0, import_provider_utils5.generateId)(),
modelId: value.model_id ?? void 0,
timestamp: value.created != null ? new Date(value.created * 1e3) : void 0
});
}
if (value.usage != null) {
usage = {
inputTokens: value.usage.prompt_tokens,
outputTokens: value.usage.completion_tokens,
totalTokens: value.usage.prompt_tokens + value.usage.completion_tokens
};
}
const choice = value.results[0];
if (choice?.stop_reason != null) {
finishReason = mapWatsonxCompletionFinishReason(
choice.stop_reason
);
}
if (choice?.generated_text != null) {
controller.enqueue({
type: "text-delta",
id: (0, import_provider_utils5.generateId)(),
delta: choice.generated_text
});
}
},
flush(controller) {
controller.enqueue({
type: "finish",
finishReason,
usage
});
}
})
),
warnings,
request: { body },
response: { headers: responseHeaders }
};
}
};
// src/provider.ts
function createWatsonx(options = {}) {
const clusterURL = (0, import_provider_utils6.loadOptionalSetting)({
settingValue: options.clusterURL,
environmentVariableName: "WATSONX_CLUSTER_URL"
}) ?? (() => {
const cluster = (0, import_provider_utils6.loadSetting)({
settingValue: options.cluster,
settingName: "cluster",
environmentVariableName: "WATSONX_CLUSTER",
description: "The IBM watsonx Cluster"
});
return `${(0, import_provider_utils6.withoutTrailingSlash)(`https://${cluster}.ml.cloud.ibm.com`)}/ml/v1`;
})();
const projectID = (0, import_provider_utils6.loadSetting)({
settingValue: options.projectID,
settingName: "projectID",
environmentVariableName: "WATSONX_PROJECT_ID",
description: "The IBM watsonx Project ID"
});
const getHeaders = () => ({
Authorization: `Bearer ${(0, import_provider_utils6.loadApiKey)({
apiKey: options.bearerToken,
environmentVariableName: "WATSONX_BEARER_TOKEN",
description: "Watsonx"
})}`,
...options.headers
});
const createChatModel = (modelId, settings = {}) => new WatsonxChatModel(modelId, settings, {
provider: "watsonx.chat",
clusterURL,
projectID,
headers: getHeaders,
fetch: options.fetch,
version: "2024-02-13"
});
const createEmbeddingModel = (modelId, settings = {}) => new WatsonxEmbeddingModel(modelId, settings, {
provider: "watsonx.embedding",
clusterURL,
projectID,
headers: getHeaders,
fetch: options.fetch,
version: "2024-02-13"
});
const createCompletionModel = (modelId, settings = {}) => new WatsonxCompletionModel(modelId, settings, {
provider: "watsonx.completion",
clusterURL,
projectID,
headers: getHeaders,
fetch: options.fetch,
version: "2024-02-13"
});
const provider = function(modelId, settings) {
if (new.target) {
throw new Error(
"The watsonx model function cannot be called with the new keyword."
);
}
return createChatModel(modelId, settings);
};
provider.languageModel = (modelId, settings) => createChatModel(modelId, settings);
provider.embedding = (modelId, settings) => createEmbeddingModel(modelId, settings);
provider.textEmbeddingModel = (modelId, settings) => createEmbeddingModel(modelId, settings);
provider.textEmbedding = (modelId, settings) => createEmbeddingModel(modelId, settings);
provider.completion = (modelId, settings) => createCompletionModel(modelId, settings);
provider.imageModel = () => {
throw new Error("Image models are not supported by watsonx provider");
};
return provider;
}
var watsonx = createWatsonx();
// src/models/embedding-models/watsonx-embedding-model-settings.ts
var EmbedingModelLists = {
"ca-tor": [
"ibm/granite-embedding-278m-multilingual",
"ibm/slate-125m-english-rtrvr-v2",
"ibm/slate-30m-english-rtrvr-v2",
"intfloat/multilingual-e5-large"
],
"jp-tok": [
"ibm/granite-embedding-278m-multilingual",
"ibm/slate-125m-english-rtrvr-v2",
"ibm/slate-30m-english-rtrvr-v2",
"intfloat/multilingual-e5-large",
"sentence-transformers/all-minilm-l6-v2"
],
"eu-gb": [
"ibm/granite-embedding-278m-multilingual",
"ibm/slate-125m-english-rtrvr-v2",
"ibm/slate-30m-english-rtrvr-v2",
"intfloat/multilingual-e5-large",
"sentence-transformers/all-minilm-l6-v2"
],
"eu-de": [
"ibm/granite-embedding-278m-multilingual",
"ibm/slate-125m-english-rtrvr-v2",
"ibm/slate-30m-english-rtrvr-v2",
"intfloat/multilingual-e5-large",
"sentence-transformers/all-minilm-l6-v2"
],
"us-south": [
"ibm/granite-embedding-278m-multilingual",
"ibm/slate-125m-english-rtrvr-v2",
"ibm/slate-30m-english-rtrvr-v2",
"intfloat/multilingual-e5-large",
"sentence-transformers/all-minilm-l6-v2"
],
"au-syd": [
"ibm/slate-125m-english-rtrvr-v2",
"ibm/slate-30m-english-rtrvr-v2",
"intfloat/multilingual-e5-large"
]
};
// src/models/completion-models/watsonx-completion-model-settings.ts
var CompletionModelLists = {
"ca-tor": [],
"jp-tok": [],
"eu-gb": [],
"eu-de": ["sdaia/allam-1-13b-instruct"],
"us-south": ["ibm/granite-8b-code-instruct"],
"au-syd": ["ibm/granite-8b-code-instruct"]
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ChatModelLists,
CompletionModelLists,
EmbedingModelLists,
FunctionCallingModelLists,
VisionModelLists,
WatsonxClusters,
createWatsonx,
watsonx
});
//# sourceMappingURL=index.js.map