-
Notifications
You must be signed in to change notification settings - Fork 15
feat: Add memory system for conversation history management #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Implements a comprehensive memory system for the OpenRouter TypeScript SDK that enables:
- Thread-based conversation management
- Resource (user) management
- Working memory (both thread and resource scoped)
- Auto-injection of conversation history
- Auto-saving of messages
- Serialization/hydration for persistence
- In-memory storage implementation (with interface for future storage backends)
## Key Features
### Core Components
- **Memory**: Main API class for managing threads, resources, and working memory
- **MemoryStorage**: Interface for storage implementations
- **InMemoryStorage**: Default in-memory storage implementation
- **Types**: Comprehensive type definitions for all memory entities
### Auto-Features
- **Auto-inject**: Automatically prepends conversation history to API requests
- **Auto-save**: Automatically saves messages after responses complete
- **Configurable**: Max history messages, enable/disable auto features
### Usage
```typescript
import { OpenRouter, Memory, InMemoryStorage } from "@openrouter/sdk";
const memory = new Memory(new InMemoryStorage());
const client = new OpenRouter({ apiKey, memory });
const response = client.getResponse({
model: "meta-llama/llama-3.2-1b-instruct",
input: [{ role: "user", content: "Hello!" }],
threadId: "thread-123",
resourceId: "user-456"
});
const text = await response.text; // History auto-injected, message auto-saved
```
### Testing
- Comprehensive E2E tests covering all memory features
- All tests passing
- Usage example included in examples/memory-usage.ts
### Architecture
- Non-breaking: Memory is completely optional
- Compatible with generated Speakeasy code
- Modular: Easy to add new storage backends
- Type-safe: Full TypeScript support
Serialization is a storage concern, not a memory concern. This refactoring: - Moves serialize/hydrate methods from Memory class to MemoryStorage interface - Implements serialize/hydrate/serializeThread/hydrateThread in InMemoryStorage - Updates tests to use storage.serialize() instead of memory.serialize() - Updates usage example to show proper storage serialization pattern This makes the architecture cleaner and allows different storage backends to implement their own serialization strategies (e.g., direct DB export, file formats, etc.)
Adds provider-agnostic enhancements to memory system to support advanced features like token budgeting, message editing, caching, and priority-based selection. ## New Features ### Enhanced Message Metadata (Optional) - status: 'active' | 'archived' | 'deleted' for filtering - importance: 0-1 score for priority-based selection - tokenCount: Provider-calculated token count - cacheControl: Cache configuration with expiry - version: Message versioning for edit tracking - editedFrom: Original message ID for edit history ### Context Window Management - ContextWindowConfig: maxTokens, strategy, retainRecentMessages - Strategies: fifo, priority-based, token-aware - Token budget-aware message retrieval ### New Storage Methods (Optional) - updateMessage: Edit existing messages - getMessageHistory: Get message version history - getThreadTokenCount: Calculate total tokens - getMessagesByTokenBudget: Retrieve within token limit - getCachedMessages: Get messages with active cache - invalidateCache: Expire cached messages - getMessagesByStatus: Filter by status - getMessagesByImportance: Filter by importance score ### Memory Class Enhancements - updateMessage: Edit messages with versioning - getMessageVersions: Get edit history - getThreadTokenCount: Get token usage - getMessagesWithinBudget: Token-aware retrieval - getCachedMessages: Cache-aware retrieval - invalidateCache: Cache management - getMessagesByStatus: Status filtering - getMessagesByImportance: Priority filtering ## Design Principles - Backward compatible: All new fields/methods are optional - Provider agnostic: No specific API dependencies - Graceful degradation: Falls back when storage doesn't support features - Type safe: Full TypeScript support with proper types ## Implementation - All optional methods implemented in InMemoryStorage - Memory class checks for method availability before calling - New types exported: CacheControl, ContextWindowConfig - All existing tests pass (10/10)
- Add 10 new tests covering all context-aware enhancements - Test message editing and version history tracking - Test token-aware message selection within budget - Test cache management (enable, retrieve, invalidate) - Test message filtering by status and importance - Test graceful degradation when storage doesn't support features - Test contextWindow config integration - Update usage examples to demonstrate new features - All 20 tests passing
- Remove getCachedMessages from MemoryStorage interface, InMemoryStorage, and Memory class - Remove getMessagesByImportance from MemoryStorage interface, InMemoryStorage, and Memory class - Remove related tests (3 tests removed, 17 tests remaining, all passing) - Update usage examples to remove references to removed methods - Build successful with no TypeScript errors
Remove unnecessary configuration options and improve developer experience: - Remove always-true config options (autoSave, autoInject, trackTokenUsage) - Remove unused config fields (strategy, retainRecentMessages) - Replace custom ID generation with UUID v4 - Fix deprecated .substr() to use .slice() - Improve error messages for unsupported storage operations - Update examples and tests This reduces MemoryConfig from 7 fields to 2, making the API simpler while maintaining all functionality.
- Add comprehensive unit tests for InMemoryStorage (91 tests) - Add comprehensive unit tests for Memory class (62 tests) - Cover all edge cases including working memory hydration and tokenCount:0 - Add @vitest/coverage-v8 dependency for coverage reporting - Total: 153 passing tests with 100% coverage on core memory classes Coverage results: - memory.ts: 100% statements, 100% branch, 100% functions - in-memory.ts: 100% statements, 100% branch, 100% functions
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview
This PR implements a comprehensive memory system for the OpenRouter TypeScript SDK, enabling conversation history management, thread-based conversations, and working memory for both threads and users/resources.
Recent Updates
100% Test Coverage Achieved ✅
Complete unit test suite with 153 passing tests:
Coverage Results:
memory.ts: 100% statements, 100% branch, 100% functionsin-memory.ts: 100% statements, 100% branch, 100% functionsConfiguration Simplification ✨
Reduced MemoryConfig from 7 fields to 2 for a cleaner, simpler API:
autoSave,autoInject,trackTokenUsage(now always enabled)strategyandretainRecentMessagesfieldsBefore:
After:
Features
Core Components
Automatic Memory Management
threadIdis providedContext-Aware Enhancements
Thread & Resource Management
Working Memory
Serialization & Persistence
Provider Compatibility
This memory system is fully compatible with hosted context management solutions as storage providers, including:
MemoryStorageinterface can be implemented to integrate with any hosted conversation or context management serviceThe optional enhancement methods (
updateMessage,getMessageHistory, etc.) enable rich integration with provider-specific features while maintaining a provider-agnostic API. Storage implementations can choose which optional methods to support based on the provider's capabilities.Usage Example
See examples/memory-usage.ts for more comprehensive examples.
Architecture
Design Principles
#regionmarkersFiles Added
src/lib/memory/types.ts- Type definitionssrc/lib/memory/memory.ts- Main Memory classsrc/lib/memory/storage/interface.ts- Storage interfacesrc/lib/memory/storage/in-memory.ts- In-memory storage implementationsrc/lib/memory/index.ts- Public exportstests/e2e/memory.test.ts- E2E integration tests (17 tests)tests/unit/memory/memory.test.ts- Memory class unit tests (62 tests, 100% coverage)tests/unit/memory/storage/in-memory.test.ts- InMemoryStorage unit tests (91 tests, 100% coverage)examples/memory-usage.ts- Usage examplesFiles Modified
src/index.ts- Export memory types and classessrc/sdk/sdk.ts- Add memory gettersrc/funcs/getResponse.ts- Handle threadId/resourceId and pass to ResponseWrappersrc/lib/response-wrapper.ts- Implement auto-inject and auto-saveTesting
✅ All 170 tests passing with 100% coverage on core classes
Test Coverage:
Future Enhancements
Potential future additions (not in this PR):
Breaking Changes
None - memory is completely optional and backward compatible.
Checklist