// src/scripts/image.ts import { config } from 'dotenv'; config(); import { HumanMessage, AIMessage, BaseMessage } from '@langchain/core/messages'; import type { RunnableConfig } from '@langchain/core/runnables'; import type * as t from '@/types'; import { ChatModelStreamHandler, createContentAggregator } from '@/stream'; import { ToolEndHandler, ModelEndHandler, createMetadataAggregator, } from '@/events'; // @ts-expect-error — example module not in current codebase import { fetchRandomImageTool, fetchRandomImageURL } from '@/tools/example'; import { getLLMConfig } from '@/utils/llmConfig'; import { getArgs } from '@/scripts/args'; import { GraphEvents } from '@/common'; import { Run } from '@/run'; const conversationHistory: BaseMessage[] = []; async function testCodeExecution(): Promise { const { userName, location, provider, currentDate } = await getArgs(); const { contentParts, aggregateContent } = createContentAggregator(); const customHandlers = { [GraphEvents.TOOL_END]: new ToolEndHandler(), [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(), [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(), [GraphEvents.ON_RUN_STEP_COMPLETED]: { handle: ( event: GraphEvents.ON_RUN_STEP_COMPLETED, data: t.StreamEventData ): void => { console.log('====== ON_RUN_STEP_COMPLETED ======'); console.dir(data, { depth: null }); aggregateContent({ event, data: data as unknown as { result: t.ToolEndEvent }, }); }, }, [GraphEvents.ON_RUN_STEP]: { handle: ( event: GraphEvents.ON_RUN_STEP, data: t.StreamEventData ): void => { console.log('====== ON_RUN_STEP ======'); console.dir(data, { depth: null }); aggregateContent({ event, data: data as t.RunStep }); }, }, [GraphEvents.ON_RUN_STEP_DELTA]: { handle: ( event: GraphEvents.ON_RUN_STEP_DELTA, data: t.StreamEventData ): void => { console.log('====== ON_RUN_STEP_DELTA ======'); console.dir(data, { depth: null }); aggregateContent({ event, data: data as t.RunStepDeltaEvent }); }, }, [GraphEvents.ON_MESSAGE_DELTA]: { handle: ( event: GraphEvents.ON_MESSAGE_DELTA, data: t.StreamEventData ): void => { console.log('====== ON_MESSAGE_DELTA ======'); console.dir(data, { depth: null }); aggregateContent({ event, data: data as t.MessageDeltaEvent }); }, }, [GraphEvents.TOOL_START]: { handle: ( _event: string, data: t.StreamEventData, metadata?: Record ): void => { console.log('====== TOOL_START ======'); console.dir(data, { depth: null }); }, }, }; const llmConfig = getLLMConfig(provider); const run = await Run.create({ runId: 'message-num-1', graphConfig: { type: 'standard', llmConfig, tools: [fetchRandomImageTool], // tools: [fetchRandomImageURL], instructions: 'You are a friendly AI assistant with internet capabilities. Always address the user by their name.', additional_instructions: `The user's name is ${userName} and they are located in ${location}.`, }, returnContent: true, skipCleanup: true, customHandlers, }); const config: Partial & { version: 'v1' | 'v2'; run_id?: string; streamMode: string; } = { configurable: { provider, thread_id: 'conversation-num-1', }, streamMode: 'values', version: 'v2' as const, }; console.log('Fetch Random Image'); const userMessage1 = `Hi ${userName} here. Please get me 2 random images. Describe them after you receive them.`; conversationHistory.push(new HumanMessage(userMessage1)); let inputs = { messages: conversationHistory, }; const finalContentParts1 = await run.processStream(inputs, config); const finalMessages1 = run.getRunMessages(); if (finalMessages1) { conversationHistory.push(...finalMessages1); } console.log('\n\n====================\n\n'); console.dir(contentParts, { depth: null }); console.log('Test 2: Follow up with another message'); const userMessage2 = `thanks, you're the best!`; conversationHistory.push(new HumanMessage(userMessage2)); inputs = { messages: conversationHistory, }; const finalContentParts2 = await run.processStream(inputs, config, { keepContent: true, }); const finalMessages2 = run.getRunMessages(); if (finalMessages2) { conversationHistory.push(...finalMessages2); } console.log('\n\n====================\n\n'); console.dir(contentParts, { depth: null }); const { handleLLMEnd, collected } = createMetadataAggregator(); const titleResult = await run.generateTitle({ provider, inputText: userMessage2, contentParts, chainOptions: { callbacks: [ { handleLLMEnd, }, ], }, }); console.log('Generated Title:', titleResult); console.log('Collected metadata:', collected); } process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); console.log('Conversation history:'); console.dir(conversationHistory, { depth: null }); process.exit(1); }); testCodeExecution().catch((err) => { console.error(err); console.log('Conversation history:'); console.dir(conversationHistory, { depth: null }); process.exit(1); });