donobu
Version:
Create browser automations with an LLM agent and replay them as Playwright scripts.
230 lines • 8.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.VercelAiGptClient = void 0;
const GptClient_1 = require("./GptClient");
const Logger_1 = require("../utils/Logger");
const GptModelNotFoundException_1 = require("../exceptions/GptModelNotFoundException");
const GptPlatformAuthenticationFailedException_1 = require("../exceptions/GptPlatformAuthenticationFailedException");
const GptPlatformInternalErrorException_1 = require("../exceptions/GptPlatformInternalErrorException");
const GptPlatformNotReachableException_1 = require("../exceptions/GptPlatformNotReachableException");
const ai_1 = require("ai");
/**
* A GPT client implemented using the Vercel AI SDK.
*/
class VercelAiGptClient extends GptClient_1.GptClient {
/**
* Create a new instance.
*/
constructor(model) {
super({
type: 'VERCEL_AI',
provider: model.provider,
modelName: model.modelId,
});
this.model = model;
}
async ping() {
try {
await (0, ai_1.generateText)({
model: this.model,
prompt: 'ping',
temperature: 0,
maxTokens: 1,
});
}
catch (error) {
if (error instanceof Error && error.message.includes('not found')) {
throw new GptModelNotFoundException_1.GptModelNotFoundException(this.config.type, this.model.modelId);
}
else {
throw await this.mapErrorToDonobuException(error);
}
}
}
async getMessage(messages) {
try {
const coreMessages = this.convertToCoreMessages(messages);
const result = await (0, ai_1.generateText)({
model: this.model,
messages: coreMessages,
temperature: 0,
});
return {
type: 'assistant',
text: result.text,
promptTokensUsed: result.usage.promptTokens,
completionTokensUsed: result.usage.completionTokens,
};
}
catch (error) {
throw await this.mapErrorToDonobuException(error);
}
}
async getStructuredOutput(messages, jsonSchema) {
try {
const coreMessages = this.convertToCoreMessages(messages);
const result = await (0, ai_1.generateObject)({
model: this.model,
messages: coreMessages,
schema: (0, ai_1.jsonSchema)(jsonSchema),
temperature: 0,
output: 'object',
});
return {
type: 'structured_output',
output: result.object,
promptTokensUsed: result.usage.promptTokens,
completionTokensUsed: result.usage.completionTokens,
};
}
catch (error) {
throw await this.mapErrorToDonobuException(error);
}
}
async getToolCalls(messages, tools) {
try {
const coreMessages = this.convertToCoreMessages(messages);
// Convert ToolOption to Vercel AI SDK Tool format
const vercelTools = {};
for (const tool of tools) {
vercelTools[tool.name] = {
parameters: {
_type: Object,
parse: (value) => value,
jsonSchema: () => tool.inputSchema,
},
description: tool.description,
};
}
// Generate text with tool calls
const result = await (0, ai_1.generateText)({
model: this.model,
messages: coreMessages,
tools: vercelTools,
temperature: 0,
toolChoice: 'required', // Force the model to use a tool
});
// Map the tool calls to the expected format
const proposedCalls = result.toolCalls.map((tc) => {
return {
name: tc.toolName,
parameters: tc.args,
toolCallId: tc.toolCallId,
};
});
return {
type: 'proposed_tool_calls',
proposedToolCalls: proposedCalls,
promptTokensUsed: result.usage.promptTokens,
completionTokensUsed: result.usage.completionTokens,
};
}
catch (error) {
throw await this.mapErrorToDonobuException(error);
}
}
/**
* Convert GptMessage array to CoreMessage array for Vercel AI SDK
*/
convertToCoreMessages(messages) {
return messages.map((msg) => {
const msgType = msg.type;
if (msgType === 'system') {
return {
role: 'system',
content: msg.text,
};
}
if (msgType === 'user') {
// Convert user message items to content
const content = msg.items.length === 1 && msg.items[0].type === 'text'
? msg.items[0].text // If it's just text, use string shorthand
: msg.items.map((item) => {
if (item.type === 'text') {
return {
type: 'text',
text: item.text,
};
}
else if (item.type === 'png') {
// Convert PNG to base64 for image parts
return {
type: 'image',
image: item.bytes,
mimeType: 'image/png',
};
}
throw new Error(`Unsupported user message item type: ${JSON.stringify(item)}`);
});
return {
role: 'user',
content,
};
}
if (msgType === 'assistant') {
return {
role: 'assistant',
content: msg.text,
};
}
if (msgType === 'tool_call_result') {
return {
role: 'tool',
content: [
{
type: 'tool-result',
toolCallId: msg.toolCallId,
toolName: msg.toolName,
result: msg.data,
},
],
};
}
if (msgType === 'proposed_tool_calls') {
// Convert proposed tool calls to assistant message with tool calls
const content = msg.proposedToolCalls.map((tc) => ({
type: 'tool-call',
toolCallId: tc.toolCallId || '',
toolName: tc.name,
args: tc.parameters,
}));
return {
role: 'assistant',
content,
};
}
if (msgType === 'structured_output') {
// Convert structured output to text format
return {
role: 'assistant',
content: JSON.stringify(msg.output, null, 2),
};
}
throw new Error(`Unsupported message type: ${msgType}`);
});
}
/**
* Maps an error to a DonobuException
*/
async mapErrorToDonobuException(error) {
Logger_1.appLogger.error(`Vercel AI SDK error: ${error}`);
if (error instanceof Error) {
// Check for authentication errors
if (error.message.includes('authentication') ||
error.message.includes('unauthorized')) {
return new GptPlatformAuthenticationFailedException_1.GptPlatformAuthenticationFailedException(this.config.type);
}
// Check for connectivity errors
if (error.message.includes('network') ||
error.message.includes('connection')) {
return new GptPlatformNotReachableException_1.GptPlatformNotReachableException(this.config.type);
}
}
// Default to internal error
return new GptPlatformInternalErrorException_1.GptPlatformInternalErrorException(error instanceof Error
? error.message
: 'Unknown error with Vercel AI SDK');
}
}
exports.VercelAiGptClient = VercelAiGptClient;
//# sourceMappingURL=VercelAiGptClient.js.map