Feat/add.azure.and.other.providers (#607)

* fix: claude-4 not having the right max_tokens

* feat: add bedrock support

* chore: fix package-lock.json

* fix: rename baseUrl to baseURL

* feat: add azure support

* fix: final touches of azure integration

* feat: add google vertex provider

* chore: fix tests and refactor task-manager.test.js

* chore: move task 92 to 94
This commit is contained in:
Ralph Khreish
2025-05-28 00:42:31 +02:00
committed by GitHub
parent 80735f9e60
commit 6a8a68e1a3
49 changed files with 12785 additions and 5015 deletions

View File

@@ -1,199 +1,39 @@
import { createOpenAI } from '@ai-sdk/openai'; // Using openai provider from Vercel AI SDK
import { generateObject, generateText } from 'ai'; // Import necessary functions from 'ai'
import { log } from '../../scripts/modules/utils.js';
function getClient(apiKey, baseUrl) {
if (!apiKey) {
throw new Error('OpenAI API key is required.');
}
return createOpenAI({
apiKey: apiKey,
...(baseUrl && { baseURL: baseUrl })
});
}
/**
* Generates text using OpenAI models via Vercel AI SDK.
*
* @param {object} params - Parameters including apiKey, modelId, messages, maxTokens, temperature, baseUrl.
* @returns {Promise<object>} The generated text content and usage.
* @throws {Error} If API call fails.
* openai.js
* AI provider implementation for OpenAI models using Vercel AI SDK.
*/
export async function generateOpenAIText(params) {
const { apiKey, modelId, messages, maxTokens, temperature, baseUrl } = params;
log('debug', `generateOpenAIText called with model: ${modelId}`);
if (!apiKey) {
throw new Error('OpenAI API key is required.');
}
if (!modelId) {
throw new Error('OpenAI Model ID is required.');
}
if (!messages || !Array.isArray(messages) || messages.length === 0) {
throw new Error('Invalid or empty messages array provided for OpenAI.');
import { createOpenAI } from '@ai-sdk/openai';
import { BaseAIProvider } from './base-provider.js';
export class OpenAIProvider extends BaseAIProvider {
constructor() {
super();
this.name = 'OpenAI';
}
const openaiClient = getClient(apiKey, baseUrl);
/**
* Creates and returns an OpenAI client instance.
* @param {object} params - Parameters for client initialization
* @param {string} params.apiKey - OpenAI API key
* @param {string} [params.baseURL] - Optional custom API endpoint
* @returns {Function} OpenAI client function
* @throws {Error} If API key is missing or initialization fails
*/
getClient(params) {
try {
const { apiKey, baseURL } = params;
try {
const result = await generateText({
model: openaiClient(modelId),
messages,
maxTokens,
temperature
});
if (!result || !result.text) {
log(
'warn',
'OpenAI generateText response did not contain expected content.',
{ result }
);
throw new Error('Failed to extract content from OpenAI response.');
}
log(
'debug',
`OpenAI generateText completed successfully for model: ${modelId}`
);
return {
text: result.text.trim(),
usage: {
inputTokens: result.usage.promptTokens,
outputTokens: result.usage.completionTokens
if (!apiKey) {
throw new Error('OpenAI API key is required.');
}
};
} catch (error) {
log(
'error',
`Error in generateOpenAIText (Model: ${modelId}): ${error.message}`,
{ error }
);
throw new Error(
`OpenAI API error during text generation: ${error.message}`
);
}
}
/**
* Streams text using OpenAI models via Vercel AI SDK.
*
* @param {object} params - Parameters including apiKey, modelId, messages, maxTokens, temperature, baseUrl.
* @returns {Promise<ReadableStream>} A readable stream of text deltas.
* @throws {Error} If API call fails.
*/
export async function streamOpenAIText(params) {
const { apiKey, modelId, messages, maxTokens, temperature, baseUrl } = params;
log('debug', `streamOpenAIText called with model: ${modelId}`);
if (!apiKey) {
throw new Error('OpenAI API key is required.');
}
if (!modelId) {
throw new Error('OpenAI Model ID is required.');
}
if (!messages || !Array.isArray(messages) || messages.length === 0) {
throw new Error(
'Invalid or empty messages array provided for OpenAI streaming.'
);
}
const openaiClient = getClient(apiKey, baseUrl);
try {
const stream = await openaiClient.chat.stream(messages, {
model: modelId,
max_tokens: maxTokens,
temperature
});
log(
'debug',
`OpenAI streamText initiated successfully for model: ${modelId}`
);
return stream;
} catch (error) {
log(
'error',
`Error initiating OpenAI stream (Model: ${modelId}): ${error.message}`,
{ error }
);
throw new Error(
`OpenAI API error during streaming initiation: ${error.message}`
);
}
}
/**
* Generates structured objects using OpenAI models via Vercel AI SDK.
*
* @param {object} params - Parameters including apiKey, modelId, messages, schema, objectName, maxTokens, temperature, baseUrl.
* @returns {Promise<object>} The generated object matching the schema and usage.
* @throws {Error} If API call fails or object generation fails.
*/
export async function generateOpenAIObject(params) {
const {
apiKey,
modelId,
messages,
schema,
objectName,
maxTokens,
temperature,
baseUrl
} = params;
log(
'debug',
`generateOpenAIObject called with model: ${modelId}, object: ${objectName}`
);
if (!apiKey) throw new Error('OpenAI API key is required.');
if (!modelId) throw new Error('OpenAI Model ID is required.');
if (!messages || !Array.isArray(messages) || messages.length === 0)
throw new Error('Invalid messages array for OpenAI object generation.');
if (!schema)
throw new Error('Schema is required for OpenAI object generation.');
if (!objectName)
throw new Error('Object name is required for OpenAI object generation.');
const openaiClient = getClient(apiKey, baseUrl);
try {
const result = await generateObject({
model: openaiClient(modelId),
schema: schema,
messages: messages,
mode: 'tool',
maxTokens: maxTokens,
temperature: temperature
});
log(
'debug',
`OpenAI generateObject completed successfully for model: ${modelId}`
);
if (!result || typeof result.object === 'undefined') {
log(
'warn',
'OpenAI generateObject response did not contain expected object.',
{ result }
);
throw new Error('Failed to extract object from OpenAI response.');
return createOpenAI({
apiKey,
...(baseURL && { baseURL })
});
} catch (error) {
this.handleError('client initialization', error);
}
return {
object: result.object,
usage: {
inputTokens: result.usage.promptTokens,
outputTokens: result.usage.completionTokens
}
};
} catch (error) {
log(
'error',
`Error in generateOpenAIObject (Model: ${modelId}, Object: ${objectName}): ${error.message}`,
{ error }
);
throw new Error(
`OpenAI API error during object generation: ${error.message}`
);
}
}