@just-every/task
Version:
Task - Thoughtful Task Loop
179 lines (154 loc) • 7.6 kB
text/typescript
/**
* Full Metamemory Demonstration
*
* This example shows a complete conversation with multiple topics
* and demonstrates how metamemory tracks, categorizes, and compacts them.
*/
import { Agent } from '@just-every/ensemble';
import {
runTask,
getCompactedHistory,
configureMetamemory,
setMetamemoryEnabled,
addMessageToTask,
type TaskEvent
} from '../index.js';
async function demonstrateMetamemory() {
console.log('=== Full Metamemory Demonstration ===\n');
// Configure metamemory with specific settings
configureMetamemory({
windowSize: 10, // Analyze last 10 messages
processInterval: 3, // Process every 3 messages
threadInactivityTimeout: 30000, // 30 seconds for demo
compactionThresholds: {
core: 100, // Always preserve
active: 80, // Preserve if score >= 80
complete: 60, // Summarize if score < 60
ephemeral: 20 // Almost always summarize
}
});
// Enable metamemory
setMetamemoryEnabled(true);
// Create an agent with access to task completion tools
const agent = new Agent({
name: 'MetamemoryDemoAgent',
modelClass: 'standard',
instructions: `You are a helpful assistant engaged in a multi-topic conversation.
Help the user with their requests. When a topic is clearly finished, acknowledge it.
Only use task_complete when the user explicitly says they are done with all topics.`
});
// Start the conversation with multiple topics
console.log('Starting multi-topic conversation...\n');
let finalState: TaskEvent['finalState'] | undefined;
const task = runTask(agent, `Hi! I'd like to have a conversation about several topics today:
1. First, can you briefly explain what recursion is in programming?
2. After that, I'd like some healthy breakfast ideas.
3. Finally, I need help planning a weekend trip to Paris.
Let's start with recursion.`, {
metamemoryEnabled: true
});
let messageCount = 0;
// Process the task
for await (const event of task) {
if (event.type === 'content') {
process.stdout.write(event.content);
} else if (event.type === 'response_output') {
messageCount++;
console.log(`\n\n[Message ${messageCount} processed by metamemory]\n`);
// Simulate user responses at key points
if (messageCount === 1) {
// After recursion explanation
console.log("\n--- USER: Great explanation! Now let's move on to breakfast ideas. ---\n");
addMessageToTask(task, {
type: 'message',
role: 'user',
content: "Great explanation! Now let's move on to breakfast ideas. I'm looking for something healthy and quick to prepare."
});
} else if (messageCount === 3) {
// After breakfast ideas
console.log("\n--- USER: Those breakfast ideas sound delicious! Now about Paris... ---\n");
addMessageToTask(task, {
type: 'message',
role: 'user',
content: "Those breakfast ideas sound delicious! Now let's plan that Paris trip. I have 3 days and I'm interested in art and food."
});
} else if (messageCount === 5) {
// After Paris suggestions
console.log("\n--- USER: Perfect! That covers everything I needed. ---\n");
addMessageToTask(task, {
type: 'message',
role: 'user',
content: "Perfect! That covers everything I needed. Thank you for your help with all three topics. I'm done for now."
});
}
} else if (event.type === 'task_complete') {
finalState = event.finalState;
console.log('\n\n=== Task Completed ===');
console.log('Result:', event.result);
} else if (event.type === 'task_fatal_error') {
console.error('\nTask failed:', event.result);
finalState = event.finalState;
}
}
// Analyze metamemory state
if (finalState?.metamemoryEnabled && finalState.metamemoryState) {
console.log('\n\n=== Metamemory Analysis ===\n');
const state = finalState.metamemoryState;
console.log(`Total messages tracked: ${state.metamemory.size}`);
console.log(`Threads identified: ${state.threads.size}`);
// Show thread details
console.log('\n--- Thread Details ---');
for (const [threadId, thread] of state.threads) {
console.log(`\nThread: ${thread.name}`);
console.log(` ID: ${threadId}`);
console.log(` Class: ${thread.class}`);
console.log(` Status: ${thread.status}`);
console.log(` Messages: ${thread.messages.length}`);
if (thread.summary) {
console.log(` Summary: ${thread.summary}`);
}
}
// Get compacted history
console.log('\n\n=== Compacting Conversation History ===\n');
const compactionResult = await getCompactedHistory(finalState, {
aggressiveMode: false,
targetTokenCount: 500 // Aim for a compact representation
});
if (compactionResult) {
console.log(`Original messages: ${compactionResult.metadata.originalCount}`);
console.log(`Compacted messages: ${compactionResult.metadata.compactedCount}`);
console.log(`Reduction: ${Math.round((1 - compactionResult.metadata.compactedCount / compactionResult.metadata.originalCount) * 100)}%`);
console.log(`\nThreads preserved: ${compactionResult.metadata.threadsPreserved.join(', ') || 'None'}`);
console.log(`Threads summarized: ${compactionResult.metadata.threadsSummarized.join(', ') || 'None'}`);
console.log('\n--- Compacted History ---\n');
compactionResult.messages.forEach((msg, idx) => {
console.log(`[${idx + 1}] ${msg.role.toUpperCase()}${msg.isCompacted ? ' (COMPACTED)' : ''}:`);
console.log(` ${msg.content}\n`);
});
}
// Demonstrate resuming with compacted history
console.log('\n\n=== Resuming with Compacted History ===\n');
console.log('Now asking the agent to summarize what we discussed...\n');
const resumedTask = runTask(agent, 'Can you briefly summarize the three topics we just discussed?', {
messages: finalState.messages,
metamemoryEnabled: true,
metamemoryState: finalState.metamemoryState
});
for await (const event of resumedTask) {
if (event.type === 'content') {
process.stdout.write(event.content);
} else if (event.type === 'task_complete') {
console.log('\n\n--- Summary task completed ---');
}
}
} else {
console.log('\nMetamemory was not enabled or no state was captured.');
}
}
// Run the demonstration
console.log('Starting metamemory demonstration...\n');
console.log('This will show how conversations are tracked, categorized, and compacted.\n');
demonstrateMetamemory().catch(error => {
console.error('Error in demonstration:', error);
process.exit(1);
});