|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { HumanMessage, AIMessage, SystemMessage, ToolMessage } from '../../../../src/index.js';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function formatMessage(message, options = {}) {
|
|
|
const maxLength = options.maxLength || 100;
|
|
|
|
|
|
|
|
|
const date = new Date(message.timestamp);
|
|
|
const timestamp = date.toLocaleTimeString('en-US', {
|
|
|
hour12: false,
|
|
|
hour: '2-digit',
|
|
|
minute: '2-digit',
|
|
|
second: '2-digit'
|
|
|
});
|
|
|
|
|
|
|
|
|
const type = message.type.toUpperCase().padEnd(6);
|
|
|
|
|
|
|
|
|
let content = message.content;
|
|
|
if (content.length > maxLength) {
|
|
|
content = content.substring(0, maxLength - 3) + '...';
|
|
|
}
|
|
|
|
|
|
|
|
|
return `[${timestamp}] ${type}: ${content}`;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function formatConversation(messages) {
|
|
|
const separator = 'β'.repeat(60);
|
|
|
const lines = [];
|
|
|
|
|
|
lines.push(separator);
|
|
|
lines.push('CONVERSATION');
|
|
|
lines.push(separator);
|
|
|
|
|
|
messages.forEach((msg) => {
|
|
|
lines.push(formatMessage(msg));
|
|
|
});
|
|
|
|
|
|
lines.push(separator);
|
|
|
|
|
|
return lines.join('\n');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const COLORS = {
|
|
|
reset: '\x1b[0m',
|
|
|
blue: '\x1b[34m',
|
|
|
green: '\x1b[32m',
|
|
|
cyan: '\x1b[36m',
|
|
|
yellow: '\x1b[33m',
|
|
|
gray: '\x1b[90m'
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getColorForType(type) {
|
|
|
const colorMap = {
|
|
|
'system': COLORS.blue,
|
|
|
'human': COLORS.green,
|
|
|
'ai': COLORS.cyan,
|
|
|
'tool': COLORS.yellow
|
|
|
};
|
|
|
return colorMap[type] || COLORS.reset;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function formatMessageWithColor(message, options = {}) {
|
|
|
const maxLength = options.maxLength || 100;
|
|
|
|
|
|
|
|
|
const date = new Date(message.timestamp);
|
|
|
const timestamp = date.toLocaleTimeString('en-US', {
|
|
|
hour12: false,
|
|
|
hour: '2-digit',
|
|
|
minute: '2-digit',
|
|
|
second: '2-digit'
|
|
|
});
|
|
|
const coloredTimestamp = `${COLORS.gray}[${timestamp}]${COLORS.reset}`;
|
|
|
|
|
|
|
|
|
const color = getColorForType(message.type);
|
|
|
const type = message.type.toUpperCase().padEnd(6);
|
|
|
const coloredType = `${color}${type}${COLORS.reset}`;
|
|
|
|
|
|
|
|
|
let content = message.content;
|
|
|
if (content.length > maxLength) {
|
|
|
content = content.substring(0, maxLength - 3) + '...';
|
|
|
}
|
|
|
|
|
|
return `${coloredTimestamp} ${coloredType}: ${content}`;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function formatConversationWithColor(messages) {
|
|
|
const separator = COLORS.gray + 'β'.repeat(60) + COLORS.reset;
|
|
|
const lines = [];
|
|
|
|
|
|
lines.push(separator);
|
|
|
lines.push(`${COLORS.gray}CONVERSATION${COLORS.reset}`);
|
|
|
lines.push(separator);
|
|
|
|
|
|
messages.forEach((msg) => {
|
|
|
lines.push(formatMessageWithColor(msg));
|
|
|
});
|
|
|
|
|
|
lines.push(separator);
|
|
|
|
|
|
return lines.join('\n');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function formatMessageDetailed(message, options = {}) {
|
|
|
const basic = formatMessage(message, options);
|
|
|
|
|
|
|
|
|
const metadata = [];
|
|
|
if (message.id) {
|
|
|
metadata.push(`ID: ${message.id.substring(0, 8)}`);
|
|
|
}
|
|
|
if (message.additionalKwargs && Object.keys(message.additionalKwargs).length > 0) {
|
|
|
metadata.push(`Meta: ${JSON.stringify(message.additionalKwargs)}`);
|
|
|
}
|
|
|
if (message.type === 'ai' && message.hasToolCalls && message.hasToolCalls()) {
|
|
|
metadata.push(`Tools: ${message.toolCalls.length}`);
|
|
|
}
|
|
|
if (message.type === 'tool' && message.toolCallId) {
|
|
|
metadata.push(`CallID: ${message.toolCallId.substring(0, 8)}`);
|
|
|
}
|
|
|
|
|
|
if (metadata.length > 0) {
|
|
|
return `${basic}\n ${COLORS.gray}[${metadata.join(', ')}]${COLORS.reset}`;
|
|
|
}
|
|
|
|
|
|
return basic;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function runTests() {
|
|
|
console.log('π§ͺ Testing Message Formatter Solution...\n');
|
|
|
|
|
|
try {
|
|
|
|
|
|
console.log('Test 1: Basic message formatting');
|
|
|
const msg1 = new HumanMessage("Hello, how are you?");
|
|
|
const formatted1 = formatMessage(msg1);
|
|
|
console.log(` Output: ${formatted1}`);
|
|
|
console.assert(formatted1.includes('HUMAN'), 'Should include message type');
|
|
|
console.assert(formatted1.includes('Hello'), 'Should include content');
|
|
|
console.assert(/\[\d{2}:\d{2}:\d{2}\]/.test(formatted1), 'Should have timestamp');
|
|
|
console.log('β
Basic formatting works\n');
|
|
|
|
|
|
|
|
|
console.log('Test 2: Long message truncation');
|
|
|
const longContent = 'A'.repeat(150);
|
|
|
const msg2 = new AIMessage(longContent);
|
|
|
const formatted2 = formatMessage(msg2, { maxLength: 50 });
|
|
|
console.log(` Original length: 150 chars`);
|
|
|
console.log(` Formatted: ${formatted2.substring(0, 70)}...`);
|
|
|
console.assert(formatted2.includes('...'), 'Should have ellipsis');
|
|
|
console.log('β
Truncation works\n');
|
|
|
|
|
|
|
|
|
console.log('Test 3: Different message types');
|
|
|
const messages = [
|
|
|
new SystemMessage("You are helpful"),
|
|
|
new HumanMessage("Hi"),
|
|
|
new AIMessage("Hello!"),
|
|
|
new ToolMessage("result", "tool_123")
|
|
|
];
|
|
|
|
|
|
messages.forEach(msg => {
|
|
|
const formatted = formatMessage(msg);
|
|
|
console.log(` ${formatted}`);
|
|
|
});
|
|
|
console.log('β
All message types format correctly\n');
|
|
|
|
|
|
|
|
|
console.log('Test 4: Full conversation formatting');
|
|
|
const conversation = [
|
|
|
new SystemMessage("You are a helpful assistant"),
|
|
|
new HumanMessage("What's 2+2?"),
|
|
|
new AIMessage("2+2 equals 4")
|
|
|
];
|
|
|
|
|
|
console.log(formatConversation(conversation));
|
|
|
console.log('β
Conversation formatting works\n');
|
|
|
|
|
|
|
|
|
console.log('Test 5: Colored terminal output');
|
|
|
const coloredMessages = [
|
|
|
new SystemMessage("System message in blue"),
|
|
|
new HumanMessage("Human message in green"),
|
|
|
new AIMessage("AI message in cyan"),
|
|
|
new ToolMessage("Tool message in yellow", "tool_123")
|
|
|
];
|
|
|
|
|
|
console.log(formatConversationWithColor(coloredMessages));
|
|
|
console.log('β
Colored output works\n');
|
|
|
|
|
|
|
|
|
console.log('Test 6: Detailed formatting with metadata');
|
|
|
const msgWithMeta = new HumanMessage("Hello", {
|
|
|
userId: "user_123",
|
|
|
sessionId: "sess_456"
|
|
|
});
|
|
|
const detailed = formatMessageDetailed(msgWithMeta);
|
|
|
console.log(detailed);
|
|
|
console.assert(detailed.includes('Meta:'), 'Should include metadata');
|
|
|
console.log('β
Detailed formatting works\n');
|
|
|
|
|
|
|
|
|
console.log('Test 7: AI message with tool calls');
|
|
|
const aiWithTools = new AIMessage("Let me calculate that", {
|
|
|
toolCalls: [
|
|
|
{ id: 'call_123', type: 'function', function: { name: 'calculator' } }
|
|
|
]
|
|
|
});
|
|
|
const formattedTools = formatMessageDetailed(aiWithTools);
|
|
|
console.log(formattedTools);
|
|
|
console.log('β
Tool call formatting works\n');
|
|
|
|
|
|
|
|
|
console.log('Test 8: Edge cases');
|
|
|
const emptyMsg = new HumanMessage("");
|
|
|
const formatted8 = formatMessage(emptyMsg);
|
|
|
console.log(` Empty message: ${formatted8}`);
|
|
|
|
|
|
const specialChars = new AIMessage("Hello\nWorld\tTest");
|
|
|
const formatted8b = formatMessage(specialChars);
|
|
|
console.log(` Special chars: ${formatted8b}`);
|
|
|
console.log('β
Edge cases handled\n');
|
|
|
|
|
|
|
|
|
console.log('Test 9: Performance test');
|
|
|
const manyMessages = Array.from({ length: 100 }, (_, i) =>
|
|
|
new HumanMessage(`Message ${i}`)
|
|
|
);
|
|
|
|
|
|
const startTime = Date.now();
|
|
|
manyMessages.forEach(msg => formatMessage(msg));
|
|
|
const duration = Date.now() - startTime;
|
|
|
|
|
|
console.log(` Formatted 100 messages in ${duration}ms`);
|
|
|
console.assert(duration < 100, 'Should be fast');
|
|
|
console.log('β
Performance is good\n');
|
|
|
|
|
|
|
|
|
console.log('Test 10: Real conversation example');
|
|
|
const realConversation = [
|
|
|
new SystemMessage("You are a helpful Python tutor."),
|
|
|
new HumanMessage("How do I reverse a string in Python?"),
|
|
|
new AIMessage("You can reverse a string using slicing: text[::-1]"),
|
|
|
new HumanMessage("Can you show me an example?"),
|
|
|
new AIMessage("Sure! Here's an example: 'hello'[::-1] returns 'olleh'"),
|
|
|
new HumanMessage("Thanks!")
|
|
|
];
|
|
|
|
|
|
console.log('\n' + formatConversationWithColor(realConversation));
|
|
|
console.log('\nβ
Real conversation looks great\n');
|
|
|
|
|
|
console.log('π All tests passed!');
|
|
|
console.log('\nπ‘ Key Features Demonstrated:');
|
|
|
console.log(' β’ Timestamp formatting');
|
|
|
console.log(' β’ Message type identification');
|
|
|
console.log(' β’ Content truncation');
|
|
|
console.log(' β’ Terminal colors');
|
|
|
console.log(' β’ Metadata display');
|
|
|
console.log(' β’ Tool call indicators');
|
|
|
} catch (error) {
|
|
|
console.error('β Test failed:', error.message);
|
|
|
console.error(error.stack);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
runTests();
|
|
|
}
|
|
|
|
|
|
export {
|
|
|
formatMessage,
|
|
|
formatConversation,
|
|
|
formatMessageWithColor,
|
|
|
formatConversationWithColor,
|
|
|
formatMessageDetailed
|
|
|
}; |