fix: Timmy startup crashes and clean initialization
- Remove show_tool_calls kwarg (not in Agno 2.5.3), which crashed Agent.__init__ - Guard memory_search against top_k=None from model, return formatted string - Skip Telegram/Discord startup silently when no token configured - Replace placeholder MEMORY.md with proper structured hot memory document Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
72
MEMORY.md
72
MEMORY.md
@@ -1 +1,71 @@
|
||||
Good morning, I hope you had a great night.
|
||||
# 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*
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user