UNPKG

@friendliai/ai-provider

Version:

<!-- header start --> <p align="center"> <img src="https://huggingface.co/datasets/FriendliAI/documentation-images/resolve/main/model-card-assets/friendliai.png" width="100%" alt="FriendliAI Logo"> </p> <!-- header end -->

1,164 lines (1,154 loc) 42 kB
"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); // src/index.ts var index_exports = {}; __export(index_exports, { createFriendli: () => createFriendli, friendli: () => friendli }); module.exports = __toCommonJS(index_exports); // src/friendli-provider.ts var import_openai_compatible = require("@ai-sdk/openai-compatible"); var import_provider4 = require("@ai-sdk/provider"); var import_provider_utils5 = require("@ai-sdk/provider-utils"); // src/friendli-chat-language-model.ts var import_internal = require("@ai-sdk/openai-compatible/internal"); var import_provider3 = require("@ai-sdk/provider"); var import_provider_utils2 = require("@ai-sdk/provider-utils"); var import_v4 = require("zod/v4"); // src/friendli-error.ts var import_provider = require("@ai-sdk/provider"); var import_provider_utils = require("@ai-sdk/provider-utils"); var import_zod = require("zod"); var friendliErrorResponseSchema = import_zod.z.object({ message: import_zod.z.string(), error: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional() }); var openAIStyleErrorResponseSchema = import_zod.z.object({ error: import_zod.z.object({ message: import_zod.z.string() }).loose() }).loose(); var friendliaiErrorSchema = import_zod.z.union([ // OpenAI/OpenRouter style error: { "error": { "message": "..." } } openAIStyleErrorResponseSchema, // Friendli style error: { "message": "...", "error": { ... } } friendliErrorResponseSchema ]); var friendliaiErrorStructure = { errorSchema: friendliaiErrorSchema, errorToMessage: (data) => { if (typeof data === "object" && data != null && "error" in data && typeof data.error === "object" && data.error != null && "message" in data.error && typeof data.error.message === "string") { return data.error.message; } if (typeof data === "object" && data != null && "message" in data && typeof data.message === "string") { return data.message; } return "Unknown error"; } }; var friendliaiFailedResponseHandler = async ({ response, url, requestBodyValues }) => { const responseBody = await response.text(); const responseHeaders = {}; response.headers.forEach((value, key) => { responseHeaders[key] = value; }); const baseErrorOptions = { url, requestBodyValues, statusCode: response.status, responseHeaders, responseBody }; const trimmedBody = responseBody.trim(); if (trimmedBody === "") { const fallback2 = response.statusText || `Request failed with status ${response.status}`; return { responseHeaders, value: new import_provider.APICallError({ message: fallback2, ...baseErrorOptions }) }; } const parsedError = await (0, import_provider_utils.safeParseJSON)({ text: responseBody, schema: friendliaiErrorSchema }); if (parsedError.success) { return { responseHeaders, value: new import_provider.APICallError({ message: friendliaiErrorStructure.errorToMessage(parsedError.value), data: parsedError.value, ...baseErrorOptions }) }; } const fallback = trimmedBody || response.statusText || `Request failed with status ${response.status}`; return { responseHeaders, value: new import_provider.APICallError({ message: fallback, cause: parsedError.error, ...baseErrorOptions }) }; }; var tryWrapFriendliJsonEnvelopeError = async (error) => { if (!import_provider.APICallError.isInstance(error)) { return void 0; } const responseBody = error.responseBody; if (typeof responseBody !== "string" || responseBody.trim() === "") { return void 0; } const parsedError = await (0, import_provider_utils.safeParseJSON)({ text: responseBody, schema: friendliaiErrorSchema }); if (!parsedError.success) { return void 0; } return new import_provider.APICallError({ message: friendliaiErrorStructure.errorToMessage(parsedError.value), url: error.url, requestBodyValues: error.requestBodyValues, statusCode: error.statusCode, responseHeaders: error.responseHeaders, responseBody: error.responseBody, cause: error, isRetryable: error.isRetryable, data: parsedError.value }); }; // src/friendli-prepare-tools.ts var import_provider2 = require("@ai-sdk/provider"); function prepareTools({ tools, toolChoice }) { var _a; tools = (tools == null ? void 0 : tools.length) ? tools : void 0; const toolWarnings = []; if (tools == null) { return { tools: void 0, toolChoice: void 0, toolWarnings }; } const openaiCompatTools = []; for (const tool of tools) { if (tool.type === "provider") { openaiCompatTools.push({ // NOTE: Friendli tool-assisted API expects provider tool types like "web:search". // We derive it from the provider tool id (e.g. "friendli.web:search" -> "web:search") // instead of tool.name (often "web_search"). type: (_a = tool.id.split(".")[1]) != null ? _a : "unknown" }); } else { openaiCompatTools.push({ type: "function", function: { name: tool.name, description: tool.description, parameters: tool.inputSchema } }); } } if (toolChoice == null) { return { tools: openaiCompatTools, toolChoice: void 0, toolWarnings }; } const type = toolChoice.type; switch (type) { case "auto": case "none": case "required": return { tools: openaiCompatTools, toolChoice: type, toolWarnings }; case "tool": return { tools: openaiCompatTools, toolChoice: { type: "function", function: { name: toolChoice.toolName } }, toolWarnings }; default: { const _exhaustiveCheck = type; throw new import_provider2.UnsupportedFunctionalityError({ functionality: `tool choice type: ${_exhaustiveCheck}` }); } } } // src/friendli-chat-language-model.ts function isRecord(value) { return typeof value === "object" && value != null; } function isHostedToolExecutionChunk(value) { if (!isRecord(value)) return false; return typeof value.status === "string" && typeof value.name === "string" && Array.isArray(value.parameters); } function getChunkErrorMessage(value) { if (!isRecord(value)) return void 0; if (typeof value.message === "string") { return value.message; } const nestedError = value.error; if (isRecord(nestedError) && typeof nestedError.message === "string") { return nestedError.message; } return void 0; } function isOpenAIChatChunk(value) { if (!isRecord(value)) return false; return Array.isArray(value.choices); } function addReasoningToMessages(prompt, messages) { let promptAssistantIndex = 0; for (const promptMessage of prompt) { if (promptMessage.role === "assistant") { const reasoningText = promptMessage.content.filter((part) => part.type === "reasoning").map((part) => part.text).join("\n"); if (reasoningText) { let messagesAssistantIndex = 0; for (let i = 0; i < messages.length; i++) { if (messages[i].role === "assistant") { if (messagesAssistantIndex === promptAssistantIndex) { messages[i].reasoning_content = reasoningText; break; } messagesAssistantIndex++; } } } promptAssistantIndex++; } } return messages; } var FriendliAIChatLanguageModel = class { // type inferred via constructor constructor(modelId, config) { this.specificationVersion = "v3"; var _a; this.modelId = modelId; this.config = config; const errorStructure = friendliaiErrorStructure; this.chunkSchema = createOpenAICompatibleChatChunkSchema(errorStructure.errorSchema); this.failedResponseHandler = friendliaiFailedResponseHandler; this.supportsStructuredOutputs = (_a = config.supportsStructuredOutputs) != null ? _a : true; } get provider() { return this.config.provider; } get supportedUrls() { var _a, _b, _c; return (_c = (_b = (_a = this.config).supportedUrls) == null ? void 0 : _b.call(_a)) != null ? _c : {}; } async getArgs({ prompt, maxOutputTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, providerOptions, stopSequences, responseFormat, seed, toolChoice, tools, stream }) { var _a; const warnings = []; const friendliOptions = await (0, import_provider_utils2.parseProviderOptions)({ provider: "friendliai", providerOptions, schema: friendliProviderOptionsSchema }); const legacyFriendliOptions = await (0, import_provider_utils2.parseProviderOptions)({ provider: "friendli", providerOptions, schema: friendliProviderOptionsSchema }); const options = { ...legacyFriendliOptions, ...friendliOptions }; if ((responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !this.supportsStructuredOutputs) { warnings.push({ type: "unsupported", feature: "responseFormat", details: "JSON response format schema is only supported with structuredOutputs" }); } const { tools: openaiTools, toolChoice: openaiToolChoice, toolWarnings } = prepareTools({ tools, toolChoice }); const isToolsPresent = openaiTools != null && openaiTools.length > 0; if (isToolsPresent && (responseFormat != null || (options == null ? void 0 : options.regex) != null)) { warnings.push({ type: "unsupported", feature: "responseFormat", details: "response_format is not supported when tools are present." }); } return { args: { // >>> hard-coded default options >>> parse_reasoning: true, // <<< hard-coded default options <<< model: this.modelId, // standardized settings: stream, max_tokens: maxOutputTokens, temperature, top_p: topP, top_k: topK, frequency_penalty: frequencyPenalty, presence_penalty: presencePenalty, response_format: isToolsPresent === false ? (responseFormat == null ? void 0 : responseFormat.type) === "json" ? this.supportsStructuredOutputs === true && responseFormat.schema != null ? { type: "json_schema", json_schema: { schema: responseFormat.schema, name: (_a = responseFormat.name) != null ? _a : "response", description: responseFormat.description } } : { type: "json_object" } : (options == null ? void 0 : options.regex) != null ? { type: "regex", schema: options.regex } : void 0 : void 0, stop: stopSequences, seed, min_p: options == null ? void 0 : options.minP, repetition_penalty: options == null ? void 0 : options.repetitionPenalty, xtc_threshold: options == null ? void 0 : options.xtcThreshold, xtc_probability: options == null ? void 0 : options.xtcProbability, ...(options == null ? void 0 : options.chat_template_kwargs) ? { chat_template_kwargs: options.chat_template_kwargs } : {}, // messages: // Use addReasoningToMessages to include reasoning_content in assistant messages // for interleaved thinking support messages: addReasoningToMessages(prompt, (0, import_internal.convertToOpenAICompatibleChatMessages)(prompt)), // tools: tools: openaiTools, tool_choice: openaiToolChoice, parallel_tool_calls: options == null ? void 0 : options.parallelToolCalls }, warnings: [...warnings, ...toolWarnings] }; } async doGenerate(options) { var _a, _b; const { args, warnings } = await this.getArgs({ ...options, stream: false }); const body = JSON.stringify(args); const response = await (async () => { try { return await (0, import_provider_utils2.postJsonToApi)({ url: this.config.url({ path: "/chat/completions", modelId: this.modelId }), headers: (0, import_provider_utils2.combineHeaders)(this.config.headers(), options.headers), body: args, failedResponseHandler: this.failedResponseHandler, successfulResponseHandler: (0, import_provider_utils2.createJsonResponseHandler)(OpenAICompatibleChatResponseSchema), abortSignal: options.abortSignal, fetch: this.config.fetch }); } catch (error) { const wrappedError = await tryWrapFriendliJsonEnvelopeError(error); if (wrappedError != null) { throw wrappedError; } throw error; } })(); const { responseHeaders, value: responseBody, rawValue: rawResponse } = response; const choice = responseBody.choices[0]; const content = []; const text = choice.message.content; if (text != null && text.length > 0) { content.push({ type: "text", text }); } const reasoning = choice.message.reasoning_content; if (reasoning != null && reasoning.length > 0) { content.push({ type: "reasoning", text: reasoning }); } if (choice.message.tool_calls != null) { for (const toolCall of choice.message.tool_calls) { content.push({ type: "tool-call", toolCallId: (_a = toolCall.id) != null ? _a : (0, import_provider_utils2.generateId)(), toolName: toolCall.function.name, input: toolCall.function.arguments }); } } return { content, finishReason: { unified: (0, import_internal.mapOpenAICompatibleFinishReason)(choice.finish_reason), raw: (_b = choice.finish_reason) != null ? _b : void 0 }, usage: (0, import_internal.convertOpenAICompatibleChatUsage)(responseBody.usage), // providerMetadata, request: { body }, response: { ...(0, import_internal.getResponseMetadata)(responseBody), headers: responseHeaders, body: rawResponse }, warnings }; } async doStream(options) { var _a; const { args, warnings } = await this.getArgs({ ...options, stream: true }); const body = { ...args, stream: true, // only include stream_options when in strict compatibility mode: stream_options: this.config.includeUsage ? { include_usage: true } : void 0 }; const metadataExtractor = (_a = this.config.metadataExtractor) == null ? void 0 : _a.createStreamExtractor(); const { responseHeaders, value: response } = await (0, import_provider_utils2.postJsonToApi)({ url: this.config.url({ path: "/chat/completions", modelId: this.modelId }), headers: (0, import_provider_utils2.combineHeaders)(this.config.headers(), options.headers), body, failedResponseHandler: this.failedResponseHandler, successfulResponseHandler: (0, import_provider_utils2.createEventSourceResponseHandler)(this.chunkSchema), abortSignal: options.abortSignal, fetch: this.config.fetch }); const toolCalls = []; let finishReason = { unified: "other", raw: void 0 }; let usage = void 0; let isFirstChunk = true; const providerOptionsName = "friendliai"; let currentTextId = null; let currentReasoningId = null; return { stream: response.pipeThrough( new TransformStream({ start(controller) { controller.enqueue({ type: "stream-start", warnings }); }, // NOTE: Chunk values can contain OpenAI-compatible deltas, hosted tool events, and error events. // We narrow with type guards for safe handling. transform(chunk, controller) { var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q; if (options.includeRawChunks) { controller.enqueue({ type: "raw", rawValue: chunk.rawValue }); } if (!chunk.success) { finishReason = { unified: "error", raw: void 0 }; controller.enqueue({ type: "error", error: chunk.error }); return; } const value = chunk.value; metadataExtractor == null ? void 0 : metadataExtractor.processChunk(chunk.rawValue); if (isHostedToolExecutionChunk(value)) { const toolCallId = (_a2 = value.tool_call_id) != null ? _a2 : (0, import_provider_utils2.generateId)(); switch (value.status) { case "STARTED": controller.enqueue({ type: "tool-call", toolCallId, toolName: value.name, input: JSON.stringify( Object.fromEntries(value.parameters.map((p) => [p.name, p.value])) ), providerExecuted: true }); break; case "UPDATING": break; case "ENDED": controller.enqueue({ type: "tool-result", toolCallId, toolName: value.name, result: (_b = value.result) != null ? _b : "" }); break; case "ERRORED": finishReason = { unified: "error", raw: void 0 }; controller.enqueue({ type: "tool-result", toolCallId, toolName: value.name, result: (_d = (_c = value.error) == null ? void 0 : _c.msg) != null ? _d : "Unknown error", isError: true }); break; default: finishReason = { unified: "error", raw: void 0 }; controller.enqueue({ type: "error", error: new Error(`Unsupported tool call status: ${value.status}`) }); } return; } const chunkErrorMessage = getChunkErrorMessage(value); if (chunkErrorMessage != null) { finishReason = { unified: "error", raw: void 0 }; controller.enqueue({ type: "error", error: chunkErrorMessage }); return; } if (!isOpenAIChatChunk(value)) { finishReason = { unified: "error", raw: void 0 }; controller.enqueue({ type: "error", error: new Error("Unsupported chunk shape") }); return; } const chunkValue = value; if (isFirstChunk) { isFirstChunk = false; controller.enqueue({ type: "response-metadata", ...(0, import_internal.getResponseMetadata)(chunkValue) }); } if (chunkValue.usage != null) { usage = chunkValue.usage; } const choice = chunkValue.choices[0]; if ((choice == null ? void 0 : choice.finish_reason) != null) { finishReason = { unified: (0, import_internal.mapOpenAICompatibleFinishReason)(choice.finish_reason), raw: choice.finish_reason }; } if ((choice == null ? void 0 : choice.delta) == null) { return; } const delta = choice.delta; if (delta.reasoning_content != null) { if (currentReasoningId == null) { currentReasoningId = (0, import_provider_utils2.generateId)(); controller.enqueue({ type: "reasoning-start", id: currentReasoningId }); } controller.enqueue({ type: "reasoning-delta", id: currentReasoningId, delta: delta.reasoning_content }); } if (delta.content != null) { if (currentTextId == null) { currentTextId = (0, import_provider_utils2.generateId)(); controller.enqueue({ type: "text-start", id: currentTextId }); } controller.enqueue({ type: "text-delta", id: currentTextId, delta: delta.content }); } if (delta.tool_calls != null) { for (const toolCallDelta of delta.tool_calls) { const index = toolCallDelta.index; if (toolCalls[index] == null) { if (toolCallDelta.type !== "function") { throw new import_provider3.InvalidResponseDataError({ data: toolCallDelta, message: `Expected 'function' type.` }); } if (toolCallDelta.id == null) { throw new import_provider3.InvalidResponseDataError({ data: toolCallDelta, message: `Expected 'id' to be a string.` }); } if (((_e = toolCallDelta.function) == null ? void 0 : _e.name) == null) { throw new import_provider3.InvalidResponseDataError({ data: toolCallDelta, message: `Expected 'function.name' to be a string.` }); } toolCalls[index] = { id: toolCallDelta.id, type: "function", function: { name: toolCallDelta.function.name, arguments: (_f = toolCallDelta.function.arguments) != null ? _f : "" }, hasFinished: false }; controller.enqueue({ type: "tool-input-start", id: toolCallDelta.id, toolName: toolCallDelta.function.name }); const toolCall2 = toolCalls[index]; if (((_g = toolCall2.function) == null ? void 0 : _g.name) != null && ((_h = toolCall2.function) == null ? void 0 : _h.arguments) != null) { if (toolCall2.function.arguments.length > 0) { controller.enqueue({ type: "tool-input-delta", id: toolCall2.id, delta: toolCall2.function.arguments }); } if ((0, import_provider_utils2.isParsableJson)(toolCall2.function.arguments)) { controller.enqueue({ type: "tool-input-end", id: toolCall2.id }); controller.enqueue({ type: "tool-call", toolCallId: (_i = toolCall2.id) != null ? _i : (0, import_provider_utils2.generateId)(), toolName: toolCall2.function.name, input: toolCall2.function.arguments }); toolCall2.hasFinished = true; } } continue; } const toolCall = toolCalls[index]; if (toolCall.hasFinished) { continue; } if (((_j = toolCallDelta.function) == null ? void 0 : _j.arguments) != null) { toolCall.function.arguments += (_l = (_k = toolCallDelta.function) == null ? void 0 : _k.arguments) != null ? _l : ""; } controller.enqueue({ type: "tool-input-delta", id: toolCall.id, delta: (_n = (_m = toolCallDelta.function) == null ? void 0 : _m.arguments) != null ? _n : "" }); if (((_o = toolCall.function) == null ? void 0 : _o.name) != null && ((_p = toolCall.function) == null ? void 0 : _p.arguments) != null && (0, import_provider_utils2.isParsableJson)(toolCall.function.arguments)) { controller.enqueue({ type: "tool-input-end", id: toolCall.id }); controller.enqueue({ type: "tool-call", toolCallId: (_q = toolCall.id) != null ? _q : (0, import_provider_utils2.generateId)(), toolName: toolCall.function.name, input: toolCall.function.arguments }); toolCall.hasFinished = true; } } } }, flush(controller) { var _a2, _b, _c; if (currentReasoningId != null) { controller.enqueue({ type: "reasoning-end", id: currentReasoningId }); } if (currentTextId != null) { controller.enqueue({ type: "text-end", id: currentTextId }); } for (const toolCall of toolCalls.filter( (pendingToolCall) => !pendingToolCall.hasFinished )) { controller.enqueue({ type: "tool-input-end", id: toolCall.id }); controller.enqueue({ type: "tool-call", toolCallId: (_a2 = toolCall.id) != null ? _a2 : (0, import_provider_utils2.generateId)(), toolName: toolCall.function.name, input: toolCall.function.arguments }); } const providerMetadata = { [providerOptionsName]: {}, ...metadataExtractor == null ? void 0 : metadataExtractor.buildMetadata() }; if (((_b = usage == null ? void 0 : usage.completion_tokens_details) == null ? void 0 : _b.accepted_prediction_tokens) != null) { providerMetadata[providerOptionsName].acceptedPredictionTokens = usage.completion_tokens_details.accepted_prediction_tokens; } if (((_c = usage == null ? void 0 : usage.completion_tokens_details) == null ? void 0 : _c.rejected_prediction_tokens) != null) { providerMetadata[providerOptionsName].rejectedPredictionTokens = usage.completion_tokens_details.rejected_prediction_tokens; } controller.enqueue({ type: "finish", finishReason, usage: (0, import_internal.convertOpenAICompatibleChatUsage)(usage), providerMetadata }); } }) ), request: { body }, response: { headers: responseHeaders } }; } }; var openaiCompatibleTokenUsageSchema = import_v4.z.object({ prompt_tokens: import_v4.z.number().nullish(), completion_tokens: import_v4.z.number().nullish(), total_tokens: import_v4.z.number().nullish(), prompt_tokens_details: import_v4.z.object({ cached_tokens: import_v4.z.number().nullish() }).nullish(), completion_tokens_details: import_v4.z.object({ reasoning_tokens: import_v4.z.number().nullish(), accepted_prediction_tokens: import_v4.z.number().nullish(), rejected_prediction_tokens: import_v4.z.number().nullish() }).nullish() }).nullish(); var OpenAICompatibleChatResponseSchema = import_v4.z.object({ id: import_v4.z.string().nullish(), created: import_v4.z.number().nullish(), model: import_v4.z.string().nullish(), choices: import_v4.z.array( import_v4.z.object({ message: import_v4.z.object({ role: import_v4.z.literal("assistant").nullish(), content: import_v4.z.string().nullish(), reasoning_content: import_v4.z.string().nullish(), tool_calls: import_v4.z.array( import_v4.z.object({ id: import_v4.z.string().nullish(), type: import_v4.z.literal("function"), function: import_v4.z.object({ name: import_v4.z.string(), arguments: import_v4.z.string() }) }) ).nullish() }), finish_reason: import_v4.z.string().nullish() }) ), usage: openaiCompatibleTokenUsageSchema }); var createOpenAICompatibleChatChunkSchema = (errorSchema) => import_v4.z.union([ import_v4.z.object({ id: import_v4.z.string().nullish(), created: import_v4.z.number().nullish(), model: import_v4.z.string().nullish(), choices: import_v4.z.array( import_v4.z.object({ delta: import_v4.z.object({ role: import_v4.z.enum(["assistant"]).nullish(), content: import_v4.z.string().nullish(), reasoning_content: import_v4.z.string().nullish(), tool_calls: import_v4.z.array( import_v4.z.object({ index: import_v4.z.number(), id: import_v4.z.string().nullish(), type: import_v4.z.literal("function").nullish(), function: import_v4.z.object({ name: import_v4.z.string().nullish(), arguments: import_v4.z.string().nullish() }) }) ).nullish() }).nullish(), finish_reason: import_v4.z.string().nullish() }) ), usage: openaiCompatibleTokenUsageSchema }), import_v4.z.object({ name: import_v4.z.string(), status: import_v4.z.enum(["ENDED", "STARTED", "ERRORED", "UPDATING"]), message: import_v4.z.null(), parameters: import_v4.z.array( import_v4.z.object({ name: import_v4.z.string(), value: import_v4.z.string() }) ), result: import_v4.z.string().nullable(), error: import_v4.z.object({ type: import_v4.z.enum(["INVALID_PARAMETER", "UNKNOWN"]), msg: import_v4.z.string() }).nullable(), timestamp: import_v4.z.number(), usage: import_v4.z.null(), tool_call_id: import_v4.z.string().nullable() }), errorSchema ]); var friendliProviderOptionsSchema = import_v4.z.object({ /** * Whether to enable parallel function calling during tool use. Default to true. */ parallelToolCalls: import_v4.z.boolean().nullish(), /** * BETA FEATURE: You can write a regular expression to force output that satisfies that regular expression. */ // regex: z.instanceof(RegExp).nullish(), regex: import_v4.z.string().nullish(), chat_template_kwargs: import_v4.z.record(import_v4.z.string(), import_v4.z.any()).nullish(), /** * A scaling factor used to determine the minimum token probability threshold. */ minP: import_v4.z.number().nullish(), /** * Penalizes tokens that have already appeared in the generated result. */ repetitionPenalty: import_v4.z.number().nullish(), /** * A probability threshold used to identify “top choice” tokens for exclusion in XTC sampling. */ xtcThreshold: import_v4.z.number().nullish(), /** * The probability that XTC (Exclude Top Choices) filtering will be applied for each sampling decision. */ xtcProbability: import_v4.z.number().nullish() }); // src/friendli-settings.ts var FriendliAIServerlessModelIds = [ "google/gemma-4-31B-it", "zai-org/GLM-5.1", "zai-org/GLM-5", "meta-llama/Llama-3.3-70B-Instruct", "meta-llama-3.3-70b-instruct", "meta-llama/Llama-3.1-8B-Instruct", "meta-llama-3.1-8b-instruct", "Qwen/Qwen3-235B-A22B-Instruct-2507", "deepseek-ai/DeepSeek-V3.2", "openai/whisper-large-v3", "MiniMaxAI/MiniMax-M2.5", "LGAI-EXAONE/K-EXAONE-236B-A23B" ]; // src/friendli-tools.ts var import_provider_utils3 = require("@ai-sdk/provider-utils"); var import_zod2 = require("zod"); var inputSchema = import_zod2.z.object({}).loose(); var outputSchema = import_zod2.z.unknown(); var webSearchTool = (0, import_provider_utils3.createProviderToolFactoryWithOutputSchema)({ id: "friendli.web:search", inputSchema, outputSchema }); var webUrlTool = (0, import_provider_utils3.createProviderToolFactoryWithOutputSchema)({ id: "friendli.web:url", inputSchema, outputSchema }); var mathCalendarTool = (0, import_provider_utils3.createProviderToolFactoryWithOutputSchema)({ id: "friendli.math:calendar", inputSchema, outputSchema }); var mathStatisticsTool = (0, import_provider_utils3.createProviderToolFactoryWithOutputSchema)({ id: "friendli.math:statistics", inputSchema, outputSchema }); var mathCalculatorTool = (0, import_provider_utils3.createProviderToolFactoryWithOutputSchema)({ id: "friendli.math:calculator", inputSchema, outputSchema }); var codePythonInterpreterTool = (0, import_provider_utils3.createProviderToolFactoryWithOutputSchema)({ id: "friendli.code:python-interpreter", inputSchema, outputSchema }); var linkupSearchTool = (0, import_provider_utils3.createProviderToolFactoryWithOutputSchema)({ id: "friendli.linkup:search", inputSchema, outputSchema }); function webSearch() { return webSearchTool({}); } function webUrl() { return webUrlTool({}); } function mathCalendar() { return mathCalendarTool({}); } function mathStatistics() { return mathStatisticsTool({}); } function mathCalculator() { return mathCalculatorTool({}); } function codePythonInterpreter() { return codePythonInterpreterTool({}); } function linkupSearch() { return linkupSearchTool({}); } var friendliTools = { webSearch, webUrl, mathCalendar, mathStatistics, mathCalculator, codePythonInterpreter, linkupSearch }; // src/get-available-models.ts var import_provider_utils4 = require("@ai-sdk/provider-utils"); var DEFAULT_GRAPHQL_URL = "https://api-internal.friendli.ai/api/graphql"; async function postGraphQL(url, body, headers) { const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", ...headers }, body: JSON.stringify(body) }); let json; try { json = await res.json(); } catch (err) { console.error( "Failed to parse JSON response from Friendli API:", err, "Status:", res.status, res.statusText ); throw new Error( `Failed to parse JSON response from Friendli API: ${err instanceof Error ? err.message : String(err)}` ); } return json; } function normalizePriceUnit(unit) { if (!unit) return void 0; return unit; } async function getAvailableModelsImpl(options) { var _a, _b, _c, _d, _e, _f; let token; try { token = (_a = options.apiKey) != null ? _a : (0, import_provider_utils4.loadApiKey)({ apiKey: void 0, environmentVariableName: "FRIENDLI_TOKEN", description: "FRIENDLI_TOKEN" }); } catch (e) { token = void 0; } const headers = { ...token ? { Authorization: `Bearer ${token}` } : {}, ...options.teamId ? { "X-Friendli-Team": options.teamId } : {}, ...(_b = options.headers) != null ? _b : {} }; const url = (_c = options.graphqlURL) != null ? _c : DEFAULT_GRAPHQL_URL; const query = ` query Edges { serverlessEndpoints { edges { ... on ServerlessChatEndpointCatalog { id name status price { inputPrice cachedInputPrice outputPrice audioMinutePrice unit responseTimePrice priceUnitType } contextLength } } } } `; const resp = await postGraphQL( url, { query, variables: {}, operationName: "Edges" }, headers ); if (resp.errors && resp.errors.length > 0) { throw new Error( `getAvailableModels: GraphQL error: ${resp.errors.map((e) => e.message).join("; ")}` ); } const edges = (_f = (_e = (_d = resp.data) == null ? void 0 : _d.serverlessEndpoints) == null ? void 0 : _e.edges) != null ? _f : []; const models = edges.map((e) => { var _a2, _b2, _c2, _d2, _e2, _f2, _g, _h; const warm = e.status === "WARM"; const pricing = e.price ? { inputToken: (_a2 = e.price.inputPrice) != null ? _a2 : void 0, cachedInputToken: (_b2 = e.price.cachedInputPrice) != null ? _b2 : void 0, outputToken: (_c2 = e.price.outputPrice) != null ? _c2 : void 0, responseTime: (_d2 = e.price.responseTimePrice) != null ? _d2 : void 0, audioMinute: (_e2 = e.price.audioMinutePrice) != null ? _e2 : void 0, unitType: (_f2 = e.price.priceUnitType) != null ? _f2 : void 0, unit: normalizePriceUnit(e.price.unit), currency: "USD" } : void 0; return { id: e.id, name: (_g = e.name) != null ? _g : void 0, description: void 0, pricing, warm, cold: warm === false, contextLength: (_h = e.contextLength) != null ? _h : void 0 }; }); return { models }; } // src/friendli-provider.ts function createFriendli(options = {}) { const getHeaders = () => ({ Authorization: `Bearer ${(0, import_provider_utils5.loadApiKey)({ apiKey: options.apiKey, environmentVariableName: "FRIENDLI_TOKEN", description: "FRIENDLI_TOKEN" })}`, "X-Friendli-Team": options.teamId, ...options.headers }); const baseURLAutoSelect = (modelId, baseURL) => { const FriendliBaseURL = { serverless: "https://api.friendli.ai/serverless/v1", serverless_tools: "https://api.friendli.ai/serverless/tools/v1", dedicated: "https://api.friendli.ai/dedicated/v1" }; const customBaseURL = (0, import_provider_utils5.withoutTrailingSlash)(baseURL); if (typeof customBaseURL === "string" && customBaseURL !== "dedicated" && customBaseURL !== "serverless" && customBaseURL !== "serverless-tools") { return { baseURL: customBaseURL, type: "custom" }; } switch (baseURL) { case "dedicated": return { baseURL: FriendliBaseURL.dedicated, type: "dedicated" }; case "serverless": return { baseURL: FriendliBaseURL.serverless, type: "serverless" }; case "serverless-tools": return { baseURL: FriendliBaseURL.serverless_tools, type: "serverless-tools" }; default: if (FriendliAIServerlessModelIds.includes(modelId)) { return { baseURL: FriendliBaseURL.serverless, type: "serverless" }; } else { return { baseURL: FriendliBaseURL.dedicated, type: "dedicated" }; } } }; const createLanguageModel = (modelId) => { const { baseURL, type } = baseURLAutoSelect(modelId, options.baseURL); return new FriendliAIChatLanguageModel(modelId, { provider: `friendliai.${type}.chat`, url: ({ path }) => `${baseURL}${path}`, headers: getHeaders, fetch: options.fetch, includeUsage: options.includeUsage }); }; const createCompletionModel = (modelId) => { const { baseURL, type } = baseURLAutoSelect(modelId, options.baseURL); return new import_openai_compatible.OpenAICompatibleCompletionLanguageModel(modelId, { provider: `friendliai.${type}.completion`, url: ({ path }) => `${baseURL}${path}`, headers: getHeaders, fetch: options.fetch, errorStructure: friendliaiErrorStructure }); }; const createTextEmbeddingModel = (modelId) => { throw new import_provider4.NoSuchModelError({ modelId, modelType: "embeddingModel" }); }; const createImageModel = (modelId) => { throw new import_provider4.NoSuchModelError({ modelId, modelType: "imageModel" }); }; const createTranscriptionModel = (modelId) => { throw new import_provider4.NoSuchModelError({ modelId, modelType: "languageModel" }); }; const createSpeechModel = (modelId) => { throw new import_provider4.NoSuchModelError({ modelId, modelType: "languageModel" }); }; const provider = (modelId) => createLanguageModel(modelId); provider.languageModel = createLanguageModel; provider.chat = createLanguageModel; provider.completion = createCompletionModel; provider.embedding = createTextEmbeddingModel; provider.embeddingModel = createTextEmbeddingModel; provider.getAvailableModels = async (opts) => { var _a; const defaultURL = "https://api-internal.friendli.ai/api/graphql"; const graphqlURL = (_a = opts == null ? void 0 : opts.graphqlURL) != null ? _a : defaultURL; const apiKey = options.apiKey; const teamId = options.teamId; const headers = options.headers; return getAvailableModelsImpl({ apiKey, teamId, headers, graphqlURL }); }; provider.imageModel = createImageModel; provider.transcription = createTranscriptionModel; provider.speech = createSpeechModel; provider.tools = friendliTools; return provider; } var friendli = createFriendli(); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createFriendli, friendli }); //# sourceMappingURL=index.js.map