UNPKG

@llmbridge/core

Version:

Core package for unified LLM interface

206 lines (203 loc) 6.27 kB
// src/abort.ts var abort = { value: null }; // src/types.ts function isToolRequest(message) { return "id" in message && "name" in message && "input" in message; } function isToolResponse(message) { return "id" in message && "output" in message; } function isTextMessage(message) { return !isToolRequest(message) && !isToolResponse(message) && typeof message.content === "string"; } function isMediaMessage(message) { return "content" in message && Array.isArray(message.content); } // src/index.ts import { config } from "dotenv"; import { resolve } from "path"; config({ path: resolve(process.cwd(), ".env") }); var providers = {}; var Plugins = class { constructor() { this.list = []; } add(plugin) { this.list.push(plugin); } async wrapRun(next, context) { if (this.list.length === 0) { return await next(); } let chain = next; for (let i = this.list.length - 1; i >= 0; i--) { const plugin = this.list[i]; if (plugin.wrapRun) { const currentChain = chain; chain = () => plugin.wrapRun(currentChain, context); } } return await chain(); } async wrapExec(next, params, context) { if (this.list.length === 0) { return await next(params); } let chain = next; for (let i = this.list.length - 1; i >= 0; i--) { const plugin = this.list[i]; if (plugin.wrapExec) { const currentChain = chain; chain = (params2) => plugin.wrapExec(currentChain, params2, context); } } return await chain(params); } async wrapToolExec(next, tool, counter, input, context) { if (this.list.length === 0) { return await next(tool, counter, input); } let chain = next; for (let i = this.list.length - 1; i >= 0; i--) { const plugin = this.list[i]; if (plugin.wrapToolExec) { const currentChain = chain; chain = (tool2, counter2, input2) => plugin.wrapToolExec(currentChain, tool2, counter2, input2, context); } } return await chain(tool, counter, input); } async wrapGetEmbeddings(next, params, context) { if (this.list.length === 0) { return await next(params); } let chain = next; for (let i = this.list.length - 1; i >= 0; i--) { const plugin = this.list[i]; if (plugin.wrapGetEmbeddings) { const currentChain = chain; chain = (params2) => plugin.wrapGetEmbeddings(currentChain, params2, context); } } return await chain(params); } }; var plugins = new Plugins(); var LLMBridge; ((LLMBridge2) => { LLMBridge2.isTextMessage = isTextMessage; LLMBridge2.isMediaMessage = isMediaMessage; LLMBridge2.isToolRequest = isToolRequest; LLMBridge2.isToolResponse = isToolResponse; function registerProvider(name, provider) { providers[name] = provider; } LLMBridge2.registerProvider = registerProvider; function use(plugin) { plugins.add(plugin); } LLMBridge2.use = use; async function getTextResponse(model, system_prompt, messages, options) { const result = (await run(model, system_prompt, messages, options)).messages; const lastMessage = result[result.length - 1]; if (isTextMessage(lastMessage)) { return lastMessage.content; } return null; } LLMBridge2.getTextResponse = getTextResponse; async function run(model, systemPrompt, messages, options) { const prevAbort = abort.value; const controller = new AbortController(); abort.value = controller; function checkAbort() { if (controller.signal.aborted) { throw new Error("Operation aborted"); } } try { const slashIndex = model.indexOf("/"); const providerName = model.substring(0, slashIndex); const modelName = model.substring(slashIndex + 1); let result = null; const provider = providers[providerName]; if (!provider) { throw new Error(`Provider ${providerName} not found`); } const context = { model, systemPrompt, messages, options, provider, providerName }; result = await plugins.wrapRun( () => provider.run(providerName, modelName, systemPrompt, messages, checkAbort, plugins, options), context ); return result; } finally { abort.value = prevAbort; } } LLMBridge2.run = run; async function getEmbeddings(model, text) { const slashIndex = model.indexOf("/"); const providerName = model.substring(0, slashIndex); const modelName = model.substring(slashIndex + 1); const provider = providers[providerName]; if (!provider) { throw new Error(`Provider ${providerName} not found`); } const response = await provider.getEmbeddings(modelName, plugins, text); return response; } LLMBridge2.getEmbeddings = getEmbeddings; function cleanJsonSchema(schema) { if (typeof schema !== "object" || schema === null) { return schema; } const cleanedSchema = Array.isArray(schema) ? [] : {}; for (const [key, value] of Object.entries(schema)) { if (key === "additionalProperties" || key === "$schema") { continue; } if (typeof value === "object" && value !== null) { cleanedSchema[key] = cleanJsonSchema(value); } else { cleanedSchema[key] = value; } } return cleanedSchema; } function addPropertyOrdering(schema) { if (typeof schema !== "object" || schema === null || Array.isArray(schema)) { return schema; } if (schema.required && !schema.propertyOrdering) { const requiredArray = Array.isArray(schema.required) ? schema.required : Object.values(schema.required); const allStrings = requiredArray.every((item) => typeof item === "string"); if (allStrings && requiredArray.length > 0) { schema.propertyOrdering = [...requiredArray]; } } for (const [key, value] of Object.entries(schema)) { if (typeof value === "object" && !Array.isArray(value) && value !== null) { schema[key] = addPropertyOrdering(value); } } return schema; } LLMBridge2.utils = { cleanJsonSchema, addPropertyOrdering }; })(LLMBridge || (LLMBridge = {})); export { LLMBridge };