@maximai/maxim-js
Version:
Maxim AI JS SDK. Visit https://getmaxim.ai for more info.
251 lines ⢠10.7 kB
JavaScript
;
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