diff --git a/dist/memory_thread-1.0.0.tar.gz b/dist/memory_thread-1.0.0.tar.gz new file mode 100644 index 0000000..8a26aaa Binary files /dev/null and b/dist/memory_thread-1.0.0.tar.gz differ diff --git a/memory_thread.egg-info/PKG-INFO b/memory_thread.egg-info/PKG-INFO deleted file mode 100644 index 0331040..0000000 --- a/memory_thread.egg-info/PKG-INFO +++ /dev/null @@ -1,333 +0,0 @@ -Metadata-Version: 2.4 -Name: memory-thread -Version: 1.0.0 -Summary: A truth-preserving, multi-agent cognitive memory system for AI -Home-page: https://github.com/badalraj/MemoryThread -Author: Badal Raj -Author-email: Badal Raj -License: MIT -Project-URL: Homepage, https://github.com/badalraj/MemoryThread -Project-URL: Documentation, https://github.com/badalraj/MemoryThread#readme -Project-URL: Repository, https://github.com/badalraj/MemoryThread -Project-URL: Issues, https://github.com/badalraj/MemoryThread/issues -Keywords: memory,ai,cognitive,truth-preservation,multi-agent,llm,rag,knowledge-graph -Classifier: Development Status :: 4 - Beta -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Science/Research -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence -Classifier: Topic :: Database -Requires-Python: >=3.9 -Description-Content-Type: text/markdown; charset=UTF-8 -License-File: LICENSE -Requires-Dist: pydantic>=2.0 -Requires-Dist: networkx>=3.0 -Requires-Dist: sentence-transformers>=2.0 -Requires-Dist: python-dotenv>=1.0 -Provides-Extra: api -Requires-Dist: fastapi>=0.100; extra == "api" -Requires-Dist: uvicorn>=0.20; extra == "api" -Provides-Extra: db -Requires-Dist: psycopg2-binary>=2.9; extra == "db" -Requires-Dist: qdrant-client>=1.5; extra == "db" -Provides-Extra: streaming -Requires-Dist: pyzmq>=25.0; extra == "streaming" -Requires-Dist: aiokafka>=0.8; extra == "streaming" -Provides-Extra: tui -Requires-Dist: textual>=0.40; extra == "tui" -Provides-Extra: cli -Requires-Dist: typer>=0.9; extra == "cli" -Requires-Dist: rich>=13.0; extra == "cli" -Provides-Extra: nlp -Requires-Dist: spacy>=3.5; extra == "nlp" -Provides-Extra: observability -Requires-Dist: opentelemetry-api>=1.20; extra == "observability" -Requires-Dist: opentelemetry-sdk>=1.20; extra == "observability" -Requires-Dist: opentelemetry-instrumentation-fastapi>=0.41; extra == "observability" -Requires-Dist: opentelemetry-exporter-otlp>=1.20; extra == "observability" -Provides-Extra: full -Requires-Dist: memory-thread[api,cli,db,nlp,observability,streaming]; extra == "full" -Provides-Extra: dev -Requires-Dist: pytest>=7.0; extra == "dev" -Requires-Dist: pytest-asyncio>=0.21; extra == "dev" -Requires-Dist: pytest-cov>=4.0; extra == "dev" -Requires-Dist: black>=23.0; extra == "dev" -Requires-Dist: ruff>=0.1; extra == "dev" -Requires-Dist: mypy>=1.0; extra == "dev" -Dynamic: author -Dynamic: home-page -Dynamic: license-file -Dynamic: requires-python - -# Memory Thread - -> **A Truth-Preserving Cognitive Memory System for AI** - -[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/) -[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) -[![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)](tests/) -[![API Docs](https://img.shields.io/badge/docs-OpenAPI-orange.svg)](#api-documentation) - ---- - -## Overview - -Memory Thread (MT) is a **cognitive memory layer** for AI systems that solves the fundamental problem of **truth preservation** in multi-agent environments. Unlike traditional vector databases, MT tracks the _provenance_, _confidence_, and _decay_ of every piece of information. - -### Key Features - -| Feature | Description | -| --------------------- | ------------------------------------------------------------ | -| **Truth Vectors** | Every memory has confidence, authority, and freshness scores | -| **Galaxy Schema** | OLAP-style queries across fact and belief dimensions | -| **Multi-Agent** | Each agent has its own belief dimension | -| **Graceful Fallback** | DB → File → Memory (never loses data) | -| **RBAC** | Role-based access control with audit logging | -| **Time Travel** | Event-sourced history reconstruction | - ---- - -## Quick Start - -### Installation - -```bash -# Basic installation -pip install memory-thread - -# With all extras -pip install memory-thread[full] - -# Development -pip install memory-thread[dev] -``` - -### From Source - -```bash -git clone https://github.com/badalraj/MemoryThread.git -cd MemoryThread -pip install -e .[dev] -``` - -### Basic Usage - -```python -from memory_thread.sdk import MemoryClient - -# Create a client -mt = MemoryClient(namespace="my_app") - -# Store memories with truth metadata -mt.remember("User prefers dark mode", confidence=0.9, source="observation") -mt.remember("Project deadline is Friday", confidence=1.0, source="user") - -# Recall with truth filtering -results = mt.recall("user preferences", min_truth_score=0.5) - -for memory in results.memories: - print(f"{memory.content} (truth: {memory.truth_score:.2f})") -``` - ---- - -## Architecture - -``` -┌─────────────────────────────────────────────────────────────┐ -│ Memory Thread Architecture │ -├─────────────────────────────────────────────────────────────┤ -│ SDK / API Layer │ -│ ├── MemoryClient (Python SDK) │ -│ ├── REST API (FastAPI) │ -│ └── TUI (Terminal Interface) │ -├─────────────────────────────────────────────────────────────┤ -│ Galaxy Schema (OLAP for Cognition) │ -│ ├── Fact Store (Layer 0) - Immutable, content-addressed │ -│ ├── Belief Store (Layer 1) - Agent-specific interpretations │ -│ └── Query Engine (Layer 2) - SLICE/DICE/DRILL/ROLLUP │ -├─────────────────────────────────────────────────────────────┤ -│ Core Services │ -│ ├── TMS (Truth Maintenance System) │ -│ ├── Identity Service │ -│ ├── Timewarp Engine (Event Sourcing) │ -│ └── Contemplator (Self-Observation) │ -├─────────────────────────────────────────────────────────────┤ -│ Storage │ -│ ├── PostgreSQL (Events/States) │ -│ ├── Qdrant (Vector Search) │ -│ └── File Fallback (~/.mt/) │ -└─────────────────────────────────────────────────────────────┘ -``` - ---- - -## Galaxy Schema - -The Galaxy Schema applies **OLAP data warehouse principles to cognition**: - -```python -# Store raw facts (immutable, deduplicated) -fact_id = mt.ingest_fact( - content=code, - source_uri="file://auth.py", - content_type="code" -) - -# Multiple agents derive beliefs from the same fact -mt.derive_belief(fact_id, "Handles JWT securely", agent_id="SecurityBot", confidence=0.95) -mt.derive_belief(fact_id, "Needs refactoring", agent_id="CodeReviewer", authority=0.8) - -# OLAP-style queries -mt.query_galaxy("SLICE", source_uri="file://auth.py") # All beliefs about auth.py -mt.query_galaxy("DICE", agent_id="SecurityBot", min_authority=0.8) -mt.query_galaxy("ROLL_UP", entity_query="authentication") # Summarize -``` - ---- - -## API Documentation - -### REST API - -Start the API server: - -```bash -uvicorn memory_thread.api.server:app --reload -``` - -Access documentation: - -- **Swagger UI**: http://localhost:8000/docs -- **ReDoc**: http://localhost:8000/redoc - -### Endpoints - -| Method | Endpoint | Description | -| ------ | ------------------ | --------------- | -| POST | `/memory/remember` | Store a memory | -| POST | `/memory/recall` | Recall memories | -| POST | `/galaxy/fact` | Ingest a fact | -| POST | `/galaxy/belief` | Derive a belief | -| POST | `/galaxy/query` | OLAP query | -| GET | `/galaxy/stats` | Get statistics | -| GET | `/health` | Health check | - ---- - -## TUI (Terminal Interface) - -```bash -python -m memory_thread.utils.cli_bridge -``` - -### Commands - -| Command | Description | -| ----------------- | ----------------------------- | -| `just type` | Auto-remembered, LLM responds | -| `/recall ` | Search memories | -| `/galaxy stats` | Show fact/belief counts | -| `/provider list` | List LLM providers | -| `/secure` | Toggle secure mode | -| `/help` | Show all commands | - ---- - -## Configuration - -### Environment Variables - -```bash -# Database -MT_POSTGRES_URL=postgresql://user:pass@localhost/mt -MT_QDRANT_URL=http://localhost:6333 - -# LLM Providers (or use /secure mode) -GROQ_API_KEY=your_key -OPENROUTER_API_KEY=your_key - -# Identity -MT_USER=yourname -MT_ROLE=admin -``` - ---- - -## Testing - -```bash -# Run all tests -pytest - -# With coverage -pytest --cov=memory_thread - -# Specific test file -pytest tests/test_sdk.py -v -``` - ---- - -## Project Structure - -``` -MemoryThread/ -├── memory_thread/ -│ ├── api/ # REST API (FastAPI) -│ ├── db/ # Database clients -│ ├── nervous/ # Access control, vault, fabric -│ ├── services/ # Core services (TMS, Galaxy, etc.) -│ └── utils/ # CLI, logging, embeddings -├── tests/ # Test suite -├── docs/ # Documentation -├── pyproject.toml # Modern packaging -└── README.md -``` - ---- - -## Contributing - -See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. - -1. Fork the repository -2. Create a feature branch: `git checkout -b feature/amazing` -3. Write tests for your changes -4. Ensure tests pass: `pytest` -5. Submit a pull request - ---- - -## Citation - -If you use Memory Thread in research, please cite: - -```bibtex -@software{memorythread2024, - title = {Memory Thread: A Truth-Preserving Cognitive Memory System}, - author = {Raj, Badal}, - year = {2024}, - url = {https://github.com/badalraj/MemoryThread} -} -``` - ---- - -## License - -MIT License - see [LICENSE](LICENSE) for details. - ---- - -## Acknowledgments - -- Truth Maintenance Systems (TMS) research -- OLAP/Galaxy Schema concepts from data warehousing -- The open-source AI community diff --git a/memory_thread.egg-info/SOURCES.txt b/memory_thread.egg-info/SOURCES.txt deleted file mode 100644 index 4691ae1..0000000 --- a/memory_thread.egg-info/SOURCES.txt +++ /dev/null @@ -1,123 +0,0 @@ -LICENSE -README.md -pyproject.toml -setup.py -memory_thread/chat.py -memory_thread/cli.py -memory_thread/sdk.py -memory_thread.egg-info/PKG-INFO -memory_thread.egg-info/SOURCES.txt -memory_thread.egg-info/dependency_links.txt -memory_thread.egg-info/entry_points.txt -memory_thread.egg-info/requires.txt -memory_thread.egg-info/top_level.txt -memory_thread/api/__init__.py -memory_thread/api/gateway.py -memory_thread/api/main.py -memory_thread/api/server.py -memory_thread/api/routers/maintenance.py -memory_thread/cli/assimilate.py -memory_thread/cli/debug.py -memory_thread/cli/decay.py -memory_thread/cli/graph.py -memory_thread/cli/identity.py -memory_thread/cli/main.py -memory_thread/cli/maintenance.py -memory_thread/cli/maintenance_stub.py -memory_thread/cli/mock_main.py -memory_thread/cli/phase6.py -memory_thread/cli/prune.py -memory_thread/cli/replay.py -memory_thread/cli/replay_stub.py -memory_thread/cli/timewarp_stub.py -memory_thread/config/settings.py -memory_thread/db/async_postgres_client.py -memory_thread/db/async_qdrant_client.py -memory_thread/db/postgres_client.py -memory_thread/db/qdrant_client.py -memory_thread/db/qdrant_setup.py -memory_thread/db/sqlite_client.py -memory_thread/models/entity.py -memory_thread/models/events.py -memory_thread/models/memory_object.py -memory_thread/models/provenance.py -memory_thread/nervous/access_control.py -memory_thread/nervous/audit_ledger.py -memory_thread/nervous/authority_store.py -memory_thread/nervous/auto_bridge.py -memory_thread/nervous/backpressure.py -memory_thread/nervous/client_registry.py -memory_thread/nervous/conflict_resolution.py -memory_thread/nervous/fabric.py -memory_thread/nervous/galaxy_core.py -memory_thread/nervous/persistence_engine.py -memory_thread/nervous/persistence_scheduler.py -memory_thread/nervous/queue_manager.py -memory_thread/nervous/spillover_buffer.py -memory_thread/nervous/vault.py -memory_thread/producers/python_producer.py -memory_thread/services/ancestry_cache.py -memory_thread/services/assimilator.py -memory_thread/services/async_wal.py -memory_thread/services/belief_store.py -memory_thread/services/classify_service.py -memory_thread/services/code_intelligence.py -memory_thread/services/contemplator.py -memory_thread/services/decay_engine.py -memory_thread/services/decay_service.py -memory_thread/services/document_intelligence.py -memory_thread/services/extract_service.py -memory_thread/services/fact_store.py -memory_thread/services/file_ingest_service.py -memory_thread/services/galaxy_query.py -memory_thread/services/graph_service.py -memory_thread/services/hybrid_ner_service.py -memory_thread/services/identity_service.py -memory_thread/services/importance_service.py -memory_thread/services/ingest_service.py -memory_thread/services/maintenance_orchestrator.py -memory_thread/services/meta_stability_service.py -memory_thread/services/observability.py -memory_thread/services/persistence.py -memory_thread/services/pruner.py -memory_thread/services/replay_service.py -memory_thread/services/retrieval_service.py -memory_thread/services/routing_service.py -memory_thread/services/snapshot_service.py -memory_thread/services/temporal_manager.py -memory_thread/services/timewarp_engine.py -memory_thread/services/tms_service.py -memory_thread/services/transaction_manager.py -memory_thread/services/vault_service.py -memory_thread/services/vector_service.py -memory_thread/services/wal.py -memory_thread/services/reasoning/inference_engine.py -memory_thread/services/reasoning/query_engine.py -memory_thread/utils/caching.py -memory_thread/utils/cli_bridge.py -memory_thread/utils/embeddings.py -memory_thread/utils/health.py -memory_thread/utils/llm_provider.py -memory_thread/utils/logger.py -memory_thread/utils/ner.py -memory_thread/utils/regex_extractor.py -memory_thread/utils/secure_sdk.py -memory_thread/utils/shared_cache.py -memory_thread/utils/shared_memory.py -tests/test_api_maintenance.py -tests/test_assimilator.py -tests/test_decay.py -tests/test_galaxy.py -tests/test_identity_service.py -tests/test_orchestrator.py -tests/test_persistence_roundtrip.py -tests/test_phase_3_4.py -tests/test_phase_4_logic.py -tests/test_phase_6_integration.py -tests/test_pruner.py -tests/test_realworld_scenarios.py -tests/test_replay_service.py -tests/test_sdk.py -tests/test_timewarp_engine.py -tests/test_tms_complete.py -tests/test_vault.py \ No newline at end of file diff --git a/memory_thread.egg-info/dependency_links.txt b/memory_thread.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/memory_thread.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/memory_thread.egg-info/entry_points.txt b/memory_thread.egg-info/entry_points.txt deleted file mode 100644 index 04fc70e..0000000 --- a/memory_thread.egg-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -mt = memory_thread.cli:run -mt-api = memory_thread.api.server:main diff --git a/memory_thread.egg-info/requires.txt b/memory_thread.egg-info/requires.txt deleted file mode 100644 index 186bd84..0000000 --- a/memory_thread.egg-info/requires.txt +++ /dev/null @@ -1,43 +0,0 @@ -pydantic>=2.0 -networkx>=3.0 -sentence-transformers>=2.0 -python-dotenv>=1.0 - -[api] -fastapi>=0.100 -uvicorn>=0.20 - -[cli] -typer>=0.9 -rich>=13.0 - -[db] -psycopg2-binary>=2.9 -qdrant-client>=1.5 - -[dev] -pytest>=7.0 -pytest-asyncio>=0.21 -pytest-cov>=4.0 -black>=23.0 -ruff>=0.1 -mypy>=1.0 - -[full] -memory-thread[api,cli,db,nlp,observability,streaming] - -[nlp] -spacy>=3.5 - -[observability] -opentelemetry-api>=1.20 -opentelemetry-sdk>=1.20 -opentelemetry-instrumentation-fastapi>=0.41 -opentelemetry-exporter-otlp>=1.20 - -[streaming] -pyzmq>=25.0 -aiokafka>=0.8 - -[tui] -textual>=0.40 diff --git a/memory_thread.egg-info/top_level.txt b/memory_thread.egg-info/top_level.txt deleted file mode 100644 index d5353fa..0000000 --- a/memory_thread.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -memory_thread diff --git a/memory_thread/cli.py b/memory_thread/cli.py index 9f91acb..7289dad 100644 --- a/memory_thread/cli.py +++ b/memory_thread/cli.py @@ -182,7 +182,7 @@ def main( SSS (godfather) + clear, rootkey, su, sudo """ if version: - console.print("[bold cyan]Memory Thread[/bold cyan] v1.0.0") + console.print("[bold cyan]Memory Thread[/bold cyan] v3.0.0") raise typer.Exit() if role: @@ -604,11 +604,33 @@ def provider_set( @provider_app.command("use") -def provider_use(name: str = typer.Argument(..., help="Provider to activate")): +def provider_use( + name: str = typer.Argument(..., help="Provider to activate"), + model: str = typer.Option(None, "--model", "-m", help="Set model for this provider"), +): """Switch active LLM provider. [dim]B-CLASS[/dim]""" _require(Grade.B_CLASS, "provider use") try: from memory_thread.nervous.vault import vault + + # If model is specified, update the provider config + if model: + if name.lower() == "ollama": + # Special handling for Ollama since it doesn't use API keys + vault.set_provider("ollama", "local", "http://localhost:11434", model, _user()) + else: + # For other providers, we need to preserve existing key/url + creds = vault.get_provider(name, _user()) + if not creds and name.lower() != "local": + console.print(f"[yellow]Provider '{name}' not configured. Use 'mt provider set {name} --key ...' first.[/yellow]") + return + + # Update model while keeping other fields + api_key = creds.get("api_key") if creds else "default" + base_url = creds.get("base_url") if creds else None + vault.set_provider(name, api_key, base_url, model, _user()) + console.print(f"[green]✔ Updated {name} model to: {model}[/green]") + vault.set_active_provider(name, _user()) console.print(f"[green]✔ Switched to: {name}[/green]") except Exception as e: diff --git a/memory_thread/nervous/vault.py b/memory_thread/nervous/vault.py index bae55dc..b3c0301 100644 --- a/memory_thread/nervous/vault.py +++ b/memory_thread/nervous/vault.py @@ -171,14 +171,24 @@ def delete_provider(self, name: str, user_id: str = "default") -> bool: def get_active_provider(self, user_id: str = "default") -> str: """Get active provider for a user.""" + # Try specific user preference user_active = self._cache.get(f"active_provider_{user_id}") if user_active: return user_active - return self._cache.get("active_provider", "local") + + # Try global preference (legacy) + global_active = self._cache.get("active_provider") + if global_active: + return global_active + + return "local" def set_active_provider(self, name: str, user_id: str = "default"): """Set active provider for a user.""" self._cache[f"active_provider_{user_id}"] = name.lower() + # Also set global for backward compat if it's the default user + if user_id == "default": + self._cache["active_provider"] = name.lower() self._save() diff --git a/memory_thread/sdk.py b/memory_thread/sdk.py index aa2f6f7..184bf67 100644 --- a/memory_thread/sdk.py +++ b/memory_thread/sdk.py @@ -1122,14 +1122,21 @@ def chat( # 3. Default fallback (SmolLM) user_id = os.environ.get("MT_USER", "default") - active_provider = vault.get_active_provider(user_id) - log.info(f"Generating response using provider: {active_provider}") + # Check explicit env override first + env_provider = os.environ.get("MT_PROVIDER") + if env_provider: + active_provider = env_provider.lower() + else: + active_provider = vault.get_active_provider(user_id) + + log.debug(f"Chat request - Provider: {active_provider}, User: {user_id}") if active_provider == "ollama": # Get configured model for ollama, or default creds = vault.get_provider("ollama", user_id) model = creds.get("model") if creds else "llama3" + log.debug(f"Calling Ollama with model: {model}") response = self._generate_ollama(full_prompt, model=model) elif active_provider in ["groq", "openrouter", "openai"]: @@ -1137,6 +1144,8 @@ def chat( else: # Fallback to SmolLM (local transformers) + # If active_provider was 'local' or unknown, we land here. + log.debug(f"Falling back to local SmolLM (provider={active_provider})") response = self._generate_smollm(full_prompt) # 6. Remember agent response (lower authority) @@ -1145,25 +1154,56 @@ def chat( return response def _generate_ollama(self, prompt: str, model: str = "llama3") -> str: - """Generate response using local Ollama instance.""" + """Generate response using local Ollama instance via Chat API.""" try: - url = "http://localhost:11434/api/generate" + # Use /api/chat which is better for chat models than /api/generate + url = "http://localhost:11434/api/chat" payload = { "model": model, - "prompt": prompt, - "stream": False + "messages": [{"role": "user", "content": prompt}], + "stream": False, + # Keep context window reasonable + "options": { + "num_ctx": 4096 + } } resp = requests.post(url, json=payload, timeout=60) + if resp.status_code == 200: - return resp.json().get("response", "") + data = resp.json() + # Chat API returns message content in message.content + return data.get("message", {}).get("content", "") + elif resp.status_code == 404: + # Fallback to generate if chat endpoint missing (old versions) or model not found + log.warning(f"Ollama chat endpoint/model failed (404). Trying /api/generate...") + return self._generate_ollama_legacy(prompt, model) else: log.warning(f"Ollama error {resp.status_code}: {resp.text}") - return f"[Ollama failed ({resp.status_code}). Falling back...]" + return f"[Ollama error ({resp.status_code}). Check logs.]" + except requests.exceptions.ConnectionError: + log.warning("Ollama unreachable at localhost:11434") + return "[Ollama unreachable. Is 'ollama serve' running?]" except Exception as e: log.warning(f"Ollama connection failed: {e}") - return f"[Ollama unavailable. ensure 'ollama serve' is running.]" + return f"[Ollama error: {e}]" + + def _generate_ollama_legacy(self, prompt: str, model: str) -> str: + """Fallback for older Ollama versions or completion models.""" + try: + url = "http://localhost:11434/api/generate" + payload = { + "model": model, + "prompt": prompt, + "stream": False + } + resp = requests.post(url, json=payload, timeout=60) + if resp.status_code == 200: + return resp.json().get("response", "") + return f"[Ollama legacy failed ({resp.status_code})]" + except Exception: + return "[Ollama legacy failed]" def _generate_smollm(self, prompt: str) -> str: """Generate response using local SmolLM (Transformers).""" diff --git a/memory_thread/utils/logger.py b/memory_thread/utils/logger.py index d2713af..b7efed3 100644 --- a/memory_thread/utils/logger.py +++ b/memory_thread/utils/logger.py @@ -116,6 +116,12 @@ def get_logger(name: str): logger.addHandler(console_handler) + # Silence noisy libraries unless debugging + if not os.environ.get("MT_DEBUG"): + logging.getLogger("httpx").setLevel(logging.WARNING) + logging.getLogger("httpcore").setLevel(logging.WARNING) + logging.getLogger("urllib3").setLevel(logging.WARNING) + return logger diff --git a/setup.py b/setup.py index 394fccd..3a015e7 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name="memory-thread", - version="1.0.0", + version="3.0.0", packages=find_packages(), python_requires=">=3.9", install_requires=[ @@ -36,7 +36,7 @@ }, author="Badal Raj", description="A truth-preserving cognitive memory system for AI", - long_description=open("README.md").read(), + long_description=open("README.md", encoding="utf-8").read(), long_description_content_type="text/markdown", url="https://github.com/badalraj/MemoryThread", classifiers=[