UNPKG

@maximai/maxim-js

Version:

Maxim AI JS SDK. Visit https://getmaxim.ai for more info.

251 lines • 10.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const uuid_1 = require("uuid"); const ai_1 = require("ai"); const openai_1 = require("@ai-sdk/openai"); const v3_1 = require("zod/v3"); const dotenv = __importStar(require("dotenv")); const vercel_1 = require("src/lib/logger/vercel"); const maxim_1 = require("src/lib/maxim"); // Load environment variables dotenv.config(); // Initialize Maxim SDK async function initializeMaxim() { const apiKey = process.env["MAXIM_API_KEY"]; const repoId = process.env["MAXIM_LOG_REPO_ID"]; const baseUrl = process.env["MAXIM_BASE_URL"]; if (!apiKey || !repoId) { throw new Error("MAXIM_API_KEY or MAXIM_LOG_REPO_ID is not defined in the environment variables"); } const maxim = new maxim_1.Maxim({ baseUrl, apiKey, debug: true }); const logger = await maxim.logger({ id: repoId, }); if (!logger) { throw new Error("Logger is not available"); } return { maxim, logger }; } // Define a simple tool for testing const getWeatherInfo = (0, ai_1.tool)({ description: "Get current weather information for a city", inputSchema: v3_1.z.object({ city: v3_1.z.string().describe("Name of the city"), unit: v3_1.z.enum(["celsius", "fahrenheit"]).describe("Temperature unit"), }), execute: async ({ city, unit }) => { return { city, temperature: unit === "celsius" ? 18 : 64, humidity: 72, windSpeed: 15, conditions: "Rainy", lastUpdated: new Date().toISOString(), unit, }; }, }); // Helper function to process a single trace async function processTrace(logger, sessionId, conversationHistory, newMessage, traceNumber) { var _a, _b; console.log(`\n${"=".repeat(60)}`); console.log(`Trace ${traceNumber}: "${(_a = newMessage.parts[0]) === null || _a === void 0 ? void 0 : _a.text}"`); console.log("=".repeat(60)); // Combine messages const messages = [...conversationHistory, newMessage]; // Validate UI messages const validatedMessages = await (0, ai_1.validateUIMessages)({ messages }); console.log(`Conversation history: ${conversationHistory.length} messages`); console.log(`New message: "${(_b = newMessage.parts[0]) === null || _b === void 0 ? void 0 : _b.text}"`); // System prompt const systemPrompt = "You are a helpful weather assistant. When asked about weather, use the getWeatherInfo tool to get current conditions."; // Create UI message stream const stream = (0, ai_1.createUIMessageStream)({ execute: async ({ writer: dataStream }) => { var _a; // Convert validated messages to model messages const modelMessages = await (0, ai_1.convertToModelMessages)(validatedMessages, { tools: { getWeatherInfo, }, }); // Log the model messages being passed to the AI SDK console.log(`\nšŸ“¤ Model Messages for Trace ${traceNumber}:`); console.log(JSON.stringify(modelMessages, null, 2)); const wrappedModel = (0, vercel_1.wrapMaximAISDKModel)((0, openai_1.openai)("gpt-5"), logger); // Prepare streamText options const streamTextOptions = { messages: modelMessages, tools: { getWeatherInfo, }, system: systemPrompt, model: wrappedModel, providerOptions: { maxim: { sessionId: sessionId, traceName: `Trace ${traceNumber}: ${(_a = newMessage.parts[0]) === null || _a === void 0 ? void 0 : _a.text.substring(0, 30)}...`, traceTags: { trace_number: traceNumber.toString(), }, }, openai: {}, }, }; // Log the streamText options (excluding the model object) console.log(`\nšŸ“¤ StreamText Options for Trace ${traceNumber}:`); console.log(JSON.stringify({ ...streamTextOptions, model: `[Model: ${wrappedModel.modelId || 'wrapped'}]`, }, null, 2)); // Stream text with Maxim integration const result = (0, ai_1.streamText)(streamTextOptions); // toUIMessageStream() automatically handles tool execution and stream consumption dataStream.merge(result.toUIMessageStream()); }, generateId: () => (0, uuid_1.v4)(), originalMessages: validatedMessages, }); // Convert stream to SSE format const sseStream = stream.pipeThrough(new ai_1.JsonToSseTransformStream()); // Read the stream to verify it works const reader = sseStream.getReader(); let streamContent = ""; let chunkCount = 0; try { while (true) { const { done, value } = await reader.read(); if (done) break; // JsonToSseTransformStream outputs strings directly const chunk = typeof value === "string" ? value : new TextDecoder().decode(value); streamContent += chunk; chunkCount++; // Log first few chunks for debugging if (chunkCount <= 3) { console.log(` Chunk ${chunkCount}:`, chunk.substring(0, 80)); } } } catch (error) { console.error(`Error reading stream for trace ${traceNumber}:`, error); throw error; } finally { reader.releaseLock(); } console.log(` āœ… Trace ${traceNumber} completed: ${chunkCount} chunks, ${streamContent.length} chars`); return { chunkCount, streamLength: streamContent.length }; } // Main test function async function main() { const { logger } = await initializeMaxim(); try { // Create a session for testing const sessionId = (0, uuid_1.v4)(); const session = logger.session({ id: sessionId, name: "UI Message Stream Test Session - Multiple Traces", }); console.log("\n" + "=".repeat(60)); console.log("UI Message Stream Test - Multiple Traces in Session"); console.log("=".repeat(60)); console.log(`Session ID: ${sessionId}`); console.log("\nThis test creates multiple traces in the same session,"); console.log("each with different user inputs, to verify trace isolation."); // Build conversation history incrementally let conversationHistory = []; // Trace 1: Initial greeting const trace1Message = { id: (0, uuid_1.v4)(), role: "user", parts: [{ type: "text", text: "Hello, how are you?" }], }; const trace1Result = await processTrace(logger, sessionId, conversationHistory, trace1Message, 1); // Update conversation history with trace 1 conversationHistory.push(trace1Message); conversationHistory.push({ id: (0, uuid_1.v4)(), role: "assistant", parts: [{ type: "text", text: "I'm doing well, thank you! How can I help you today?" }], }); // Trace 2: Weather question for San Francisco const trace2Message = { id: (0, uuid_1.v4)(), role: "user", parts: [{ type: "text", text: "What's the weather in San Francisco?" }], }; const trace2Result = await processTrace(logger, sessionId, conversationHistory, trace2Message, 2); // Update conversation history with trace 2 conversationHistory.push(trace2Message); conversationHistory.push({ id: (0, uuid_1.v4)(), role: "assistant", parts: [{ type: "text", text: "The weather in San Francisco is currently rainy with a temperature of 18°C." }], }); // Summary console.log("\n" + "=".repeat(60)); console.log("Test Summary"); console.log("=".repeat(60)); console.log(`Total traces created: 2`); console.log(`Trace 1 chunks: ${trace1Result.chunkCount}, length: ${trace1Result.streamLength}`); console.log(`Trace 2 chunks: ${trace2Result.chunkCount}, length: ${trace2Result.streamLength}`); // End session session.end(); await logger.cleanup(); console.log("\nāœ… Test completed successfully!"); console.log("\nšŸ“Š Verification Checklist:"); console.log(" āœ“ Check Maxim dashboard - session should contain 2 traces"); console.log(" āœ“ Each trace should have its own unique input:"); console.log(" - Trace 1: 'Hello, how are you?'"); console.log(" - Trace 2: 'What's the weather in San Francisco?'"); console.log(" āœ“ Verify that traces do NOT show duplicate inputs"); console.log(" āœ“ Each trace should only contain its own user message, not previous ones"); } catch (error) { console.error("Error in UI message stream test:", error); throw error; } finally { await logger.cleanup(); } } // Run the test main().catch((error) => { console.error("Fatal error:", error); process.exit(1); }); //# sourceMappingURL=ui_message_stream_test.js.map