mcal-ai 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,217 @@
1
+ """
2
+ AWS Bedrock LLM Provider for MCAL.
3
+ """
4
+
5
+ import json
6
+ import asyncio
7
+ import logging
8
+ from typing import Dict, List, Any, Optional
9
+ import boto3
10
+ from botocore.exceptions import ClientError
11
+
12
+ from ..core.retry import (
13
+ llm_retry,
14
+ classify_boto_error,
15
+ LLMThrottlingError,
16
+ LLMServerError,
17
+ LLMTimeoutError,
18
+ )
19
+ from ..core.rate_limiter import (
20
+ TokenBucketRateLimiter,
21
+ RateLimitConfig,
22
+ create_rate_limiter,
23
+ )
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ class BedrockProvider:
29
+ """AWS Bedrock LLM provider for MCAL."""
30
+
31
+ MODELS = {
32
+ # Fast models (simple tasks: intent detection, graph updates)
33
+ # Use cross-region inference profile IDs for on-demand throughput
34
+ "llama-3.1-8b": {"id": "us.meta.llama3-1-8b-instruct-v1:0", "max_tokens": 4096, "type": "llama", "tier": "fast"},
35
+ "llama-3.2-3b": {"id": "us.meta.llama3-2-3b-instruct-v1:0", "max_tokens": 4096, "type": "llama", "tier": "fast"},
36
+ # Smart models (complex tasks: decision extraction, reasoning)
37
+ "llama-3.3-70b": {"id": "us.meta.llama3-3-70b-instruct-v1:0", "max_tokens": 4096, "type": "llama", "tier": "smart"},
38
+ "llama-4-maverick": {"id": "us.meta.llama4-maverick-17b-instruct-v1:0", "max_tokens": 4096, "type": "llama", "tier": "smart"},
39
+ "llama-3.1-70b": {"id": "us.meta.llama3-1-70b-instruct-v1:0", "max_tokens": 4096, "type": "llama", "tier": "smart"},
40
+ }
41
+
42
+ # Default models for tiered selection
43
+ DEFAULT_FAST_MODEL = "llama-3.1-8b"
44
+ DEFAULT_SMART_MODEL = "llama-3.3-70b"
45
+
46
+ def __init__(
47
+ self,
48
+ model: str = "llama-3.3-70b",
49
+ region: str = "us-east-1",
50
+ temperature: float = 0.7,
51
+ max_tokens: int = 2048,
52
+ # Rate limiting options (Issue #39)
53
+ enable_rate_limiting: bool = False,
54
+ rate_limit_rpm: int = 60,
55
+ rate_limit_tpm: int = 100_000,
56
+ max_cost_per_hour: Optional[float] = None,
57
+ enable_cost_logging: bool = True,
58
+ ):
59
+ """
60
+ Initialize Bedrock provider.
61
+
62
+ Args:
63
+ model: Model name (e.g., "llama-3.3-70b")
64
+ region: AWS region
65
+ temperature: Sampling temperature
66
+ max_tokens: Maximum tokens per response
67
+ enable_rate_limiting: Enable rate limiting (default: False)
68
+ rate_limit_rpm: Requests per minute limit (default: 60)
69
+ rate_limit_tpm: Tokens per minute limit (default: 100,000)
70
+ max_cost_per_hour: Maximum cost per hour in USD (None = unlimited)
71
+ enable_cost_logging: Log cost estimates for each call
72
+ """
73
+ if model not in self.MODELS:
74
+ raise ValueError(f"Unknown model: {model}")
75
+ self.model_name = model
76
+ self.model_config = self.MODELS[model]
77
+ self.model_id = self.model_config["id"]
78
+ self.temperature = temperature
79
+ self.max_tokens = min(max_tokens, self.model_config["max_tokens"])
80
+ self.bedrock = boto3.client('bedrock-runtime', region_name=region)
81
+
82
+ # Token tracking
83
+ self.total_prompt_tokens = 0
84
+ self.total_completion_tokens = 0
85
+
86
+ # Rate limiting (Issue #39)
87
+ self._rate_limiter: Optional[TokenBucketRateLimiter] = None
88
+ if enable_rate_limiting:
89
+ self._rate_limiter = create_rate_limiter(
90
+ model=model,
91
+ provider="bedrock",
92
+ rpm=rate_limit_rpm,
93
+ tpm=rate_limit_tpm,
94
+ max_cost_per_hour=max_cost_per_hour,
95
+ enable_cost_logging=enable_cost_logging,
96
+ )
97
+ logger.info(
98
+ f"Rate limiting enabled for {model}: "
99
+ f"{rate_limit_rpm} RPM, {rate_limit_tpm} TPM"
100
+ + (f", max ${max_cost_per_hour}/hr" if max_cost_per_hour else "")
101
+ )
102
+
103
+ def get_token_usage(self) -> dict:
104
+ """Get total token usage."""
105
+ return {
106
+ "prompt_tokens": self.total_prompt_tokens,
107
+ "completion_tokens": self.total_completion_tokens,
108
+ "total_tokens": self.total_prompt_tokens + self.total_completion_tokens
109
+ }
110
+
111
+ def reset_token_usage(self):
112
+ """Reset token counters."""
113
+ self.total_prompt_tokens = 0
114
+ self.total_completion_tokens = 0
115
+
116
+ @llm_retry(max_attempts=3, min_wait=1.0, max_wait=10.0)
117
+ async def generate(self, messages: List[Dict[str, str]], **kwargs) -> str:
118
+ """
119
+ Generate a response from Bedrock with automatic retry on transient failures.
120
+
121
+ Retries on:
122
+ - ThrottlingException (rate limits)
123
+ - ServiceUnavailableException (5xx errors)
124
+ - Connection timeouts
125
+
126
+ Args:
127
+ messages: List of message dicts with 'role' and 'content'
128
+ **kwargs: Additional parameters (max_tokens, temperature)
129
+
130
+ Returns:
131
+ Generated text response
132
+
133
+ Raises:
134
+ LLMThrottlingError: After max retries on throttling
135
+ LLMServerError: After max retries on server errors
136
+ PermissionError: On access denied (not retried)
137
+ RuntimeError: On other non-retryable errors or cost limit exceeded
138
+ """
139
+ # Rate limiting (Issue #39)
140
+ if self._rate_limiter:
141
+ # Estimate tokens based on message content
142
+ total_chars = sum(len(m.get("content", "")) for m in messages)
143
+ estimated_tokens = max(total_chars // 4, 500) # Rough estimate
144
+ await self._rate_limiter.acquire(estimated_tokens=estimated_tokens)
145
+
146
+ try:
147
+ # Convert message format for Converse API (content must be a list)
148
+ formatted_messages = []
149
+ for msg in messages:
150
+ formatted_messages.append({
151
+ "role": msg["role"],
152
+ "content": [{"text": msg["content"]}]
153
+ })
154
+
155
+ response = await asyncio.get_event_loop().run_in_executor(
156
+ None,
157
+ lambda: self.bedrock.converse(
158
+ modelId=self.model_id,
159
+ messages=formatted_messages,
160
+ inferenceConfig={
161
+ "maxTokens": kwargs.get("max_tokens", self.max_tokens),
162
+ "temperature": kwargs.get("temperature", self.temperature),
163
+ "topP": 0.9,
164
+ }
165
+ )
166
+ )
167
+
168
+ # Track token usage from Bedrock response
169
+ input_tokens = 0
170
+ output_tokens = 0
171
+ if 'usage' in response:
172
+ input_tokens = response['usage'].get('inputTokens', 0)
173
+ output_tokens = response['usage'].get('outputTokens', 0)
174
+ self.total_prompt_tokens += input_tokens
175
+ self.total_completion_tokens += output_tokens
176
+
177
+ # Record usage for rate limiting (Issue #39)
178
+ if self._rate_limiter:
179
+ self._rate_limiter.record_usage(input_tokens, output_tokens)
180
+
181
+ return response['output']['message']['content'][0]['text']
182
+ except ClientError as e:
183
+ error_code = e.response['Error']['Code']
184
+ error_msg = e.response['Error']['Message']
185
+
186
+ # Non-retryable: access denied
187
+ if error_code == "AccessDeniedException":
188
+ raise PermissionError(f"Bedrock access denied: {error_msg}")
189
+
190
+ # Classify and potentially retry
191
+ classified_error = classify_boto_error(error_code, error_msg)
192
+ logger.warning(f"Bedrock error ({error_code}): {error_msg} - {'retrying' if isinstance(classified_error, (LLMThrottlingError, LLMServerError)) else 'not retrying'}")
193
+ raise classified_error
194
+
195
+ def get_rate_limit_stats(self) -> Optional[Dict[str, Any]]:
196
+ """Get rate limiter statistics (if enabled)."""
197
+ if self._rate_limiter:
198
+ return self._rate_limiter.get_stats()
199
+ return None
200
+
201
+
202
+ async def test_bedrock_provider():
203
+ print("Testing Bedrock Provider...")
204
+ print("=" * 70)
205
+ for model in ["llama-3.3-70b", "llama-4-maverick"]:
206
+ try:
207
+ print(f"\nTesting {model}...")
208
+ provider = BedrockProvider(model=model, max_tokens=100)
209
+ messages = [{"role": "user", "content": "What is 2+2?"}]
210
+ response = await provider.generate(messages)
211
+ print(f"✅ Response: {response[:100]}")
212
+ except Exception as e:
213
+ print(f"❌ Error: {str(e)[:150]}")
214
+
215
+
216
+ if __name__ == "__main__":
217
+ asyncio.run(test_bedrock_provider())
@@ -0,0 +1 @@
1
+ """MCAL Storage backends."""
@@ -0,0 +1,319 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcal-ai
3
+ Version: 0.1.0
4
+ Summary: Memory-Context Alignment Layer for Goal-Coherent AI Agents
5
+ Author: MCAL Team
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Shivakoreddi/mcal-ai
8
+ Project-URL: Documentation, https://github.com/Shivakoreddi/mcal-ai#readme
9
+ Project-URL: Repository, https://github.com/Shivakoreddi/mcal-ai.git
10
+ Project-URL: Issues, https://github.com/Shivakoreddi/mcal-ai/issues
11
+ Keywords: llm,memory,agents,context,ai,nlp
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: anthropic>=0.18.0
24
+ Requires-Dist: openai>=1.0.0
25
+ Requires-Dist: boto3>=1.28.0
26
+ Requires-Dist: pydantic>=2.0.0
27
+ Requires-Dist: numpy>=1.24.0
28
+ Requires-Dist: faiss-cpu>=1.7.4
29
+ Requires-Dist: sentence-transformers>=2.2.0
30
+ Requires-Dist: sqlalchemy>=2.0.0
31
+ Requires-Dist: aiosqlite>=0.19.0
32
+ Requires-Dist: tiktoken>=0.5.0
33
+ Requires-Dist: tenacity>=8.2.0
34
+ Requires-Dist: rich>=13.0.0
35
+ Requires-Dist: python-dotenv>=1.0.0
36
+ Provides-Extra: langgraph
37
+ Requires-Dist: langgraph>=0.0.40; extra == "langgraph"
38
+ Requires-Dist: langchain-core>=0.1.0; extra == "langgraph"
39
+ Provides-Extra: crewai
40
+ Requires-Dist: crewai>=0.28.0; extra == "crewai"
41
+ Provides-Extra: autogen
42
+ Requires-Dist: pyautogen>=0.2.0; extra == "autogen"
43
+ Provides-Extra: langchain
44
+ Requires-Dist: langchain>=0.1.0; extra == "langchain"
45
+ Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
46
+ Provides-Extra: integrations
47
+ Requires-Dist: langgraph>=0.0.40; extra == "integrations"
48
+ Requires-Dist: langchain-core>=0.1.0; extra == "integrations"
49
+ Requires-Dist: crewai>=0.28.0; extra == "integrations"
50
+ Requires-Dist: pyautogen>=0.2.0; extra == "integrations"
51
+ Provides-Extra: mem0
52
+ Requires-Dist: mem0ai>=0.1.0; extra == "mem0"
53
+ Provides-Extra: dev
54
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
55
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
56
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
57
+ Requires-Dist: black>=23.0.0; extra == "dev"
58
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
59
+ Requires-Dist: mypy>=1.5.0; extra == "dev"
60
+ Requires-Dist: pre-commit>=3.4.0; extra == "dev"
61
+ Requires-Dist: ipykernel>=6.25.0; extra == "dev"
62
+ Requires-Dist: jupyter>=1.0.0; extra == "dev"
63
+ Provides-Extra: eval
64
+ Requires-Dist: pandas>=2.0.0; extra == "eval"
65
+ Requires-Dist: matplotlib>=3.7.0; extra == "eval"
66
+ Requires-Dist: seaborn>=0.12.0; extra == "eval"
67
+ Requires-Dist: wandb>=0.15.0; extra == "eval"
68
+ Requires-Dist: scipy>=1.11.0; extra == "eval"
69
+ Provides-Extra: all
70
+ Requires-Dist: mcal[dev,eval,integrations]; extra == "all"
71
+ Dynamic: license-file
72
+
73
+ # MCAL: Memory-Context Alignment Layer
74
+
75
+ > **Beyond Retrieval:** Intent-Preserving Memory for Goal-Coherent AI Agents
76
+
77
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
78
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
79
+ [![arXiv](https://img.shields.io/badge/arXiv-coming--soon-b31b1b.svg)](https://arxiv.org/)
80
+ [![Standalone](https://img.shields.io/badge/architecture-standalone-green.svg)](docs/MCAL_DESIGN.md)
81
+
82
+ ## What's New in v2.0
83
+
84
+ MCAL is now **fully standalone** - no external dependencies on Mem0 or other memory providers. The architecture includes:
85
+
86
+ - **Built-in Embedding Service** - OpenAI or Bedrock embeddings
87
+ - **Native Vector Search** - Cosine similarity with HNSW-like indexing
88
+ - **Graph Deduplication** - Automatic node merging with similarity detection
89
+ - **JSON Persistence** - Zero-config file-based storage
90
+
91
+ ## The Problem
92
+
93
+ Current AI agent memory systems store **facts** but lose **meaning**:
94
+
95
+ | What's Stored | What's Lost |
96
+ |--------------------------------------|--------------------------------------------------|
97
+ | "User wants to visit Japan" | **WHY** they chose Japan over other destinations |
98
+ | "User booked a hotel in Shibuya" | **WHAT** alternatives were considered (Shinjuku, Ginza, Asakusa) |
99
+ | "User plans to visit Kyoto" | **HOW** this fits into the overall trip plan |
100
+
101
+ This creates the **Memory-Context Alignment Paradox**: as conversations grow, agents remember *what* was said but forget *why* it mattered.
102
+
103
+ ## Our Solution: Three Pillars
104
+
105
+ ### 1. Intent Graph Preservation
106
+ Hierarchical goal structures that persist across sessions:
107
+ ```
108
+ MISSION: Plan a 2-week vacation to Japan
109
+ ├── GOAL: Book travel [✓ COMPLETED]
110
+ │ ├── TASK: Find flights [✓]
111
+ │ └── TASK: Reserve hotels [✓]
112
+ ├── GOAL: Plan activities [ACTIVE]
113
+ │ ├── TASK: Research Tokyo attractions [✓]
114
+ │ ├── TASK: Plan Kyoto day trips [IN PROGRESS]
115
+ │ └── TASK: Book restaurants [PENDING]
116
+ └── GOAL: Pack and prepare [PENDING]
117
+ ```
118
+
119
+ ### 2. Reasoning Chain Storage
120
+ Preserve **WHY** decisions were made, not just conclusions:
121
+ ```
122
+ Decision: "Stay in Shibuya for Tokyo accommodation"
123
+ ├── Alternatives: [Shinjuku, Ginza, Asakusa]
124
+ ├── Rationale: "Central location, good nightlife, easy metro access"
125
+ ├── Evidence: ["User wants to explore at night", "Prefers walkable areas"]
126
+ └── Trade-offs: ["More expensive but saves daily transit time"]
127
+ ```
128
+
129
+ ### 3. Goal-Aware Retrieval
130
+ Retrieve based on **objective achievement**, not just similarity:
131
+ ```
132
+ Score = α × semantic_similarity
133
+ + β × goal_alignment ← NEW
134
+ + γ × decision_relevance ← NEW
135
+ + δ × recency_decay
136
+ ```
137
+
138
+ ## Installation
139
+
140
+ ```bash
141
+ # Install from source (recommended)
142
+ git clone https://github.com/Shivakoreddi/mcla-research.git
143
+ cd mcla-research
144
+ pip install -e .
145
+
146
+ # Development installation with test dependencies
147
+ pip install -e ".[dev]"
148
+
149
+ # Optional: Install with legacy Mem0 support
150
+ pip install -e ".[mem0]"
151
+ ```
152
+
153
+ ### Requirements
154
+ - Python 3.11+
155
+ - `anthropic` - For LLM extraction (Claude)
156
+ - `openai` - For embeddings (optional, can use Bedrock instead)
157
+
158
+ ## Quick Start
159
+
160
+ ```python
161
+ import asyncio
162
+ from mcal import MCAL
163
+
164
+ async def main():
165
+ # Initialize MCAL (standalone by default)
166
+ mcal = MCAL(
167
+ llm_provider="anthropic", # or "bedrock", "openai"
168
+ embedding_provider="openai", # or "bedrock"
169
+ )
170
+
171
+ # Add conversation messages
172
+ messages = [
173
+ {"role": "user", "content": "I'm building a fraud detection ML pipeline"},
174
+ {"role": "assistant", "content": "Great! Let's start with data ingestion..."},
175
+ {"role": "user", "content": "I chose PostgreSQL over MongoDB for the data store"},
176
+ {"role": "assistant", "content": "PostgreSQL is a solid choice for structured fraud data..."}
177
+ ]
178
+
179
+ result = await mcal.add(messages, user_id="user_123")
180
+
181
+ # Access the unified graph with goals, decisions, and reasoning
182
+ print(f"Extracted {result.unified_graph.node_count} nodes")
183
+ print(f"Active goals: {result.unified_graph.get_active_goals()}")
184
+ print(f"Decisions: {result.unified_graph.get_all_decisions_with_detail()}")
185
+
186
+ # Search for relevant context
187
+ search_results = await mcal.search(
188
+ query="What database did the user choose?",
189
+ user_id="user_123"
190
+ )
191
+
192
+ # Get formatted context for LLM
193
+ context = mcal.get_context(
194
+ query="What should we focus on next?",
195
+ user_id="user_123",
196
+ max_tokens=4000
197
+ )
198
+
199
+ asyncio.run(main())
200
+
201
+ ## Architecture
202
+
203
+ ```
204
+ ┌─────────────────────────────────────────────────────────────────┐
205
+ │ MCAL v2.0 │
206
+ │ ┌───────────────────────────────────────────────────────────┐ │
207
+ │ │ Application Layer │ │
208
+ │ │ mcal.add() │ mcal.search() │ mcal.get_context() │ │
209
+ │ └───────────────────────────────────────────────────────────┘ │
210
+ │ │ │
211
+ │ ┌───────────────────────────────────────────────────────────┐ │
212
+ │ │ Unified Deep Extractor │ │
213
+ │ │ Single LLM call extracts: GOALS | DECISIONS | FACTS │ │
214
+ │ └───────────────────────────────────────────────────────────┘ │
215
+ │ │ │
216
+ │ ┌───────────────────────────────────────────────────────────┐ │
217
+ │ │ Unified Graph (6 Nodes, 13 Edges) │ │
218
+ │ │ PERSON | THING | CONCEPT | GOAL | DECISION | ACTION │ │
219
+ │ └───────────────────────────────────────────────────────────┘ │
220
+ │ │ │
221
+ │ ┌───────────────────────────────────────────────────────────┐ │
222
+ │ │ Standalone Services │ │
223
+ │ │ ┌──────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
224
+ │ │ │ Embeddings │ │Vector Search│ │ Deduplication │ │ │
225
+ │ │ │ (OpenAI/ │ │(Cosine Sim) │ │ (Similarity │ │ │
226
+ │ │ │ Bedrock) │ │ │ │ Merging) │ │ │
227
+ │ │ └──────────────┘ └─────────────┘ └─────────────────┘ │ │
228
+ │ └───────────────────────────────────────────────────────────┘ │
229
+ │ │ │
230
+ │ ┌───────────────────────────────────────────────────────────┐ │
231
+ │ │ JSON File Persistence │ │
232
+ │ │ ~/.mcal/users/{user_id}/graph.json │ │
233
+ │ └───────────────────────────────────────────────────────────┘ │
234
+ └─────────────────────────────────────────────────────────────────┘
235
+ ```
236
+
237
+ ## Project Structure
238
+
239
+ ```
240
+ mcla-research/
241
+ ├── src/mcal/
242
+ │ ├── mcal.py # Main MCAL class
243
+ │ ├── core/
244
+ │ │ ├── unified_extractor.py # Single-pass extraction
245
+ │ │ ├── unified_graph.py # Graph with rich attributes
246
+ │ │ ├── embedding_service.py # Embedding generation
247
+ │ │ ├── vector_index.py # Similarity search
248
+ │ │ └── deduplication.py # Node merging
249
+ │ ├── providers/
250
+ │ │ └── llm_providers.py # Anthropic, OpenAI, Bedrock
251
+ │ └── storage/
252
+ │ └── sqlite_store.py # Persistence layer
253
+ ├── experiments/
254
+ ├── data/
255
+ │ ├── synthetic/ # Generated conversations
256
+ │ └── benchmarks/ # MCAL-Bench dataset
257
+ ├── tests/
258
+ └── docs/
259
+ ```
260
+
261
+ ## Evaluation: MCAL-Bench
262
+
263
+ We introduce **MCAL-Bench**, the first benchmark for reasoning preservation and goal coherence:
264
+
265
+ | Metric | What It Measures |
266
+ |--------|------------------|
267
+ | **RPS** (Reasoning Preservation Score) | Can the system explain WHY a decision was made? |
268
+ | **GCS** (Goal Coherence Score) | Do responses align with user's active objectives? |
269
+ | **TER** (Token Efficiency Ratio) | Quality-per-token vs full context baseline |
270
+
271
+ ## Results (Preliminary)
272
+
273
+ | System | RPS | GCS | TER |
274
+ |--------|-----|-----|-----|
275
+ | Full Context | 0.85 | 0.82 | 1.0x |
276
+ | Summarization | 0.45 | 0.58 | 2.1x |
277
+ | Mem0 | 0.52 | 0.61 | 3.2x |
278
+ | **MCAL (Ours)** | **0.78** | **0.79** | **3.8x** |
279
+
280
+ ## Roadmap
281
+
282
+ - [x] Problem formulation & research
283
+ - [ ] Week 1: Foundation (baseline + data)
284
+ - [ ] Week 2: Core algorithms
285
+ - [ ] Week 3: Benchmark & evaluation
286
+ - [ ] Week 4: Paper draft
287
+ - [ ] Week 5: Release & arXiv
288
+
289
+ ## Citation
290
+
291
+ ```bibtex
292
+ @article{mcal2026,
293
+ title={MCAL: Memory-Context Alignment for Goal-Coherent AI Agents},
294
+ author={Koreddi, Shiva},
295
+ journal={arXiv preprint},
296
+ year={2026}
297
+ }
298
+ ```
299
+
300
+ ## License
301
+
302
+ MIT License - see [LICENSE](LICENSE) for details.
303
+
304
+ ## Acknowledgments
305
+
306
+ Built on insights from:
307
+ - [MemGPT](https://github.com/cpacker/MemGPT) - OS-inspired memory hierarchy
308
+ - [Reflexion](https://arxiv.org/abs/2303.11366) - Verbal self-reflection
309
+
310
+ ---
311
+
312
+ ## Migration from v1.x
313
+
314
+ If you were using MCAL with Mem0 backend, see [STANDALONE_MIGRATION.md](docs/STANDALONE_MIGRATION.md) for migration guide.
315
+
316
+ **Key changes:**
317
+ - `mem0_config` and `mem0_api_key` parameters are deprecated
318
+ - `use_standalone_backend` is deprecated (standalone is now default)
319
+ - Install `mcal[mem0]` for legacy Mem0 support
@@ -0,0 +1,32 @@
1
+ mcal/__init__.py,sha256=8paMduzZUQ1oDhJQtt9lj01fqWohvqoo5m296Swx2pY,4276
2
+ mcal/mcal.py,sha256=-CIODdF6XK6cnFjJBvSEy_3dcZOFjP1tuXFf2LoAvDE,69662
3
+ mcal/backends/__init__.py,sha256=bYNXulnb39Fl6BSpqb7sEswJIORVnY9pe1L2-qTY2Bk,1200
4
+ mcal/backends/base.py,sha256=zELlkIuqPG7Kk11j_gF0rvCaYAey_mPm0jvHSGOIJ_Y,11683
5
+ mcal/baselines/__init__.py,sha256=0CnVJQxNp9sHfUCMxyBGoWjijlBmYV4hIprETWzuD-E,52
6
+ mcal/core/__init__.py,sha256=EWpI1hJrozDcx0T7QxmRGNZDC5xaA5W0JyRjMuRZRXo,2205
7
+ mcal/core/embeddings.py,sha256=mqXhuyDAfqctSZSEQPTe8ZhuSKS0ZwflVKt1RYqX0wY,8465
8
+ mcal/core/extraction_cache.py,sha256=YJKJIDmPrnhWQYq1WS6qDnDlC28gjWRpl7QkERLhn1M,13717
9
+ mcal/core/goal_retriever.py,sha256=WlkyL6Wk3GBMQHsBGtVWnblnZdC9CDyhwvDixVLwujI,17946
10
+ mcal/core/intent_tracker.py,sha256=KDTlhiVA4CZrD9rMyt2syTsOMQqRB9U7yspDlpBZxRo,25322
11
+ mcal/core/models.py,sha256=CSC3lqeaVovP8B-R4eU720PbCef4fYLUWGr2vT-wfKc,15505
12
+ mcal/core/rate_limiter.py,sha256=L1vUwWvtVrrIy5EDIZxWGEGxYtiP9sfmBbv8sroXAuc,14243
13
+ mcal/core/reasoning_store.py,sha256=lj4cR7sUwWinxsMaKGkEWE5SQV0AobpvDnOjmnbIzVY,38277
14
+ mcal/core/retry.py,sha256=fM9xhIEUMKROGxWG02j_aZqE6dz7QL5EGK_UdcPWsAk,5488
15
+ mcal/core/storage.py,sha256=sB6d49d1Z8ez4RTVEOOhJA6RefKyNfgybMj8ubtJVkU,15309
16
+ mcal/core/streaming.py,sha256=9Og_RO8AK3l15Dfwkc_Lz6TV_AHzvv0sIqtVXvtSFcs,7402
17
+ mcal/core/unified_extractor.py,sha256=GFxSGxarHVG6hz2L1biIgyiNGXOldPdFvqH_QbyInRM,53172
18
+ mcal/core/vector_index.py,sha256=Z67ZuKh0Vol8zeQ0ruFJ94x9vzesMWtcmKt7O6Q3MvM,6091
19
+ mcal/evaluation/__init__.py,sha256=J1JtxdEVFocjJKk0nhuqoagpRVmuCpa46xKOonq5m0s,46
20
+ mcal/integrations/__init__.py,sha256=4YN2Rg1ZG38qN-SyVgb6DYE4Gj6zaXGy8jtr32bmGEc,2878
21
+ mcal/integrations/autogen.py,sha256=uaIEAktLsl8mgEc64PK1Nu9vQJDy9PAXiXWvf57_gLk,2593
22
+ mcal/integrations/crewai.py,sha256=FVfOWxnKnxhXB7KEhLgQMdEv5HFv2OK0RfDPcH3jTZ4,2462
23
+ mcal/integrations/langchain.py,sha256=J_xOUIUoWYcTA5iFiwyt9rTLt1R4lltAJ3hj957B4Vs,3171
24
+ mcal/integrations/langgraph.py,sha256=nIE7U9aQQLgG_qRQmZuy2ZOJbg_ZRCIbmYOWc0bZklA,1257
25
+ mcal/providers/bedrock.py,sha256=zUI07KouzOAXfMgDwloJuor0COElIBrE5_PVtjn6g7E,8632
26
+ mcal/storage/__init__.py,sha256=9CsHK4EtBOoSk04EcOFzCAP8LjvqX3K2ZE-hxA96jPU,29
27
+ mcal_ai-0.1.0.dist-info/licenses/LICENSE,sha256=zdp5kxDzb-kYvBiEZ_h1Hi96z-o6e5oXoXFx2IIefCs,1062
28
+ mcal_ai-0.1.0.dist-info/METADATA,sha256=MK_rggbEuc13eRezR3xHVIproSKNJ_RrZXdTjx6_KL8,14262
29
+ mcal_ai-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
30
+ mcal_ai-0.1.0.dist-info/entry_points.txt,sha256=ICilsPI5krXkoM9espdv7jtJnRMO2hTdTcwiocNDfJs,39
31
+ mcal_ai-0.1.0.dist-info/top_level.txt,sha256=aJ6Ay5tUlQgkrlbGXc90wuOWQpncaHNFN036i9hIWj0,5
32
+ mcal_ai-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mcal = mcal.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shiva
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ mcal