UNPKG

gaunt-sloth-assistant

Version:

[![Tests and Lint](https://github.com/Galvanized-Pukeko/gaunt-sloth-assistant/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/Galvanized-Pukeko/gaunt-sloth-assistant/actions/workflows/unit-tests.yml) [![Integration Tests](https://github.co

104 lines 4.62 kB
import { GthLangChainAgent } from '#src/core/GthLangChainAgent.js'; import { executeHooks } from '#src/utils.js'; import { getNewRunnableConfig } from '#src/llmUtils.js'; import { initDebugLogging, debugLog, debugLogError, debugLogObject } from '#src/debugUtils.js'; /** * Agent simplifies interaction with LLM and reduces it to calling a few methods * {@link GthAgentRunner#init} and {@link GthAgentRunner#processMessages}. */ export class GthAgentRunner { statusUpdate; agent = null; config = null; runConfig = null; constructor(statusUpdate) { this.statusUpdate = statusUpdate; } /** * Init is split into a separate method. This may create a number of connections, * and we'd better have an instance by that moment, for the case things will go wrong, * so we can wrap init into try-catch and then call {@link #cleanup} within finally. */ async init(command, configIn, checkpointSaver) { this.config = configIn; // Initialize debug logging initDebugLogging(configIn.debugLog ?? false); debugLog(`Initializing GthAgentRunner with command: ${command || 'default'}`); this.runConfig = this.config.hooks?.createRunnableConfig ? await this.config.hooks.createRunnableConfig(this.config) : getNewRunnableConfig(); debugLogObject('Runnable Config', this.runConfig); this.agent = this.config.hooks?.createAgent ? await this.config.hooks?.createAgent(this.config) : new GthLangChainAgent(this.statusUpdate); // Call before init hook debugLog('Executing beforeAgentInit hooks...'); await executeHooks(this.config.hooks?.beforeAgentInit, this); // Initialize the agent debugLog('Initializing agent...'); await this.agent.init(command, configIn, checkpointSaver); // Call after init hook debugLog('Executing afterAgentInit hooks...'); await executeHooks(this.config.hooks?.afterAgentInit, this); debugLog('Agent initialization complete'); } /** * processMessages deals with both streaming and non-streaming approaches. */ async processMessages(messages) { if (!this.agent || !this.config || !this.runConfig) { throw new Error('AgentRunner not initialized. Call init() first.'); } debugLog('Processing messages...'); debugLogObject('Input Messages', messages); await executeHooks(this.config.hooks?.beforeProcessMessages, this, messages, this.runConfig); try { // Decision: Use streaming or non-streaming based on config if (this.config.streamOutput) { // Use streaming debugLog('Using streaming mode'); const stream = await this.agent.stream(messages, this.runConfig); let result = ''; try { for await (const chunk of stream) { debugLogObject('Stream chunk', chunk); result += chunk; } } catch (streamError) { // Handle streaming-specific errors debugLogError('Stream processing', streamError); throw new Error(`Stream processing failed: ${streamError instanceof Error ? streamError.message : String(streamError)}`); } debugLog(`Stream completed. Total response length: ${result.length}`); return result; } else { // Use non-streaming debugLog('Using non-streaming mode'); const result = await this.agent.invoke(messages, this.runConfig); debugLog(`Non-stream response length: ${result.length}`); return result; } } catch (error) { // Handle agent invocation errors debugLogError('Agent processing', error); throw new Error(`Agent processing failed: ${error instanceof Error ? error.message : String(error)}`); } } // noinspection JSUnusedGlobalSymbols getAgent() { return this.agent; } async cleanup() { debugLog('Cleaning up GthAgentRunner...'); if (this.agent && 'cleanup' in this.agent && typeof this.agent.cleanup === 'function') { await this.agent.cleanup(); } this.agent = null; this.config = null; debugLog('GthAgentRunner cleanup complete'); } } //# sourceMappingURL=GthAgentRunner.js.map