Initial commit: Ajarbot with optimizations

Features:
- Multi-platform bot (Slack, Telegram)
- Memory system with SQLite FTS
- Tool use capabilities (file ops, commands)
- Scheduled tasks system
- Dynamic model switching (/sonnet, /haiku)
- Prompt caching for cost optimization

Optimizations:
- Default to Haiku 4.5 (12x cheaper)
- Reduced context: 3 messages, 2 memory results
- Optimized SOUL.md (48% smaller)
- Automatic caching when using Sonnet (90% savings)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 19:06:28 -07:00
commit a99799bf3d
58 changed files with 11434 additions and 0 deletions

231
memory_workspace/MEMORY.md Normal file
View File

@@ -0,0 +1,231 @@
# MEMORY - Project Context
## Project: ajarbot - AI Agent with Memory
**Created**: 2026-02-12
**Inspired by**: OpenClaw memory system
## Complete System Architecture
### 1. Memory System (memory_system.py)
**Storage**: SQLite + Markdown (source of truth)
**Files Structure**:
- `SOUL.md` - Agent personality/identity (auto-created)
- `MEMORY.md` - Long-term curated facts (this file)
- `users/*.md` - Per-user preferences & context
- `memory/YYYY-MM-DD.md` - Daily activity logs
- `HEARTBEAT.md` - Periodic check checklist
- `memory_index.db` - SQLite FTS5 index
**Features**:
- Full-text search (FTS5) - keyword matching, 64-char snippets
- File watching - auto-reindex on changes
- Chunking - ~500 chars per chunk
- Per-user search - `search_user(username, query)`
- Task tracking - SQLite table for work items
- Hooks integration - triggers events on sync/tasks
**Key Methods**:
```python
memory.sync() # Index all .md files
memory.write_memory(text, daily=True/False) # Append to daily or MEMORY.md
memory.update_soul(text, append=True) # Update personality
memory.update_user(username, text, append=True) # User context
memory.search(query, max_results=5) # FTS5 search
memory.search_user(username, query) # User-specific search
memory.add_task(title, desc, metadata) # Add task → triggers hook
memory.update_task(id, status) # Update task
memory.get_tasks(status="pending") # Query tasks
```
### 2. LLM Integration (llm_interface.py)
**Providers**: Claude (Anthropic API), GLM (z.ai)
**Configuration**:
- API Keys: `ANTHROPIC_API_KEY`, `GLM_API_KEY` (env vars)
- Models: claude-sonnet-4-5-20250929, glm-4-plus
- Switching: `llm = LLMInterface("claude")` or `"glm"`
**Methods**:
```python
llm.chat(messages, system=None, max_tokens=4096) # Returns str
llm.set_model(model_name) # Change model
```
### 3. Task System
**Storage**: SQLite `tasks` table
**Schema**:
- id, title, description, status, created_at, updated_at, metadata
**Statuses**: `pending`, `in_progress`, `completed`
**Hooks**: Triggers `task:created` event when added
### 4. Heartbeat System (heartbeat.py)
**Inspired by**: OpenClaw's periodic awareness checks
**How it works**:
1. Background thread runs every N minutes (default: 30)
2. Only during active hours (default: 8am-10pm)
3. Reads `HEARTBEAT.md` checklist
4. Sends to LLM with context: SOUL, pending tasks, current time
5. Returns `HEARTBEAT_OK` if nothing needs attention
6. Calls `on_alert()` callback if action required
7. Logs alerts to daily memory
**Configuration**:
```python
heartbeat = Heartbeat(memory, llm,
interval_minutes=30,
active_hours=(8, 22) # 24h format
)
heartbeat.on_alert = lambda msg: print(f"ALERT: {msg}")
heartbeat.start() # Background thread
heartbeat.check_now() # Immediate check
heartbeat.stop() # Cleanup
```
**HEARTBEAT.md Example**:
```markdown
# Heartbeat Checklist
- Review pending tasks
- Check tasks pending > 24 hours
- Verify memory synced
- Return HEARTBEAT_OK if nothing needs attention
```
### 5. Hooks System (hooks.py)
**Pattern**: Event-driven automation
**Events**:
- `task:created` - When task added
- `memory:synced` - After memory.sync()
- `agent:startup` - Agent initialization
- `agent:shutdown` - Agent cleanup
**Usage**:
```python
hooks = HooksSystem()
def my_hook(event: HookEvent):
if event.type != "task": return
print(f"Task: {event.context['title']}")
event.messages.append("Logged")
hooks.register("task:created", my_hook)
hooks.trigger("task", "created", {"title": "Build X"})
```
**HookEvent properties**:
- `event.type` - Event type (task, memory, agent)
- `event.action` - Action (created, synced, startup)
- `event.timestamp` - When triggered
- `event.context` - Dict with event data
- `event.messages` - List to append messages
### 6. Agent Class (agent.py)
**Main interface** - Combines all systems
**Initialization**:
```python
agent = Agent(
provider="claude", # or "glm"
workspace_dir="./memory_workspace",
enable_heartbeat=False # Set True for background checks
)
```
**What happens on init**:
1. Creates MemorySystem, LLMInterface, HooksSystem
2. Syncs memory (indexes all .md files)
3. Triggers `agent:startup` hook
4. Optionally starts heartbeat thread
5. Creates SOUL.md, users/default.md, HEARTBEAT.md if missing
**Methods**:
```python
agent.chat(message, username="default") # Context-aware chat
agent.switch_model("glm") # Change LLM provider
agent.shutdown() # Stop heartbeat, close DB, trigger shutdown hook
```
**Chat Context Loading**:
1. SOUL.md (personality)
2. users/{username}.md (user preferences)
3. memory.search(message, max_results=3) (relevant context)
4. Last 5 conversation messages
5. Logs exchange to daily memory
## Complete File Structure
```
ajarbot/
├── Core Implementation
│ ├── memory_system.py # Memory (SQLite + Markdown)
│ ├── llm_interface.py # Claude/GLM API integration
│ ├── heartbeat.py # Periodic checks system
│ ├── hooks.py # Event-driven automation
│ └── agent.py # Main agent class (combines all)
│
├── Examples & Docs
│ ├── example_usage.py # SOUL/User file examples
│ ├── QUICKSTART.md # 30-second setup guide
│ ├── README_MEMORY.md # Memory system docs
│ ├── HEARTBEAT_HOOKS.md # Heartbeat/hooks guide
│ └── requirements.txt # Dependencies
│
└── memory_workspace/
├── SOUL.md # Agent personality (auto-created)
├── MEMORY.md # This file - long-term memory
├── HEARTBEAT.md # Heartbeat checklist (auto-created)
├── users/
│ └── default.md # Default user template (auto-created)
├── memory/
│ └── 2026-02-12.md # Daily logs (auto-created)
└── memory_index.db # SQLite FTS5 index
```
## Quick Start
```python
# Initialize
from agent import Agent
agent = Agent(provider="claude")
# Chat with memory context
response = agent.chat("Help me code", username="alice")
# Switch models
agent.switch_model("glm")
# Add task
task_id = agent.memory.add_task("Implement feature X", "Details...")
agent.memory.update_task(task_id, status="completed")
```
## Environment Setup
```bash
export ANTHROPIC_API_KEY="sk-ant-..."
export GLM_API_KEY="your-glm-key"
pip install anthropic requests watchdog
```
## Token Efficiency
- Memory auto-indexes all files (no manual sync needed)
- Search returns snippets only (64 chars), not full content
- Task system tracks context without bloating prompts
- User-specific search isolates context per user
# System Architecture Decisions
## Memory System Design
- **Date**: 2026-02-12
- **Decision**: Use SQLite + Markdown for memory
- **Rationale**: Simple, fast, no external dependencies
- **Files**: SOUL.md for personality, users/*.md for user context
## Search Strategy
- FTS5 for keyword search (fast, built-in)
- No vector embeddings (keep it simple)
- Per-user search capability for privacy

45
memory_workspace/SOUL.md Normal file
View File

@@ -0,0 +1,45 @@
# SOUL - Agent Identity
## Core Traits
Helpful, concise, proactive. Value clarity and user experience. Prefer simple solutions. Learn from feedback.
## Memory System
- Store facts in MEMORY.md
- Track daily activities in memory/YYYY-MM-DD.md
- Remember user preferences in users/[username].md
## Tool Powers
I can directly edit files and run commands! Available tools:
1. **read_file** - Read file contents
2. **write_file** - Create/rewrite files
3. **edit_file** - Targeted text replacement
4. **list_directory** - Explore file structure
5. **run_command** - Execute shell commands
**Key principle**: DO things, don't just explain them. If asked to schedule a task, edit the config file directly.
## Scheduler Management
When users ask to schedule tasks (e.g., "remind me at 9am"):
1. **Read** `config/scheduled_tasks.yaml` to see existing tasks
2. **Edit** the YAML to add the new task with proper formatting
3. **Inform** user what was added (may need bot restart)
### Schedule Formats
- `hourly` - Every hour
- `daily HH:MM` - Daily at time (24-hour)
- `weekly day HH:MM` - Weekly (mon/tue/wed/thu/fri/sat/sun)
### Task Template
```yaml
- name: task-name
prompt: |
[What to do/say]
schedule: "daily HH:MM"
enabled: true
send_to_platform: "telegram" # or "slack"
send_to_channel: "USER_CHAT_ID"
```
Be proactive and use tools to make things happen!

View File

@@ -0,0 +1,22 @@
# User: alice
## Personal Info
- Name: Alice Johnson
- Role: Senior Python Developer
- Timezone: America/New_York (EST)
- Active hours: 9 AM - 6 PM EST
## Preferences
- Communication: Detailed technical explanations
- Code style: PEP 8, type hints, docstrings
- Favorite tools: VS Code, pytest, black
## Current Projects
- Building a microservices architecture
- Learning Kubernetes
- Migrating legacy Django app
## Recent Conversations
- 2026-02-12: Discussed SQLite full-text search implementation
- 2026-02-12: Asked about memory system design patterns

View File

@@ -0,0 +1,22 @@
# User: bob
## Personal Info
- Name: Bob Smith
- Role: Frontend Developer
- Timezone: America/Los_Angeles (PST)
- Active hours: 11 AM - 8 PM PST
## Preferences
- Communication: Concise, bullet points
- Code style: ESLint, Prettier, React best practices
- Favorite tools: WebStorm, Vite, TailwindCSS
## Current Projects
- React dashboard redesign
- Learning TypeScript
- Performance optimization work
## Recent Conversations
- 2026-02-11: Asked about React optimization techniques
- 2026-02-12: Discussed Vite configuration

View File

@@ -0,0 +1,14 @@
# User: default
## Preferences
- Communication style: professional
- Detail level: moderate
- Timezone: UTC
## Context
- Projects: []
- Interests: []
- Goals: []
## Notes
(Add user-specific notes here)