autodiary
v0.0.1
Published
Memory, Simplified: JSON-Driven, Agent-Approved - TypeScript port of tomldiary
Readme
Autodiary
⚠️ ALPHA RELEASE: This package is in early development. APIs may change without notice. Not recommended for production use.
Memory, Simplified: JSON-Driven, Agent-Approved.
Autodiary is a TypeScript/JavaScript port of tomldiary - a dead-simple, customizable memory system for agentic applications. It stores data in human-readable JSON files so your agents can keep a tidy diary of only the useful stuff.
Key Features
- Human-readable JSON storage – easy to inspect, debug and manage
- Fully customizable – define your own memory schema with TypeScript interfaces
- Smart deduplication – prevents duplicate preferences with fuzzy similarity detection (70% threshold)
- Enhanced limit enforcement – visual indicators and pre-flight checking prevent failed operations
- Force creation mechanism – bypass similarity detection when needed with
id="new"parameter - Minimal overhead – lightweight design, backend agnostic and easy to integrate
- Atomic, safe writes – ensures data integrity with proper file operations
- Powered by Google Gemini 2.5 Flash – uses the AI SDK for intelligent extraction
Installation
Requires Node.js 18+ or Bun
npm install autodiary ai @ai-sdk/google zod fuzzball
# or
bun add autodiary ai @ai-sdk/google zod fuzzballQuick Start
import { DiaryService, JSONFileBackend } from "autodiary";
// Define your preference schema
const MY_PREF_SCHEMA = {
likes: {},
dislikes: {},
allergies: {},
routines: {},
biography: {},
};
const CATEGORIES_DOC = `
likes : What the user enjoys
dislikes : Things user avoids
allergies: Substances causing reactions
routines : User's typical habits
biography: User's personal details
`;
// Create storage backend
const backend = new JSONFileBackend({
rootPath: "./memories",
});
// Create diary service
const diary = new DiaryService({
memoryStore: backend,
schemaName: "MyPrefTable",
allowedCategories: Object.keys(MY_PREF_SCHEMA),
categoriesDoc: CATEGORIES_DOC,
maxPrefsPerCategory: 100,
maxConversations: 50,
});
const userId = "alice";
const sessionId = "session_001";
// Ensure session exists
await diary.ensureSession(userId, sessionId);
// Process a conversation turn
await diary.updateMemory(
userId,
sessionId,
"I'm allergic to walnuts.",
"I'll remember you're allergic to walnuts."
);JSON Memory Example
Preferences File (alice_preferences.json)
{
"_meta": {
"version": "0.3",
"schema_name": "MyPrefTable"
},
"preferences": {
"allergies": {
"pref001": {
"text": "allergic to walnuts",
"contexts": ["diet", "health"],
"_count": 1,
"_created": "2024-01-01T00:00:00Z",
"_updated": "2024-01-01T00:00:00Z",
"_created_by": "session_001",
"_updated_by": "session_001"
}
}
}
}Conversations File (alice_conversations.json)
{
"_meta": {
"version": "0.3",
"schema_name": "MyPrefTable"
},
"conversations": {
"session_001": {
"_created": "2024-01-01T00:00:00Z",
"_updated": "2024-01-01T00:00:00Z",
"_turns": 5,
"summary": "Discussed food preferences and dietary restrictions",
"keywords": ["food", "allergy", "italian"]
}
}
}API Reference
DiaryService
Main class for memory operations:
ensureSession(userId, sessionId): Create session if neededupdateMemory(userId, sessionId, userMsg, assistantMsg): Process and store memorygetPreferences(userId, skipMetadata?): Get user preferences as JSON stringgetLastConversations(userId, limit?, skipMetadata?): Get last N conversation summariesclose(): Cleanup resources
MemoryWriter
Background queue for non-blocking writes:
submit(userId, sessionId, userMessage, assistantResponse): Queue memory updateclose(): Graceful shutdowndrain(): Wait for queue to empty
Storage Backends
JSONFileBackend - Local file storage with atomic writes:
import { JSONFileBackend } from "autodiary";
const backend = new JSONFileBackend({
rootPath: "./memories",
});CloudflareKvBackend - Cloudflare Workers KV storage:
import { CloudflareKvBackend } from "autodiary";
// In Cloudflare Worker
export default {
async fetch(request, env) {
const backend = new CloudflareKvBackend({
kvNamespace: env.AUTODIARY_KV,
keyPrefix: "diary:", // optional, defaults to "autodiary:"
});
const diary = new DiaryService({
memoryStore: backend,
// ... other config
});
// Use diary...
}
}Configuration
Environment Variables
GOOGLE_GENERATIVE_AI_API_KEY: Your Google AI API key
Custom Storage Backend
Implement the MemoryStore interface for other backends (Redis, S3, etc.):
import { MemoryStore, DiaryPreferences, DiaryConversations } from "autodiary";
class MyCustomBackend implements MemoryStore {
async loadPreferences(userId: string): Promise<DiaryPreferences | null> {
// Your implementation
}
async loadConversations(userId: string): Promise<DiaryConversations | null> {
// Your implementation
}
async savePreferences(userId: string, prefs: DiaryPreferences): Promise<void> {
// Your implementation
}
async saveConversations(userId: string, convs: DiaryConversations): Promise<void> {
// Your implementation
}
async close?(): Promise<void> {
// Optional cleanup
}
}Development
# Install dependencies
bun install
# Build
bun run build
# Run example
bun run example
# Run tests
bun testDifferences from tomldiary
- Uses JSON instead of TOML for storage (more native to JavaScript/TypeScript)
- Powered by Google Gemini 2.0 Flash via AI SDK (instead of Pydantic AI)
- TypeScript-first with full type safety
- Compatible with both Bun and Node.js runtimes
License
MIT License - see LICENSE file for details.
Credits
TypeScript port of tomldiary by the same author.
