Skip to content

Repository files navigation

WhenM

English | 日本語

CInpm versionLicense: MIT

Temporal memory system that understands when things happened, not just what happened

What is WhenM?

WhenM is a schemaless temporal memory system that gives AI applications the ability to understand time, state changes, and causality. Unlike traditional databases or RAG systems, WhenM natively understands that facts change over time.

Core Difference from RAG

AspectRAGWhenM
Time Understanding❌ None✅ Native temporal reasoning
State Changes❌ Can't track✅ Tracks all transitions
Contradictions❌ Returns all versions✅ Resolves by timeline
Schema⚠️ Predefined✅ Completely schemaless
Query"What is X?""What was X at time Y?"

Quick Start

# Install
npm install @aid-on/whenm
# Setup (copy and edit .env)
cp .env.example .env
import{WhenM}from'@aid-on/whenm';// Initialize (uses mock LLM by default, or your API keys from .env)constmemory=awaitWhenM.auto();// Or explicitly use mock for testingconstmemory=awaitWhenM.mock();// Or use Groq (recommended for production)constmemory=awaitWhenM.groq(process.env.GROQ_API_KEY// Get from https://console.groq.com/keys);// Remember events - any language, any domainawaitmemory.remember("Alice joined as engineer","2020-01-15");awaitmemory.remember("Alice became team lead","2022-06-01");awaitmemory.remember("Pikachu learned Thunderbolt","2023-01-01");// Ask temporal questionsawaitmemory.ask("What was Alice's role in 2021?");// → "engineer"awaitmemory.ask("What is Alice's current role?");// → "team lead"awaitmemory.ask("When did Pikachu learn Thunderbolt?");// → "January 1, 2023"

Key Features

🌍 Truly Schemaless

No schemas, no configuration, no entity definitions. WhenM understands any concept in any language through LLM integration.

// Gaming domainawaitmemory.remember("Mario collected a fire flower","2024-01-01");// Cooking domain awaitmemory.remember("Added salt to the soup","2024-02-01");// Business domainawaitmemory.remember("Tanaka became director","2024-03-01");// All work without any setup!

⏰ Temporal Reasoning

Built on formal Event Calculus, providing mathematically sound temporal logic for natural language queries about time and state changes.

🌐 Any Language, Any Domain

The query refinement layer automatically handles multiple languages and domains.

// Japanese exampleawaitmemory.remember("Pikachu learned Thunderbolt");// Spanish exampleawaitmemory.remember("El gato subió al árbol");// English with emojisawaitmemory.remember("🚀 launched to Mars");

Installation

npm install @aid-on/whenm

Usage

Basic Setup

import{WhenM}from'@aid-on/whenm';// Simple string format (provider:apikey)constmemory=awaitWhenM.create('groq:your-api-key');// With model specificationconstmemory=awaitWhenM.create('groq:your-api-key:llama-3.3-70b-versatile');// Unified config objectconstmemory=awaitWhenM.create({provider: 'groq',apiKey: process.env.GROQ_API_KEY,model: 'llama-3.3-70b-versatile'});// Provider-specific helpersconstmemory=awaitWhenM.groq(process.env.GROQ_API_KEY);constmemory=awaitWhenM.gemini(process.env.GEMINI_API_KEY);constmemory=awaitWhenM.cloudflare({apiKey: process.env.CLOUDFLARE_API_KEY,accountId: process.env.CLOUDFLARE_ACCOUNT_ID,email: process.env.CLOUDFLARE_EMAIL});

Recording Events

// Simple eventawaitmemory.remember("Project started","2024-01-01");// Complex state changeawaitmemory.remember("Bob promoted to manager","2024-06-01");// Multilingual supportawaitmemory.remember("Experiment succeeded","2024-07-01");

Querying

// Natural language queriesawaitmemory.ask("What happened in January?");awaitmemory.ask("Who became manager this year?");awaitmemory.ask("What is the current status of the project?");// All queries use natural language through the ask() methodconstevents=awaitmemory.ask("What did Alice do between January and December 2024?");conststatusInMarch=awaitmemory.ask("What was Project-X status on March 15, 2024?");constrecentChanges=awaitmemory.ask("What happened with Project-X in the last 30 days?");

Advanced Features

Query Refinement Layer

WhenM includes a sophisticated refinement layer that standardizes queries across languages:

// These all work seamlessly:awaitmemory.ask("What is Alice's role?");awaitmemory.ask("What is Alice's role?");awaitmemory.ask("¿Cuál es el rol de Alice?");

Enable Query Refinement

For better multilingual support:

