Claude/remove persona system f vgt m (#126)
* Remove persona system, identity, and all Timmy references
Strip the codebase to pure orchestration logic:
- Delete TIMMY_IDENTITY.md and memory/self/identity.md
- Gut brain/identity.py to no-op stubs (empty returns)
- Remove all system prompts reinforcing Timmy's character, faith,
sovereignty, sign-off ("Sir, affirmative"), and agent roster
- Replace identity-laden prompts with generic local-AI-assistant prompts
- Remove "You work for Timmy" from all sub-agent system prompts
- Rename PersonaTools → AgentTools, PERSONA_TOOLKITS → AGENT_TOOLKITS
- Replace "timmy" agent ID with "orchestrator" across routes, marketplace,
tools catalog, and orchestrator class
- Strip Timmy references from config comments, templates, telegram bot,
chat API, and dashboard UI
- Delete tests/brain/test_identity.py entirely
- Fix all test assertions that checked for persona identity content
729 tests pass (2 pre-existing failures in test_calm.py unrelated).
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
* Add Taskosaur (PM + AI task execution) to docker-compose
Spins up Taskosaur alongside the dashboard on `docker compose up`:
- postgres:16-alpine (port 5432, Taskosaur DB)
- redis:7-alpine (Bull queue backend)
- taskosaur (ports 3000 API / 3001 UI)
- dashboard now depends_on taskosaur healthy
- TASKOSAUR_API_URL injected into dashboard environment
Dashboard can reach Taskosaur at http://taskosaur:3000/api on the
internal network. Frontend UI accessible at http://localhost:3001.
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 12:00:49 -05:00
|
|
|
"""Agent creation with three-tier memory system.
|
2026-02-25 18:07:44 -05:00
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
Memory Architecture:
|
|
|
|
|
- Tier 1 (Hot): MEMORY.md — always loaded, ~300 lines
|
2026-02-25 19:18:08 -05:00
|
|
|
- Tier 2 (Vault): memory/ — structured markdown, append-only
|
|
|
|
|
- Tier 3 (Semantic): Vector search over vault files
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
Model Management:
|
|
|
|
|
- Pulls requested model automatically if not available
|
|
|
|
|
- Falls back through capability-based model chains
|
|
|
|
|
- Multi-modal support with vision model fallbacks
|
|
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
Handoff Protocol maintains continuity across sessions.
|
2026-02-25 18:07:44 -05:00
|
|
|
"""
|
|
|
|
|
|
2026-02-25 19:18:08 -05:00
|
|
|
import logging
|
ruff (#169)
* polish: streamline nav, extract inline styles, improve tablet UX
- Restructure desktop nav from 8+ flat links + overflow dropdown into
5 grouped dropdowns (Core, Agents, Intel, System, More) matching
the mobile menu structure to reduce decision fatigue
- Extract all inline styles from mission_control.html and base.html
notification elements into mission-control.css with semantic classes
- Replace JS-built innerHTML with secure DOM construction in
notification loader and chat history
- Add CONNECTING state to connection indicator (amber) instead of
showing OFFLINE before WebSocket connects
- Add tablet breakpoint (1024px) with larger touch targets for
Apple Pencil / stylus use and safe-area padding for iPad toolbar
- Add active-link highlighting in desktop dropdown menus
- Rename "Mission Control" page title to "System Overview" to
disambiguate from the chat home page
- Add "Home — Timmy Time" page title to index.html
https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h
* fix(security): move auth-gate credentials to environment variables
Hardcoded username, password, and HMAC secret in auth-gate.py replaced
with os.environ lookups. Startup now refuses to run if any variable is
unset. Added AUTH_GATE_SECRET/USER/PASS to .env.example.
https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h
* refactor(tooling): migrate from black+isort+bandit to ruff
Replace three separate linting/formatting tools with a single ruff
invocation. Updates tox.ini (lint, format, pre-push, pre-commit envs),
.pre-commit-config.yaml, and CI workflow. Fixes all ruff errors
including unused imports, missing raise-from, and undefined names.
Ruff config maps existing bandit skips to equivalent S-rules.
https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-11 12:23:35 -04:00
|
|
|
from typing import TYPE_CHECKING, Union
|
2026-02-21 16:53:16 +00:00
|
|
|
|
2026-03-14 18:24:00 -04:00
|
|
|
import httpx
|
2026-02-19 19:05:01 +00:00
|
|
|
from agno.agent import Agent
|
|
|
|
|
from agno.db.sqlite import SqliteDb
|
2026-02-21 16:53:16 +00:00
|
|
|
from agno.models.ollama import Ollama
|
2026-02-19 19:05:01 +00:00
|
|
|
|
2026-03-05 18:56:52 -05:00
|
|
|
from config import check_ollama_model_available, settings
|
2026-02-25 19:18:08 -05:00
|
|
|
from timmy.prompts import get_system_prompt
|
feat: swarm E2E, MCP tools, timmy-serve L402, tests, notifications
Major Features:
- Auto-spawn persona agents (Echo, Forge, Seer) on app startup
- WebSocket broadcasts for real-time swarm UI updates
- MCP tool integration: web search, file I/O, shell, Python execution
- New /tools dashboard page showing agent capabilities
- Real timmy-serve start with L402 payment gating middleware
- Browser push notifications for briefings and task events
Tests:
- test_docker_agent.py: 9 tests for Docker agent runner
- test_swarm_integration_full.py: 18 E2E lifecycle tests
- Fixed all pytest warnings (436 tests, 0 warnings)
Improvements:
- Fixed coroutine warnings in coordinator broadcasts
- Fixed ResourceWarning for unclosed process pipes
- Added pytest-asyncio config to pyproject.toml
- Test isolation with proper event loop cleanup
2026-02-22 19:01:04 -05:00
|
|
|
from timmy.tools import create_full_toolkit
|
2026-02-21 16:53:16 +00:00
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
2026-03-19 20:46:20 -04:00
|
|
|
from timmy.backends import ClaudeBackend, GrokBackend
|
2026-02-21 16:53:16 +00:00
|
|
|
|
2026-02-25 19:18:08 -05:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
2026-02-21 16:53:16 +00:00
|
|
|
# Union type for callers that want to hint the return type.
|
2026-03-19 20:46:20 -04:00
|
|
|
TimmyAgent = Union[Agent, "GrokBackend", "ClaudeBackend"]
|
2026-02-21 16:53:16 +00:00
|
|
|
|
2026-02-25 19:18:08 -05:00
|
|
|
# Models known to be too small for reliable tool calling.
|
|
|
|
|
# These hallucinate tool calls as text, invoke tools randomly,
|
|
|
|
|
# and leak raw JSON into responses.
|
|
|
|
|
_SMALL_MODEL_PATTERNS = (
|
|
|
|
|
"llama3.2",
|
|
|
|
|
"phi-3",
|
|
|
|
|
"gemma:2b",
|
|
|
|
|
"tinyllama",
|
|
|
|
|
"qwen2:0.5b",
|
|
|
|
|
"qwen2:1.5b",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
def _check_model_available(model_name: str) -> bool:
|
|
|
|
|
"""Check if an Ollama model is available locally."""
|
2026-03-05 18:56:52 -05:00
|
|
|
return check_ollama_model_available(model_name)
|
2026-02-26 22:29:44 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def _pull_model(model_name: str) -> bool:
|
|
|
|
|
"""Attempt to pull a model from Ollama.
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
Returns:
|
|
|
|
|
True if successful or model already exists
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
import json
|
2026-03-08 12:50:44 -04:00
|
|
|
import urllib.request
|
|
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
logger.info("Pulling model: %s", model_name)
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-03-19 19:18:22 -04:00
|
|
|
url = settings.normalized_ollama_url
|
2026-02-26 22:29:44 -05:00
|
|
|
req = urllib.request.Request(
|
|
|
|
|
f"{url}/api/pull",
|
|
|
|
|
method="POST",
|
|
|
|
|
headers={"Content-Type": "application/json"},
|
|
|
|
|
data=json.dumps({"name": model_name, "stream": False}).encode(),
|
|
|
|
|
)
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
with urllib.request.urlopen(req, timeout=300) as response:
|
|
|
|
|
if response.status == 200:
|
|
|
|
|
logger.info("Successfully pulled model: %s", model_name)
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
logger.error("Failed to pull %s: HTTP %s", model_name, response.status)
|
|
|
|
|
return False
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
except Exception as exc:
|
|
|
|
|
logger.error("Error pulling model %s: %s", model_name, exc)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _resolve_model_with_fallback(
|
ruff (#169)
* polish: streamline nav, extract inline styles, improve tablet UX
- Restructure desktop nav from 8+ flat links + overflow dropdown into
5 grouped dropdowns (Core, Agents, Intel, System, More) matching
the mobile menu structure to reduce decision fatigue
- Extract all inline styles from mission_control.html and base.html
notification elements into mission-control.css with semantic classes
- Replace JS-built innerHTML with secure DOM construction in
notification loader and chat history
- Add CONNECTING state to connection indicator (amber) instead of
showing OFFLINE before WebSocket connects
- Add tablet breakpoint (1024px) with larger touch targets for
Apple Pencil / stylus use and safe-area padding for iPad toolbar
- Add active-link highlighting in desktop dropdown menus
- Rename "Mission Control" page title to "System Overview" to
disambiguate from the chat home page
- Add "Home — Timmy Time" page title to index.html
https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h
* fix(security): move auth-gate credentials to environment variables
Hardcoded username, password, and HMAC secret in auth-gate.py replaced
with os.environ lookups. Startup now refuses to run if any variable is
unset. Added AUTH_GATE_SECRET/USER/PASS to .env.example.
https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h
* refactor(tooling): migrate from black+isort+bandit to ruff
Replace three separate linting/formatting tools with a single ruff
invocation. Updates tox.ini (lint, format, pre-push, pre-commit envs),
.pre-commit-config.yaml, and CI workflow. Fixes all ruff errors
including unused imports, missing raise-from, and undefined names.
Ruff config maps existing bandit skips to equivalent S-rules.
https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-11 12:23:35 -04:00
|
|
|
requested_model: str | None = None,
|
2026-02-26 22:29:44 -05:00
|
|
|
require_vision: bool = False,
|
|
|
|
|
auto_pull: bool = True,
|
|
|
|
|
) -> tuple[str, bool]:
|
|
|
|
|
"""Resolve model with automatic pulling and fallback.
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
Args:
|
|
|
|
|
requested_model: Preferred model to use
|
|
|
|
|
require_vision: Whether the model needs vision capabilities
|
|
|
|
|
auto_pull: Whether to attempt pulling missing models
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
Returns:
|
|
|
|
|
Tuple of (model_name, is_fallback)
|
|
|
|
|
"""
|
|
|
|
|
model = requested_model or settings.ollama_model
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
# Check if requested model is available
|
|
|
|
|
if _check_model_available(model):
|
|
|
|
|
logger.debug("Using available model: %s", model)
|
|
|
|
|
return model, False
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
# Try to pull the requested model
|
|
|
|
|
if auto_pull:
|
|
|
|
|
logger.info("Model %s not available locally, attempting to pull...", model)
|
|
|
|
|
if _pull_model(model):
|
|
|
|
|
return model, False
|
|
|
|
|
logger.warning("Failed to pull %s, checking fallbacks...", model)
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-03-14 17:26:47 -04:00
|
|
|
# Use appropriate configurable fallback chain (from settings / env vars)
|
|
|
|
|
fallback_chain = settings.vision_fallback_models if require_vision else settings.fallback_models
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
for fallback_model in fallback_chain:
|
|
|
|
|
if _check_model_available(fallback_model):
|
2026-03-08 12:50:44 -04:00
|
|
|
logger.warning("Using fallback model %s (requested: %s)", fallback_model, model)
|
2026-02-26 22:29:44 -05:00
|
|
|
return fallback_model, True
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
# Try to pull the fallback
|
|
|
|
|
if auto_pull and _pull_model(fallback_model):
|
2026-03-08 12:50:44 -04:00
|
|
|
logger.info("Pulled and using fallback model %s (requested: %s)", fallback_model, model)
|
2026-02-26 22:29:44 -05:00
|
|
|
return fallback_model, True
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
# Absolute last resort - return the requested model and hope for the best
|
2026-03-08 12:50:44 -04:00
|
|
|
logger.error("No models available in fallback chain. Requested: %s", model)
|
2026-02-26 22:29:44 -05:00
|
|
|
return model, False
|
|
|
|
|
|
|
|
|
|
|
2026-02-25 19:18:08 -05:00
|
|
|
def _model_supports_tools(model_name: str) -> bool:
|
|
|
|
|
"""Check if the configured model can reliably handle tool calling.
|
|
|
|
|
|
|
|
|
|
Small models (< 7B) tend to hallucinate tool calls as text or invoke
|
|
|
|
|
them randomly. For these models, it's better to run tool-free and let
|
|
|
|
|
the model answer directly from its training data.
|
|
|
|
|
"""
|
|
|
|
|
model_lower = model_name.lower()
|
|
|
|
|
for pattern in _SMALL_MODEL_PATTERNS:
|
|
|
|
|
if pattern in model_lower:
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
2026-02-21 16:53:16 +00:00
|
|
|
|
2026-03-14 18:24:00 -04:00
|
|
|
def _warmup_model(model_name: str) -> bool:
|
|
|
|
|
"""Warm up an Ollama model by sending a minimal generation request.
|
|
|
|
|
|
|
|
|
|
This prevents 'Server disconnected' errors on first request after cold model load.
|
|
|
|
|
Cold loads can take 30-40s, so we use a 60s timeout.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
model_name: Name of the Ollama model to warm up
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
True if warmup succeeded, False otherwise (does not raise)
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
response = httpx.post(
|
|
|
|
|
f"{settings.ollama_url}/api/generate",
|
|
|
|
|
json={"model": model_name, "prompt": "hi", "options": {"num_predict": 1}},
|
|
|
|
|
timeout=60.0,
|
|
|
|
|
)
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
logger.info("Model %s warmed up successfully", model_name)
|
|
|
|
|
return True
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
logger.warning("Model warmup failed: %s — first request may disconnect", exc)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2026-02-21 16:53:16 +00:00
|
|
|
def _resolve_backend(requested: str | None) -> str:
|
2026-03-19 20:46:20 -04:00
|
|
|
"""Return the backend name to use.
|
2026-02-21 16:53:16 +00:00
|
|
|
|
2026-03-19 20:46:20 -04:00
|
|
|
Priority (highest -> lowest):
|
2026-02-21 16:53:16 +00:00
|
|
|
1. CLI flag passed directly to create_timmy()
|
|
|
|
|
2. TIMMY_MODEL_BACKEND env var / .env setting
|
2026-03-19 20:46:20 -04:00
|
|
|
3. 'ollama' (safe default -- no surprises)
|
2026-02-21 16:53:16 +00:00
|
|
|
"""
|
|
|
|
|
if requested is not None:
|
|
|
|
|
return requested
|
|
|
|
|
|
2026-03-19 20:46:20 -04:00
|
|
|
return settings.timmy_model_backend # "ollama" | "grok" | "claude"
|
2026-02-21 16:53:16 +00:00
|
|
|
|
|
|
|
|
|
2026-03-19 19:51:59 -04:00
|
|
|
def _build_tools_list(use_tools: bool, skip_mcp: bool, model_name: str) -> list:
|
|
|
|
|
"""Assemble the tools list based on model capability and MCP flags.
|
|
|
|
|
|
|
|
|
|
Returns a list of Toolkit / MCPTools objects, or an empty list.
|
|
|
|
|
"""
|
|
|
|
|
if not use_tools:
|
|
|
|
|
logger.info("Tools disabled for model %s (too small for reliable tool calling)", model_name)
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
tools_list: list = [create_full_toolkit()]
|
|
|
|
|
|
|
|
|
|
# Add MCP tool servers (lazy-connected on first arun()).
|
|
|
|
|
# Skipped when skip_mcp=True — MCP's stdio transport uses anyio cancel
|
|
|
|
|
# scopes that conflict with asyncio background task cancellation (#72).
|
|
|
|
|
if not skip_mcp:
|
|
|
|
|
try:
|
|
|
|
|
from timmy.mcp_tools import create_filesystem_mcp_tools, create_gitea_mcp_tools
|
|
|
|
|
|
|
|
|
|
gitea_mcp = create_gitea_mcp_tools()
|
|
|
|
|
if gitea_mcp:
|
|
|
|
|
tools_list.append(gitea_mcp)
|
|
|
|
|
|
|
|
|
|
fs_mcp = create_filesystem_mcp_tools()
|
|
|
|
|
if fs_mcp:
|
|
|
|
|
tools_list.append(fs_mcp)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
logger.debug("MCP tools unavailable: %s", exc)
|
|
|
|
|
|
|
|
|
|
return tools_list
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _build_prompt(use_tools: bool, session_id: str) -> str:
|
|
|
|
|
"""Build the full system prompt with optional memory context."""
|
|
|
|
|
base_prompt = get_system_prompt(tools_enabled=use_tools, session_id=session_id)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from timmy.memory_system import memory_system
|
|
|
|
|
|
|
|
|
|
memory_context = memory_system.get_system_context()
|
|
|
|
|
if memory_context:
|
|
|
|
|
# Smaller budget for small models — expanded prompt uses more tokens
|
|
|
|
|
max_context = 2000 if not use_tools else 8000
|
|
|
|
|
if len(memory_context) > max_context:
|
|
|
|
|
memory_context = memory_context[:max_context] + "\n... [truncated]"
|
|
|
|
|
return (
|
|
|
|
|
f"{base_prompt}\n\n"
|
|
|
|
|
f"## GROUNDED CONTEXT (verified sources — cite when using)\n\n"
|
|
|
|
|
f"{memory_context}"
|
|
|
|
|
)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
logger.warning("Failed to load memory context: %s", exc)
|
|
|
|
|
|
|
|
|
|
return base_prompt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _create_ollama_agent(
|
|
|
|
|
*,
|
|
|
|
|
db_file: str,
|
|
|
|
|
model_name: str,
|
|
|
|
|
tools_list: list,
|
|
|
|
|
full_prompt: str,
|
|
|
|
|
use_tools: bool,
|
|
|
|
|
) -> Agent:
|
|
|
|
|
"""Construct the Agno Agent with Ollama backend and warm up the model."""
|
|
|
|
|
model_kwargs = {}
|
|
|
|
|
if settings.ollama_num_ctx > 0:
|
|
|
|
|
model_kwargs["options"] = {"num_ctx": settings.ollama_num_ctx}
|
|
|
|
|
|
|
|
|
|
agent = Agent(
|
|
|
|
|
name="Agent",
|
|
|
|
|
model=Ollama(id=model_name, host=settings.ollama_url, timeout=300, **model_kwargs),
|
|
|
|
|
db=SqliteDb(db_file=db_file),
|
|
|
|
|
description=full_prompt,
|
|
|
|
|
add_history_to_context=True,
|
|
|
|
|
num_history_runs=20,
|
|
|
|
|
markdown=False,
|
|
|
|
|
tools=tools_list if tools_list else None,
|
|
|
|
|
tool_call_limit=settings.max_agent_steps if use_tools else None,
|
|
|
|
|
telemetry=settings.telemetry_enabled,
|
|
|
|
|
)
|
|
|
|
|
_warmup_model(model_name)
|
|
|
|
|
return agent
|
|
|
|
|
|
|
|
|
|
|
2026-02-21 16:53:16 +00:00
|
|
|
def create_timmy(
|
|
|
|
|
db_file: str = "timmy.db",
|
|
|
|
|
backend: str | None = None,
|
2026-03-14 16:34:48 -04:00
|
|
|
*,
|
|
|
|
|
skip_mcp: bool = False,
|
2026-03-14 19:43:11 -04:00
|
|
|
session_id: str = "unknown",
|
2026-02-21 16:53:16 +00:00
|
|
|
) -> TimmyAgent:
|
2026-03-19 20:46:20 -04:00
|
|
|
"""Instantiate the agent — Ollama, Grok, or Claude.
|
2026-02-21 16:53:16 +00:00
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
db_file: SQLite file for Agno conversation memory (Ollama path only).
|
2026-03-19 20:46:20 -04:00
|
|
|
backend: "ollama" | "grok" | "claude" | None (reads config/env).
|
2026-03-14 16:34:48 -04:00
|
|
|
skip_mcp: If True, omit MCP tool servers (Gitea, filesystem).
|
|
|
|
|
Use for background tasks (thinking, QA) where MCP's
|
|
|
|
|
stdio cancel-scope lifecycle conflicts with asyncio
|
|
|
|
|
task cancellation.
|
2026-02-21 16:53:16 +00:00
|
|
|
|
Claude/remove persona system f vgt m (#126)
* Remove persona system, identity, and all Timmy references
Strip the codebase to pure orchestration logic:
- Delete TIMMY_IDENTITY.md and memory/self/identity.md
- Gut brain/identity.py to no-op stubs (empty returns)
- Remove all system prompts reinforcing Timmy's character, faith,
sovereignty, sign-off ("Sir, affirmative"), and agent roster
- Replace identity-laden prompts with generic local-AI-assistant prompts
- Remove "You work for Timmy" from all sub-agent system prompts
- Rename PersonaTools → AgentTools, PERSONA_TOOLKITS → AGENT_TOOLKITS
- Replace "timmy" agent ID with "orchestrator" across routes, marketplace,
tools catalog, and orchestrator class
- Strip Timmy references from config comments, templates, telegram bot,
chat API, and dashboard UI
- Delete tests/brain/test_identity.py entirely
- Fix all test assertions that checked for persona identity content
729 tests pass (2 pre-existing failures in test_calm.py unrelated).
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
* Add Taskosaur (PM + AI task execution) to docker-compose
Spins up Taskosaur alongside the dashboard on `docker compose up`:
- postgres:16-alpine (port 5432, Taskosaur DB)
- redis:7-alpine (Bull queue backend)
- taskosaur (ports 3000 API / 3001 UI)
- dashboard now depends_on taskosaur healthy
- TASKOSAUR_API_URL injected into dashboard environment
Dashboard can reach Taskosaur at http://taskosaur:3000/api on the
internal network. Frontend UI accessible at http://localhost:3001.
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 12:00:49 -05:00
|
|
|
Returns an Agno Agent or backend-specific agent — all expose
|
2026-02-21 16:53:16 +00:00
|
|
|
print_response(message, stream).
|
|
|
|
|
"""
|
|
|
|
|
resolved = _resolve_backend(backend)
|
2026-02-19 19:05:01 +00:00
|
|
|
|
2026-02-28 09:35:44 -05:00
|
|
|
if resolved == "claude":
|
|
|
|
|
from timmy.backends import ClaudeBackend
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-28 09:35:44 -05:00
|
|
|
return ClaudeBackend()
|
|
|
|
|
|
feat: add Grok (xAI) as opt-in premium backend with monetization
- Add GrokBackend class in src/timmy/backends.py with full sync/async
support, health checks, usage stats, and cost estimation in sats
- Add consult_grok tool to Timmy's toolkit for proactive Grok queries
- Extend cascade router with Grok provider type for failover chain
- Add Grok Mode toggle card to Mission Control dashboard (HTMX live)
- Add "Ask Grok" button on chat input for direct Grok queries
- Add /grok/* routes: status, toggle, chat, stats endpoints
- Integrate Lightning invoice generation for Grok usage monetization
- Add GROK_ENABLED, XAI_API_KEY, GROK_DEFAULT_MODEL, GROK_MAX_SATS_PER_QUERY,
GROK_FREE config settings via pydantic-settings
- Update .env.example and docker-compose.yml with Grok env vars
- Add 21 tests covering backend, tools, and route endpoints (all green)
Local-first ethos preserved: Grok is premium augmentation only,
disabled by default, and Lightning-payable when enabled.
https://claude.ai/code/session_01FygwN8wS8J6WGZ8FPb7XGV
2026-02-27 01:12:51 +00:00
|
|
|
if resolved == "grok":
|
|
|
|
|
from timmy.backends import GrokBackend
|
2026-03-08 12:50:44 -04:00
|
|
|
|
feat: add Grok (xAI) as opt-in premium backend with monetization
- Add GrokBackend class in src/timmy/backends.py with full sync/async
support, health checks, usage stats, and cost estimation in sats
- Add consult_grok tool to Timmy's toolkit for proactive Grok queries
- Extend cascade router with Grok provider type for failover chain
- Add Grok Mode toggle card to Mission Control dashboard (HTMX live)
- Add "Ask Grok" button on chat input for direct Grok queries
- Add /grok/* routes: status, toggle, chat, stats endpoints
- Integrate Lightning invoice generation for Grok usage monetization
- Add GROK_ENABLED, XAI_API_KEY, GROK_DEFAULT_MODEL, GROK_MAX_SATS_PER_QUERY,
GROK_FREE config settings via pydantic-settings
- Update .env.example and docker-compose.yml with Grok env vars
- Add 21 tests covering backend, tools, and route endpoints (all green)
Local-first ethos preserved: Grok is premium augmentation only,
disabled by default, and Lightning-payable when enabled.
https://claude.ai/code/session_01FygwN8wS8J6WGZ8FPb7XGV
2026-02-27 01:12:51 +00:00
|
|
|
return GrokBackend()
|
|
|
|
|
|
2026-02-21 16:53:16 +00:00
|
|
|
# Default: Ollama via Agno.
|
2026-02-26 22:29:44 -05:00
|
|
|
model_name, is_fallback = _resolve_model_with_fallback(
|
|
|
|
|
requested_model=None,
|
|
|
|
|
require_vision=False,
|
|
|
|
|
auto_pull=True,
|
|
|
|
|
)
|
2026-02-28 09:35:44 -05:00
|
|
|
|
|
|
|
|
if not _check_model_available(model_name):
|
cleanup: delete dead modules — ~7,900 lines removed
Closes #22, Closes #23
Deleted: brain/, swarm/, openfang/, paperclip/, cascade_adapter,
memory_migrate, agents/timmy.py, dead routes + all corresponding tests.
Updated pyproject.toml, app.py, loop_qa.py for removed imports.
2026-03-14 09:49:24 -04:00
|
|
|
logger.error(
|
|
|
|
|
"Ollama unreachable and no local models available. "
|
|
|
|
|
"Start Ollama with 'ollama serve' or use --backend claude explicitly."
|
|
|
|
|
)
|
2026-02-28 09:35:44 -05:00
|
|
|
|
2026-02-26 22:29:44 -05:00
|
|
|
if is_fallback:
|
|
|
|
|
logger.info("Using fallback model %s (requested was unavailable)", model_name)
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-25 19:18:08 -05:00
|
|
|
use_tools = _model_supports_tools(model_name)
|
2026-03-19 19:51:59 -04:00
|
|
|
tools_list = _build_tools_list(use_tools, skip_mcp, model_name)
|
|
|
|
|
full_prompt = _build_prompt(use_tools, session_id)
|
|
|
|
|
|
|
|
|
|
return _create_ollama_agent(
|
|
|
|
|
db_file=db_file,
|
|
|
|
|
model_name=model_name,
|
|
|
|
|
tools_list=tools_list,
|
|
|
|
|
full_prompt=full_prompt,
|
|
|
|
|
use_tools=use_tools,
|
2026-02-19 19:05:01 +00:00
|
|
|
)
|
2026-02-25 18:07:44 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class TimmyWithMemory:
|
Claude/remove persona system f vgt m (#126)
* Remove persona system, identity, and all Timmy references
Strip the codebase to pure orchestration logic:
- Delete TIMMY_IDENTITY.md and memory/self/identity.md
- Gut brain/identity.py to no-op stubs (empty returns)
- Remove all system prompts reinforcing Timmy's character, faith,
sovereignty, sign-off ("Sir, affirmative"), and agent roster
- Replace identity-laden prompts with generic local-AI-assistant prompts
- Remove "You work for Timmy" from all sub-agent system prompts
- Rename PersonaTools → AgentTools, PERSONA_TOOLKITS → AGENT_TOOLKITS
- Replace "timmy" agent ID with "orchestrator" across routes, marketplace,
tools catalog, and orchestrator class
- Strip Timmy references from config comments, templates, telegram bot,
chat API, and dashboard UI
- Delete tests/brain/test_identity.py entirely
- Fix all test assertions that checked for persona identity content
729 tests pass (2 pre-existing failures in test_calm.py unrelated).
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
* Add Taskosaur (PM + AI task execution) to docker-compose
Spins up Taskosaur alongside the dashboard on `docker compose up`:
- postgres:16-alpine (port 5432, Taskosaur DB)
- redis:7-alpine (Bull queue backend)
- taskosaur (ports 3000 API / 3001 UI)
- dashboard now depends_on taskosaur healthy
- TASKOSAUR_API_URL injected into dashboard environment
Dashboard can reach Taskosaur at http://taskosaur:3000/api on the
internal network. Frontend UI accessible at http://localhost:3001.
https://claude.ai/code/session_01LjQGUE6nk9W9674zaxrYxy
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 12:00:49 -05:00
|
|
|
"""Agent wrapper with explicit three-tier memory management."""
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-25 18:07:44 -05:00
|
|
|
def __init__(self, db_file: str = "timmy.db") -> None:
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
from timmy.memory_system import memory_system
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-02-25 18:07:44 -05:00
|
|
|
self.agent = create_timmy(db_file=db_file)
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
self.memory = memory_system
|
|
|
|
|
self.session_active = True
|
2026-03-08 12:50:44 -04:00
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
# Store initial context for reference
|
|
|
|
|
self.initial_context = self.memory.get_system_context()
|
2026-03-08 12:50:44 -04:00
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
def chat(self, message: str) -> str:
|
2026-03-15 14:28:47 -04:00
|
|
|
"""Simple chat interface that tracks in memory.
|
|
|
|
|
|
|
|
|
|
Retries on transient Ollama errors (GPU contention, timeouts)
|
|
|
|
|
with exponential backoff (#70).
|
|
|
|
|
"""
|
|
|
|
|
import time
|
|
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
# Check for user facts to extract
|
|
|
|
|
self._extract_and_store_facts(message)
|
2026-03-08 12:50:44 -04:00
|
|
|
|
2026-03-15 14:28:47 -04:00
|
|
|
# Retry with backoff — GPU contention causes ReadError/ReadTimeout
|
|
|
|
|
max_retries = 3
|
|
|
|
|
for attempt in range(1, max_retries + 1):
|
|
|
|
|
try:
|
|
|
|
|
result = self.agent.run(message, stream=False)
|
|
|
|
|
return result.content if hasattr(result, "content") else str(result)
|
|
|
|
|
except (
|
|
|
|
|
httpx.ConnectError,
|
|
|
|
|
httpx.ReadError,
|
|
|
|
|
httpx.ReadTimeout,
|
|
|
|
|
httpx.ConnectTimeout,
|
|
|
|
|
ConnectionError,
|
|
|
|
|
TimeoutError,
|
|
|
|
|
) as exc:
|
|
|
|
|
if attempt < max_retries:
|
|
|
|
|
wait = min(2**attempt, 16)
|
|
|
|
|
logger.warning(
|
|
|
|
|
"Ollama contention on attempt %d/%d: %s. Waiting %ds before retry...",
|
|
|
|
|
attempt,
|
|
|
|
|
max_retries,
|
|
|
|
|
type(exc).__name__,
|
|
|
|
|
wait,
|
|
|
|
|
)
|
|
|
|
|
time.sleep(wait)
|
|
|
|
|
else:
|
|
|
|
|
logger.error(
|
|
|
|
|
"Ollama unreachable after %d attempts: %s",
|
|
|
|
|
max_retries,
|
|
|
|
|
exc,
|
|
|
|
|
)
|
|
|
|
|
raise
|
2026-03-08 12:50:44 -04:00
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
def _extract_and_store_facts(self, message: str) -> None:
|
|
|
|
|
"""Extract user facts from message and store in memory."""
|
2026-03-11 21:11:53 -04:00
|
|
|
try:
|
|
|
|
|
from timmy.conversation import conversation_manager
|
|
|
|
|
|
|
|
|
|
name = conversation_manager.extract_user_name(message)
|
|
|
|
|
if name:
|
|
|
|
|
self.memory.update_user_fact("Name", name)
|
|
|
|
|
self.memory.record_decision(f"Learned user's name: {name}")
|
2026-03-14 19:07:14 -04:00
|
|
|
except Exception as exc:
|
|
|
|
|
logger.warning("User name extraction failed: %s", exc)
|
2026-03-11 21:11:53 -04:00
|
|
|
pass # Best-effort extraction
|
2026-03-08 12:50:44 -04:00
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
def end_session(self, summary: str = "Session completed") -> None:
|
|
|
|
|
"""End session and write handoff."""
|
|
|
|
|
if self.session_active:
|
|
|
|
|
self.memory.end_session(summary)
|
|
|
|
|
self.session_active = False
|
2026-03-08 12:50:44 -04:00
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
def __enter__(self):
|
|
|
|
|
return self
|
2026-03-08 12:50:44 -04:00
|
|
|
|
Implement three-tier memory architecture (Hot/Vault/Handoff)
This commit replaces the previous memory_layers.py with a proper three-tier
memory system as specified by the user:
## Tier 1 — Hot Memory (MEMORY.md)
- Single flat file always loaded into system context
- Contains: current status, standing rules, agent roster, key decisions
- ~300 lines max, pruned monthly
- Managed by HotMemory class
## Tier 2 — Structured Vault (memory/)
- Directory with three namespaces:
• self/ — identity.md, user_profile.md, methodology.md
• notes/ — session logs, AARs, research
• aar/ — post-task retrospectives
- Markdown format, Obsidian-compatible
- Append-only, date-stamped
- Managed by VaultMemory class
## Handoff Protocol
- last-session-handoff.md written at session end
- Contains: summary, key decisions, open items, next steps
- Auto-loaded at next session start
- Maintains continuity across resets
## Implementation
### New Files:
- src/timmy/memory_system.py — Core memory system
- MEMORY.md — Hot memory template
- memory/self/*.md — Identity, user profile, methodology
### Modified:
- src/timmy/agent.py — Integrated with memory system
- create_timmy() injects memory context
- TimmyWithMemory class with automatic fact extraction
- tests/test_agent.py — Updated for memory context
## Key Principles
- Hot memory = small and curated
- Vault = append-only, never delete
- Handoffs = continuity mechanism
- Flat files = human-readable, portable
## Usage
All 973 tests pass.
2026-02-25 18:17:43 -05:00
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
|
|
|
self.end_session()
|
|
|
|
|
return False
|