diff --git a/MEMORY.md b/MEMORY.md index fb17015..e8d7bc5 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -1 +1,71 @@ -Good morning, I hope you had a great night. \ No newline at end of file +# Timmy Hot Memory + +> Working RAM — always loaded, ~300 lines max, pruned monthly +> Last updated: 2026-02-26 + +--- + +## Current Status + +**Agent State:** Operational +**Mode:** Development +**Model:** llama3.2 (local via Ollama) +**Backend:** Ollama on localhost:11434 +**Dashboard:** http://localhost:8000 + +--- + +## Standing Rules + +1. **Sovereignty First** — No cloud AI dependencies +2. **Local-Only Inference** — Ollama on localhost +3. **Privacy by Design** — Telemetry disabled +4. **Tool Minimalism** — Use tools only when necessary +5. **Memory Discipline** — Write handoffs at session end +6. **Clean Output** — Never show JSON, tool calls, or function syntax + +--- + +## System Architecture + +**Memory Tiers:** +- Tier 1 (Hot): This file (MEMORY.md) — always in context +- Tier 2 (Vault): memory/ directory — notes, profiles, AARs +- Tier 3 (Semantic): Vector search over vault content + +**Swarm Agents:** Echo (research), Forge (code), Seer (data) +**Dashboard Pages:** Briefing, Swarm, Spark, Market, Tools, Events, Ledger, Memory, Router, Upgrades, Creative + +--- + +## Agent Roster + +| Agent | Role | Status | +|-------|------|--------| +| Timmy | Core AI | Active | +| Echo | Research & Summarization | Active | +| Forge | Coding & Debugging | Active | +| Seer | Analytics & Prediction | Active | + +--- + +## User Profile + +**Name:** (not set) +**Interests:** (to be learned) + +--- + +## Key Decisions + +(none yet) + +--- + +## Pending Actions + +- [ ] Learn user's name and preferences + +--- + +*Prune date: 2026-03-25* diff --git a/src/dashboard/app.py b/src/dashboard/app.py index 58f77cd..df99e97 100644 --- a/src/dashboard/app.py +++ b/src/dashboard/app.py @@ -121,15 +121,21 @@ async def lifespan(app: FastAPI): if spark_engine.enabled: logger.info("Spark Intelligence active — event capture enabled") - # Auto-start Telegram bot if a token is configured + # Auto-start chat integrations (skip silently if unconfigured) from telegram_bot.bot import telegram_bot - await telegram_bot.start() - - # Auto-start Discord bot and register in platform registry from chat_bridge.vendors.discord import discord_bot from chat_bridge.registry import platform_registry platform_registry.register(discord_bot) - await discord_bot.start() + + if settings.telegram_token: + await telegram_bot.start() + else: + logger.debug("Telegram: no token configured, skipping") + + if settings.discord_token or discord_bot.load_token(): + await discord_bot.start() + else: + logger.debug("Discord: no token configured, skipping") yield diff --git a/src/timmy/agent.py b/src/timmy/agent.py index 26cb6f2..8cbc8d5 100644 --- a/src/timmy/agent.py +++ b/src/timmy/agent.py @@ -138,7 +138,6 @@ def create_timmy( num_history_runs=20, markdown=True, tools=[tools] if tools else None, - show_tool_calls=False, telemetry=settings.telemetry_enabled, ) diff --git a/src/timmy/semantic_memory.py b/src/timmy/semantic_memory.py index 265ee10..86f980c 100644 --- a/src/timmy/semantic_memory.py +++ b/src/timmy/semantic_memory.py @@ -319,6 +319,25 @@ semantic_memory = SemanticMemory() memory_searcher = MemorySearcher() -def memory_search(query: str, top_k: int = 5) -> list[tuple[str, float]]: - """Simple interface for memory search.""" - return semantic_memory.search(query, top_k) +def memory_search(query: str, top_k: int = 5) -> str: + """Search past conversations and notes for relevant context. + + Args: + query: What to search for (e.g. "Bitcoin strategy", "server setup"). + top_k: Number of results to return (default 5). + + Returns: + Formatted string of relevant memory results. + """ + # Guard: model sometimes passes None for top_k + if top_k is None: + top_k = 5 + results = semantic_memory.search(query, top_k) + if not results: + return "No relevant memories found." + parts = [] + for content, score in results: + if score < 0.2: + continue + parts.append(f"[score {score:.2f}] {content[:300]}") + return "\n\n".join(parts) if parts else "No relevant memories found." diff --git a/tests/test_agent.py b/tests/test_agent.py index 1969650..5f7f165 100644 --- a/tests/test_agent.py +++ b/tests/test_agent.py @@ -267,8 +267,8 @@ def test_create_timmy_includes_tools_for_large_model(): assert kwargs["tools"] == [mock_toolkit] -def test_create_timmy_show_tool_calls_false(): - """show_tool_calls should always be False to prevent raw JSON in output.""" +def test_create_timmy_no_show_tool_calls(): + """show_tool_calls must NOT be passed — Agno 2.5.3 doesn't support it.""" with patch("timmy.agent.Agent") as MockAgent, \ patch("timmy.agent.Ollama"), \ patch("timmy.agent.SqliteDb"): @@ -277,4 +277,4 @@ def test_create_timmy_show_tool_calls_false(): create_timmy() kwargs = MockAgent.call_args.kwargs - assert kwargs["show_tool_calls"] is False + assert "show_tool_calls" not in kwargs