constmemory=awaitWhenM.cloudflare({accountId: process.env.CLOUDFLARE_ACCOUNT_ID,apiKey: process.env.CLOUDFLARE_API_KEY,email: process.env.CLOUDFLARE_EMAIL,enableRefiner: true// Enable multilingual query refinement});

Persistence (Plugin System) - 🧪 EXPERIMENTAL

⚠️Note: The persistence feature is experimental and has not been fully tested in production. Use with caution.

WhenM provides a pluggable persistence layer for durable storage:

Memory Persistence (Default)

// Default - events stored in memory onlyconstmemory=awaitWhenM.cloudflare(config);

D1 Database Persistence

// Cloudflare D1 for durable storageconstmemory=awaitWhenM.cloudflare({accountId: process.env.CLOUDFLARE_ACCOUNT_ID,apiKey: process.env.CLOUDFLARE_API_KEY,email: process.env.CLOUDFLARE_EMAIL,persistenceType: 'd1',persistenceOptions: {database: env.DB,// D1 database bindingtableName: 'whenm_events',// Optional: custom table namenamespace: 'my-app'// Optional: namespace for multi-tenancy}});// Save current stateawaitmemory.persist();// Restore from databaseawaitmemory.restore();// Restore with filtersawaitmemory.restore({timeRange: {from: '2024-01-01',to: '2024-12-31'},limit: 1000});// Check persistence statsconststats=awaitmemory.persistenceStats();console.log(`Total persisted events: ${stats.totalEvents}`);

Custom Persistence Plugin

// Implement your own persistenceclassMyCustomPersistence{asyncsave(event){/* ... */}asyncload(query){/* ... */}asyncstats(){/* ... */}// ... other required methods}constmemory=awaitWhenM.cloudflare({// ... configpersistenceType: 'custom',persistenceOptions: newMyCustomPersistence()});

Persistence API

// Core persistence methodsawaitmemory.persist();// Save all events to storageawaitmemory.restore();// Load all events from storageawaitmemory.restore({limit: 100});// Load with query filtersconststats=awaitmemory.persistenceStats();// Get storage statistics// Export/Import Prolog formatconstprolog=awaitmemory.exportProlog();awaitmemory.importProlog(prolog);

Architecture

WhenM combines three powerful technologies:

  1. Event Calculus - Formal temporal logic for reasoning about time
  2. Trealla Prolog - High-performance logical inference engine (WASM)
  3. LLM Integration - Natural language understanding without schemas

Data Flow: How It Works

The system processes information through 5 stages:

Input → Language Normalization → Semantic Decomposition → Temporal Logic → Response

Example: Recording an Event

Input:

awaitmemory.remember("Taro became manager","2024-03-01");

Stage 1: Language Normalization

{
"original": "Taro became manager",
"language": "ja",
"refined": "Taro became manager",
"entities": ["Taro"]
}

Stage 2: Semantic Analysis (LLM)

{
"subject": "taro",
"verb": "became",
"object": "manager",
"temporalType": "STATE_UPDATE",
"affectedFluent": {
"domain": "role", // Dynamically determined"value": "manager",
"isExclusive": true// Only one role at a time
}
}

Stage 3: Prolog Facts Generation

event_fact("evt_1234", "taro", "became", "manager").happens("evt_1234", 1709251200000).initiates("evt_1234", role("taro", "manager")).is_exclusive_domain(role).

Example: Querying Information

Input:

awaitmemory.ask("What is Taro's current role?");

Prolog Query:

current_state("taro", role, Value)

Event Calculus Processing:

  • Finds latest initiates("evt_1234", role("taro", "manager"))
  • Checks no newer role changes exist (clipping check)
  • Returns: Value = "manager"

True Schemaless Design

Traditional systems require predefined schemas:

// ❌ Hardcoded approachif(verb==="became")domain="role";if(verb==="learned")domain="skill";

WhenM dynamically understands any concept:

// ✅ Dynamic understanding"Pikachu learned Thunderbolt"{domain: "skill",value: "thunderbolt",isExclusive: false}"Robot battery at 80%"{domain: "battery",value: "80",isExclusive: true}"Alien transformed into energy"{domain: "form",value: "energy",isExclusive: true}

The LLM determines the semantic meaning, domain, and exclusivity rules dynamically, enabling the system to handle any new concept without code changes.

Performance

  • Insert Speed: 25,000+ events/second
  • Query Speed: 1-30ms for typical queries
  • Memory: Optimized for edge (runs in Cloudflare Workers)
  • Languages: Any human language supported

Use Cases

🏢 Employee Performance & Career Tracking

consthr=awaitWhenM.cloudflare(config);// Track career progression with full contextawaithr.remember("Sarah joined as Junior Developer","2021-01-15");awaithr.remember("Sarah completed React certification","2021-06-20");awaithr.remember("Sarah led the payment module project","2021-09-01");awaithr.remember("Sarah promoted to Senior Developer","2022-01-15");awaithr.remember("Sarah became Tech Lead","2023-06-01");// Temporal performance queriesconstreview=awaithr.ask("What achievements led to Sarah's promotion to Senior?");// → "Completed React certification and successfully led payment module project"// Compare growth between employeesconstsarahGrowth=awaithr.ask("How did Sarah's career progress from January 2021 to January 2024?");constjohnGrowth=awaithr.ask("How did John's career progress from January 2021 to January 2024?");// → Career progression comparison// Find high performersconstfastGrowth=awaithr.ask("Who was promoted, awarded, or recognized in the last 12 months?");// → List of employees with recent achievements

🏥 Patient Medical History & Treatment Evolution

constmedical=awaitWhenM.cloudflare(config);// Complex medical timelineawaitmedical.remember("Patient diagnosed with hypertension","2020-03-15");awaitmedical.remember("Started lisinopril 10mg daily","2020-03-20");awaitmedical.remember("Blood pressure improved to 130/80","2020-06-15");awaitmedical.remember("Developed dry cough side effect","2020-09-01");awaitmedical.remember("Switched to losartan 50mg","2020-09-05");awaitmedical.remember("Blood pressure stabilized to normal","2021-01-15");// Multilingual support// Critical temporal queries for treatment decisionsconstcurrentMeds=awaitmedical.ask("What medication is the patient currently taking?");// → Current medication and conditionsconstmedicationHistory=awaitmedical.ask("Why was the medication changed in September 2020?");// → "Lisinopril caused dry cough side effect, switched to losartan"// Track treatment effectiveness over timeconstbpHistory=awaitmedical.ask("What were the blood pressure measurements in the last 6 months?");// → Blood pressure trends for treatment evaluation

🤖 AI Agent Memory & Learning System

constagent=awaitWhenM.cloudflare(config);// Agent learns and adapts over timeawaitagent.remember("User prefers TypeScript over JavaScript","2024-01-01");awaitagent.remember("User works in Tokyo timezone","2024-01-05");awaitagent.remember("User dislikes verbose explanations","2024-01-10");awaitagent.remember("Failed to solve bug with approach A","2024-02-01");awaitagent.remember("Successfully solved bug with approach B","2024-02-01");// Context-aware responses based on temporal memoryconstpreferences=awaitagent.ask("What are the user's preferences?");// → All current user preferences and learned patternsconstdebugging=awaitagent.ask("What debugging approach should I try?");// → "Use approach B, as approach A previously failed"// Learn from interaction patternsconstinteractions=awaitagent.ask("What failed, succeeded, or errored in the last 30 days?");// → Analyze success/failure patterns to improve

📊 Real-time Incident Management & RCA

constops=awaitWhenM.cloudflare(config);// Track incident timelineawaitops.remember("CPU usage spiked to 95%","2024-03-15 14:30");awaitops.remember("Database connection pool exhausted","2024-03-15 14:31");awaitops.remember("API response time degraded to 5s","2024-03-15 14:32");awaitops.remember("Deployed hotfix PR #1234","2024-03-15 14:45");awaitops.remember("System recovered","2024-03-15 14:50");// Root cause analysis with temporal reasoningconstrca=awaitops.ask("What caused the API degradation?");// → "CPU spike led to connection pool exhaustion, causing API degradation"// Pattern detection across incidentsconstpatterns=awaitops.ask("What spiked, exhausted, or degraded in the last 90 days?");// → Identify recurring issues// Automated incident correlationconstcorrelation=awaitops.ask("What happened with the system between 2:00 PM and 3:00 PM on March 15, 2024?");// → Complete incident timeline for postmortem

💰 Financial Audit Trail & Compliance

constaudit=awaitWhenM.cloudflare(config);// Maintain complete audit trailawaitaudit.remember("Account opened by John","2023-01-15");awaitaudit.remember("KYC verification completed","2023-01-16");awaitaudit.remember("$50,000 deposited from Chase Bank","2023-02-01");awaitaudit.remember("Flagged for unusual activity","2023-03-15");awaitaudit.remember("Manual review cleared","2023-03-16");awaitaudit.remember("Account upgraded to Premium","2023-06-01");// Compliance queriesconstkycStatus=awaitaudit.ask("Was KYC completed before the first transaction?");// → "Yes, KYC completed on Jan 16, first transaction on Feb 1"// Suspicious activity trackingconstflagged=awaitaudit.ask("What was flagged, suspended, or investigated in 2023?");// → All compliance events for regulatory reporting// Account state at any point for legal inquiriesconstsnapshot=awaitaudit.ask("What was the account status on March 15, 2023?");// → Exact account state when flagged

🎮 Game State & Player Progression

constgame=awaitWhenM.cloudflare(config);// Rich player historyawaitgame.remember("Player discovered hidden dungeon","2024-01-01 10:00");awaitgame.remember("Player defeated Dragon Boss","2024-01-01 11:30");awaitgame.remember("Player earned 'Dragon Slayer' title","2024-01-01 11:31");awaitgame.remember("Player joined guild 'Knights'","2024-01-02");awaitgame.remember("Won guild battle","2024-01-03");// Multilingual support// Personalized gameplay based on historyconstachievements=awaitgame.ask("What titles and skills does the player have?");// → All titles, skills, and progression// Quest eligibility based on temporal conditionsconsteligible=awaitgame.ask("Can player start the 'Ancient Evil' quest?");// → "Yes, player has defeated Dragon Boss and joined a guild"// Leaderboard with time-based scoringconstweeklyChamps=awaitgame.ask("Who defeated bosses, completed quests, or won battles in the last 7 days?");// → This week's most active players

🏭 IoT Sensor Network & Predictive Maintenance

constiot=awaitWhenM.cloudflare(config);// Continuous sensor monitoringawaitiot.remember("Machine-A vibration increased to 0.8mm/s","2024-03-01");awaitiot.remember("Machine-A temperature at 75°C","2024-03-02");awaitiot.remember("Machine-A bearing noise detected","2024-03-03");awaitiot.remember("Machine-A scheduled maintenance","2024-03-05");awaitiot.remember("Machine-A bearing replaced","2024-03-05");// Predictive maintenance queriesconstwarning=awaitiot.ask("What signs preceded the bearing failure?");// → "Vibration increased, temperature rose, then noise detected"// Pattern recognition across fleetconstmaintenance=awaitiot.ask("What increased, was detected, or failed in the last 30 days?");// → Identify machines showing similar patterns// Optimal maintenance schedulingconstmachineState=awaitiot.ask("How did Machine-A's condition change from February to March 2024?");// → Degradation rate for maintenance planning

API Reference

Core Methods

memory.remember(event: string, date?: string | Date)

Records an event at a specific time.

memory.ask(question: string)

Answers questions using temporal reasoning. This is the primary interface for all queries.

memory.remember(event: string, date?: string | Date)

Records an event at a specific time.

Query Interface

All queries are performed through natural language using the ask() method:

// Temporal queriesawaitmemory.ask("What happened in January 2024?");awaitmemory.ask("What is Alice's current role?");awaitmemory.ask("When did Bob learn Python?");awaitmemory.ask("Who joined the company last year?");// State queriesawaitmemory.ask("What skills does Alice have?");awaitmemory.ask("Where does Bob currently work?");// Historical queriesawaitmemory.ask("What was the status on March 15?");awaitmemory.ask("How did things change between February and April?");// Complex queriesawaitmemory.ask("Who was promoted in the last 12 months?");awaitmemory.ask("What failures occurred before the system recovery?");

The LLM-powered query system understands:

  • Temporal relationships (before, after, during, between)
  • State transitions (became, changed, updated)
  • Current vs historical states
  • Aggregations (who, what, when, how many)
  • Causal relationships (why, what caused)

Requirements

  • Node.js 18+
  • LLM Provider API credentials (required - one of the following):
    • Cloudflare AI (account ID, API key, email)
    • Groq API key
    • Google Gemini API key

Environment Variables

# Cloudflare AI
CLOUDFLARE_ACCOUNT_ID=your_account_id
CLOUDFLARE_API_KEY=your_api_key
CLOUDFLARE_EMAIL=your_email
# Or Groq
GROQ_API_KEY=your_groq_key
# Or Gemini
GEMINI_API_KEY=your_gemini_key

Testing

# Run unit tests only (fast)
npm run test:unit
# Run integration tests only (requires API keys or uses mock)
npm run test:integration
# Run all tests
npm run test:all
# Run tests with coverage
npm run test:coverage
# Watch mode for development
npm run test:watch

Roadmap

Upcoming Features

  • Query Builder API: Structured query interface (currently all queries use natural language)
  • Timeline API: Dedicated timeline tracking and analysis
  • Advanced Persistence: Production-ready storage backends
  • Performance Optimizations: Faster Prolog integration
  • Extended Language Support: More LLM providers

License

MIT © Aid-On

Credits

WhenM stands on the shoulders of giants:

Core Technologies

  • Trealla Prolog - WebAssembly-powered Prolog engine providing the logical reasoning foundation
  • Event Calculus - Formal temporal logic framework for rigorous time-based reasoning
  • @aid-on/unillm - Unified LLM interface enabling seamless multi-provider support

Special Thanks

  • The Trealla Prolog team for their excellent WASM implementation
  • The Event Calculus research community for decades of temporal logic advancement
  • The Aid-On team for continuous support and innovation

Releases

Packages

Contributors

Languages