const Task = require('../task'); const {TaskPreconditions} = require('../../utils/constants'); const TaskLlmOpenAI_S2S = require('./llms/openai_s2s'); class TaskLlm extends Task { constructor(logger, opts) { super(logger, opts); this.preconditions = TaskPreconditions.Endpoint; ['vendor', 'model', 'auth', 'connectOptions'].forEach((prop) => { this[prop] = this.data[prop]; }); this.eventHandlers = []; // delegate to the specific llm model this.llm = this.createSpecificLlm(); } get name() { return this.llm.name ; } get toolHook() { return this.llm?.toolHook; } get eventHook() { return this.llm?.eventHook; } get ep() { return this.cs.ep; } async exec(cs, {ep}) { await super.exec(cs, {ep}); await this.llm.exec(cs, {ep}); } async kill(cs) { super.kill(cs); await this.llm.kill(cs); } createSpecificLlm() { let llm; switch (this.vendor) { case 'openai': case 'microsoft': if (this.model.startsWith('gpt-4o-realtime')) { llm = new TaskLlmOpenAI_S2S(this.logger, this.data, this); } break; default: throw new Error(`Unsupported vendor ${this.vendor} for LLM`); } if (!llm) { throw new Error(`Unsupported vendor:model ${this.vendor}:${this.model}`); } return llm; } addCustomEventListener(ep, event, handler) { this.eventHandlers.push({ep, event, handler}); ep.addCustomEventListener(event, handler); } removeCustomEventListeners() { this.eventHandlers.forEach((h) => h.ep.removeCustomEventListener(h.event, h.handler)); } async sendEventHook(data) { await this.cs?.requestor.request('llm:event', this.eventHook, data); } async sendToolHook(tool_call_id, data) { await this.cs?.requestor.request('llm:tool-call', this.toolHook, {tool_call_id, ...data}); } async processToolOutput(tool_call_id, data) { if (!this.ep.connected) { this.logger.info('TaskLlm:processToolOutput - no connected endpoint'); return; } this.llm.processToolOutput(this.ep, tool_call_id, data); } async processLlmUpdate(data, callSid) { if (this.ep.connected) { if (typeof this.llm.processLlmUpdate === 'function') { this.llm.processLlmUpdate(this.ep, data, callSid); } else { const {vendor, model} = this.llm; this.logger.info({data, callSid}, `TaskLlm:_processLlmUpdate: LLM ${vendor}:${model} does not support llm:update`); } } } } module.exports = TaskLlm;