Skip to content

Commit 6418557

Browse files
Merge pull request #20 from RichmondAlake/feature/memorizz-cli
chore: bring UI refactors + Anthropic tool fix into main
2 parents f9aa342 + 8393601 commit 6418557

21 files changed

Lines changed: 1436 additions & 1195 deletions

.claude.md

Lines changed: 0 additions & 122 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ jobs:
1717
- uses: actions/setup-python@v5
1818
with:
1919
python-version: ${{ matrix.python-version }}
20-
- name: Install (lean base + dev tools)
21-
run: pip install -e ".[dev]"
22-
- name: Run tests (offline unit suite)
23-
run: pytest tests/ -q
20+
- name: Install (base + dev tools + ui for route tests)
21+
run: pip install -e ".[dev,ui]"
22+
- name: Run tests (deterministic unit suite)
23+
# tests/unit is offline + deterministic. tests/performance is timing/
24+
# stress (flaky on shared CI runners) and tests/integration may need
25+
# live services — run those locally/manually, not as the merge gate.
26+
run: pytest tests/unit -q
2427

2528
lint:
2629
runs-on: ubuntu-latest

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ It provides:
1919
- agent builders and application modes (`assistant`, `workflow`, `deep_research`)
2020
- scheduled automations (cron, interval, one-shot) with optional WhatsApp delivery
2121
- optional internet access, sandbox code execution, skills marketplace, and local web UI
22+
- an interactive, Claude-Code-style terminal CLI (`memorizz`) with persistent memory — see [CLI](#cli)
2223

2324
## Key Capabilities
2425

@@ -41,6 +42,8 @@ Base install:
4142
pip install memorizz
4243
```
4344

45+
The base install also gives you the interactive **`memorizz` CLI** (see [CLI](#cli)) — no extra needed.
46+
4447
Common extras:
4548

4649
```bash

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ dev = [
106106
"flake8>=6.0",
107107
"isort>=5.12",
108108
"pre-commit>=3.0",
109+
"httpx>=0.24",
109110
]
110111
all = [
111112
"anthropic>=0.26.0",

src/memorizz/__init__.py

Lines changed: 76 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,82 +2,101 @@
22
# Licensed under the PolyForm Noncommercial License 1.0.0.
33
# See LICENSE file in the project root for full license information.
44

5+
"""memorizz — a memory framework for AI agents.
6+
7+
The entire public API is resolved lazily (PEP 562 ``__getattr__``) so that a bare
8+
``import memorizz`` — and therefore ``memorizz --help`` / ``--version`` and any
9+
tool that merely imports the package — costs almost nothing: no numpy, no
10+
pydantic model building, no provider SDKs. The heavy modules load only when a
11+
symbol is actually accessed (``from memorizz import MemAgent`` triggers the core
12+
import at that point, exactly as before).
13+
"""
14+
15+
import importlib
516
from importlib.metadata import PackageNotFoundError
617
from importlib.metadata import version as _pkg_version
718

8-
from .conversation_history import is_trace_bundle_entry, strip_trace_bundles
9-
from .coordination import SharedMemory
10-
from .enums import ApplicationMode
11-
from .internet_access import (
12-
FirecrawlProvider,
13-
InternetAccessProvider,
14-
TavilyProvider,
15-
create_internet_access_provider,
16-
)
17-
from .long_term.procedural.toolbox import Toolbox
18-
from .long_term.semantic import KnowledgeBase
19-
from .long_term.semantic.persona import Persona, RoleType
20-
from .memagent import MemAgent, MemAgentModel
21-
from .memagent.builders import (
22-
MemAgentBuilder,
23-
create_assistant,
24-
create_chatbot,
25-
create_deep_research_agent,
26-
create_task_agent,
27-
)
28-
from .memory_provider import MemoryProvider, MemoryType
29-
from .short_term_memory.working_memory.cwm import CWM
30-
from .tool_context import get_tool_context, reset_tool_context, set_tool_context
31-
3219
try:
3320
__version__ = _pkg_version("memorizz")
3421
except PackageNotFoundError: # pragma: no cover - source checkout without install
3522
__version__ = "0.0.0"
3623

3724

38-
# Lazy imports for optional-dependency / heavy-SDK surfaces, so a plain
39-
# `import memorizz` stays lean (no pymongo/oracledb/anthropic/ollama import
40-
# unless the corresponding symbol is actually used).
41-
def __getattr__(name):
42-
if name == "MongoDBProvider":
43-
from .memory_provider.mongodb import MongoDBProvider
25+
# name -> (submodule, attribute). Imported on first attribute access.
26+
_LAZY = {
27+
# Agent
28+
"MemAgent": (".memagent", "MemAgent"),
29+
"MemAgentModel": (".memagent", "MemAgentModel"),
30+
"MemAgentBuilder": (".memagent.builders", "MemAgentBuilder"),
31+
"create_assistant": (".memagent.builders", "create_assistant"),
32+
"create_chatbot": (".memagent.builders", "create_chatbot"),
33+
"create_task_agent": (".memagent.builders", "create_task_agent"),
34+
"create_deep_research_agent": (".memagent.builders", "create_deep_research_agent"),
35+
"ApplicationMode": (".enums", "ApplicationMode"),
36+
# Memory providers + configs
37+
"MemoryProvider": (".memory_provider", "MemoryProvider"),
38+
"MemoryType": (".memory_provider", "MemoryType"),
39+
"MongoDBProvider": (".memory_provider.mongodb", "MongoDBProvider"),
40+
"OracleProvider": (".memory_provider.oracle", "OracleProvider"),
41+
"OracleConfig": (".memory_provider.oracle.provider", "OracleConfig"),
42+
"FileSystemProvider": (".memory_provider.filesystem", "FileSystemProvider"),
43+
"FileSystemConfig": (".memory_provider.filesystem", "FileSystemConfig"),
44+
# LLM providers
45+
"OpenAI": (".llms", "OpenAI"),
46+
"AzureOpenAI": (".llms", "AzureOpenAI"),
47+
"Anthropic": (".llms", "Anthropic"),
48+
"OllamaLLM": (".llms", "OllamaLLM"),
49+
"HuggingFaceLLM": (".llms", "HuggingFaceLLM"),
50+
# Memory primitives
51+
"Persona": (".long_term.semantic.persona", "Persona"),
52+
"RoleType": (".long_term.semantic.persona", "RoleType"),
53+
"Toolbox": (".long_term.procedural.toolbox", "Toolbox"),
54+
"KnowledgeBase": (".long_term.semantic", "KnowledgeBase"),
55+
"CWM": (".short_term_memory.working_memory.cwm", "CWM"),
56+
"SharedMemory": (".coordination", "SharedMemory"),
57+
# Internet access
58+
"InternetAccessProvider": (".internet_access", "InternetAccessProvider"),
59+
"FirecrawlProvider": (".internet_access", "FirecrawlProvider"),
60+
"TavilyProvider": (".internet_access", "TavilyProvider"),
61+
"create_internet_access_provider": (
62+
".internet_access",
63+
"create_internet_access_provider",
64+
),
65+
# Automation
66+
"AutomationJob": (".automation", "AutomationJob"),
67+
"AutomationRun": (".automation", "AutomationRun"),
68+
"AutomationDelivery": (".automation", "AutomationDelivery"),
69+
# Tool context + trace helpers
70+
"get_tool_context": (".tool_context", "get_tool_context"),
71+
"set_tool_context": (".tool_context", "set_tool_context"),
72+
"reset_tool_context": (".tool_context", "reset_tool_context"),
73+
"is_trace_bundle_entry": (".conversation_history", "is_trace_bundle_entry"),
74+
"strip_trace_bundles": (".conversation_history", "strip_trace_bundles"),
75+
}
4476

45-
return MongoDBProvider
77+
78+
def __getattr__(name):
79+
# MongoDBConfig pulls pymongo/bson transitively; give the same actionable
80+
# message as the other optional-dependency surfaces instead of a raw
81+
# ModuleNotFoundError('bson').
4682
if name == "MongoDBConfig":
4783
try:
4884
from .memory_provider.mongodb.provider import MongoDBConfig
4985
except ImportError as exc:
5086
raise ImportError(
5187
'MongoDB support requires pymongo. Install with: pip install "memorizz[mongodb]"'
5288
) from exc
53-
5489
return MongoDBConfig
55-
if name == "OracleProvider":
56-
from .memory_provider.oracle import OracleProvider
57-
58-
return OracleProvider
59-
if name == "OracleConfig":
60-
from .memory_provider.oracle.provider import OracleConfig
61-
62-
return OracleConfig
63-
if name in ("FileSystemProvider", "FileSystemConfig"):
64-
from .memory_provider.filesystem import FileSystemConfig, FileSystemProvider
6590

66-
return FileSystemProvider if name == "FileSystemProvider" else FileSystemConfig
67-
if name in ("OpenAI", "AzureOpenAI", "Anthropic", "OllamaLLM", "HuggingFaceLLM"):
68-
from . import llms
91+
spec = _LAZY.get(name)
92+
if spec is None:
93+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
94+
module = importlib.import_module(spec[0], __name__)
95+
return getattr(module, spec[1])
6996

70-
return getattr(llms, name)
71-
if name in ("AutomationJob", "AutomationRun", "AutomationDelivery"):
72-
from .automation import AutomationDelivery, AutomationJob, AutomationRun
7397

74-
_map = {
75-
"AutomationJob": AutomationJob,
76-
"AutomationRun": AutomationRun,
77-
"AutomationDelivery": AutomationDelivery,
78-
}
79-
return _map[name]
80-
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
98+
def __dir__():
99+
return sorted(__all__)
81100

82101

83102
__all__ = [
@@ -100,7 +119,7 @@ def __getattr__(name):
100119
"OracleConfig",
101120
"FileSystemProvider",
102121
"FileSystemConfig",
103-
# LLM providers (lazy)
122+
# LLM providers
104123
"OpenAI",
105124
"AzureOpenAI",
106125
"Anthropic",
@@ -118,7 +137,7 @@ def __getattr__(name):
118137
"FirecrawlProvider",
119138
"TavilyProvider",
120139
"create_internet_access_provider",
121-
# Automation (lazy)
140+
# Automation
122141
"AutomationJob",
123142
"AutomationRun",
124143
"AutomationDelivery",

src/memorizz/automation/worker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import threading
1313
import time
1414
import uuid
15-
from concurrent.futures import ThreadPoolExecutor, as_completed
15+
from concurrent.futures import ThreadPoolExecutor
1616
from datetime import datetime, timezone
1717
from typing import Any, Optional
1818

0 commit comments

Comments
 (0)