Skip to content

Commit 8ef7283

Browse files
committed
LLM rules
1 parent 588cda7 commit 8ef7283

File tree

2 files changed

+231
-0
lines changed

2 files changed

+231
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,4 @@ next-env.d.ts
221221
CLAUDE.md
222222
GEMINI.md
223223
.cursorrules
224+
.claude

LLM_RULES.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
2+
# Botspot Development Guide
3+
4+
## Build & Test Commands
5+
- Install dependencies: `poetry install`
6+
- Run tests: `poetry run pytest`
7+
- Run single test: `poetry run pytest tests/path_to_test.py::test_function_name -v`
8+
- Format code: `poetry run black .`
9+
- Sort imports: `poetry run isort .`
10+
- Lint code: `poetry run flake8`
11+
12+
## Code Style Guidelines
13+
- **Imports**: Use isort with black profile; line length 100
14+
- **Formatting**: Black with 100 character line length
15+
- **Types**: Use type hints and Pydantic for data models
16+
- **Naming**: snake_case for variables/functions, PascalCase for classes, UPPER_CASE for constants
17+
- **SYSTEM-LEVEL ERROR HANDLING**: DO NOT ADD LOCAL EXCEPTION HANDLERS. THE SYSTEM HAS PROPER ERROR HANDLING WITH LOGGING AND REPORTING
18+
- **Component Usage**: Access components via `deps` object or dedicated getters
19+
- **Documentation**: Docstrings for classes and functions in flake8-docstrings format
20+
- **Dependencies**: Managed with Poetry in pyproject.toml
21+
22+
## Adding New Components
23+
When adding a new component, include:
24+
1. New component file in appropriate subdirectory (main/data/features/middlewares/qol)
25+
2. Add component to config in `core/botspot_settings.py`
26+
3. Add component to `core/dependency_manager.py`
27+
4. Setup component in `core/bot_manager.py`
28+
5. Add getter util to `utils/deps_getters.py` if necessary
29+
6. Create example in `examples/components_examples`, use examples/base_bot - import and reuse.
30+
31+
The codebase is a Telegram bot framework with modular components. Prefer composition over inheritance when extending functionality.
32+
33+
# Botspot Development Guide
34+
35+
## 🔑 Key Principles
36+
37+
1. **EXTREME MINIMALISM**: Delete code ruthlessly. If it works with 3 lines, it doesn't need 10.
38+
2. **USE BOTSPOT DEFAULTS**: Always use base_bot, commands_menu, and default component settings.
39+
3. **ONE FEATURE AT A TIME**: Implement simplest version first, then add minimal integrations.
40+
41+
## 🚫 COMMON MISTAKES TO AVOID
42+
43+
### ❌ Over-engineering
44+
```python
45+
# BAD: Over-engineered approach with unnecessary complexity
46+
async def get_random_item_handler(message: Message):
47+
if not message.from_user:
48+
await message.reply("User information is missing.")
49+
return
50+
51+
user_id = message.from_user.id
52+
try:
53+
bindings = await get_chat_binding_status(user_id, message.chat.id)
54+
if not bindings:
55+
await message.reply("This chat is not bound to you. Use /bind_chat first.")
56+
return
57+
58+
try:
59+
queue = get_queue(f"user_{user_id}") # WHY USER-SPECIFIC? BAD!
60+
except KeyError:
61+
await message.reply("Your queue is empty.")
62+
return
63+
64+
items = await queue.get_items(str(user_id)) # WHY FILTER BY USER? BAD!
65+
if not items:
66+
await message.reply("Your queue is empty.")
67+
return
68+
69+
random_item = random.choice(items)
70+
await message.reply(f"Random item from your queue: {random_item.get('data', 'No data')}")
71+
except Exception as e:
72+
await message.reply(f"Error getting random item: {str(e)}")
73+
```
74+
75+
### ✅ Minimal Correct Implementation
76+
```python
77+
# GOOD: Minimal implementation that does exactly what's needed
78+
@botspot_command("get_random_item", "Get random item")
79+
@router.message(Command("get_random_item"))
80+
async def get_random_item_handler(message: Message):
81+
try:
82+
queue = get_queue() # Default queue - GOOD!
83+
items = await queue.get_items() # All items - GOOD!
84+
if not items:
85+
await message.reply("Queue is empty.")
86+
return
87+
random_item = random.choice(items)
88+
await message.reply(f"Random item: {random_item.get('data')}")
89+
except Exception as e:
90+
await message.reply(f"Error: {str(e)}")
91+
```
92+
93+
## 📏 IMPLEMENTATION RULES
94+
95+
1. **MAX 10 LINES PER HANDLER** - If longer, you're doing it wrong
96+
2. **USE DEFAULT EVERYTHING**:
97+
- Default queue key = `"default"`
98+
- Default item type = `QueueItem`
99+
- Default MongoDB collection
100+
3. **ALWAYS USE BASE_BOT PATTERN**:
101+
```python
102+
from examples.base_bot import App, main, router
103+
104+
class MyApp(App):
105+
name = "My App"
106+
107+
# ...handlers...
108+
109+
if __name__ == "__main__":
110+
main(routers=[router], AppClass=MyApp)
111+
```
112+
4. **ALWAYS DECORATE COMMANDS**:
113+
```python
114+
@botspot_command("command_name", "Command description")
115+
@router.message(Command("command_name"))
116+
async def command_handler(message: Message):
117+
# ...
118+
```
119+
120+
## 💯 COMPLETE EXAMPLE TEMPLATE
121+
122+
```python
123+
"""
124+
Minimal Queue Manager Demo with Chat Binder
125+
"""
126+
127+
from aiogram import F
128+
from aiogram.filters import Command
129+
from aiogram.types import Message
130+
import random
131+
132+
from botspot.commands_menu import botspot_command
133+
from botspot.components.new.chat_binder import get_binding_records
134+
from botspot.components.new.queue_manager import QueueItem, create_queue, get_queue
135+
from examples.base_bot import App, main, router
136+
137+
138+
class QueueManagerDemoApp(App):
139+
name = "Queue Manager Demo"
140+
141+
142+
@botspot_command("start", "Start the bot")
143+
@router.message(Command("start"))
144+
async def start_handler(message: Message):
145+
await message.reply(
146+
"Queue Manager Demo:\n"
147+
"- /bind_chat to bind this chat\n"
148+
"- Send messages to add to queue\n"
149+
"- /get_random_item to get random item"
150+
)
151+
152+
153+
@botspot_command("get_random_item", "Get random item")
154+
@router.message(Command("get_random_item"))
155+
async def get_random_item_handler(message: Message):
156+
try:
157+
queue = get_queue()
158+
items = await queue.get_items()
159+
if not items:
160+
await message.reply("Queue is empty.")
161+
return
162+
random_item = random.choice(items)
163+
await message.reply(f"Random item: {random_item.get('data')}")
164+
except Exception as e:
165+
await message.reply(f"Error: {str(e)}")
166+
167+
168+
@router.message(F.text)
169+
async def message_handler(message: Message):
170+
if not message.from_user or not message.text or message.text.startswith("/"):
171+
return
172+
173+
user_id = message.from_user.id
174+
175+
# Only process messages in bound chats
176+
bindings = await get_binding_records(user_id, message.chat.id)
177+
if not bindings:
178+
return
179+
180+
# Add message to queue
181+
try:
182+
queue = get_queue()
183+
except KeyError:
184+
queue = create_queue()
185+
186+
item = QueueItem(data=message.text)
187+
await queue.add_item(item, username=str(user_id))
188+
await message.reply("Added to queue!")
189+
```
190+
191+
## 🧠 LLM INTERACTION TECHNIQUES
192+
193+
When working with Claude, use these techniques to get better results:
194+
195+
1. **BE EXTREMELY EXPLICIT**: "I want the SIMPLEST implementation possible with DEFAULT queue settings"
196+
197+
2. **USE TEMPLATES**: "Copy this exact structure: [paste minimal template]"
198+
199+
3. **PAIR NEGATIVE/POSITIVE EXAMPLES**: "Don't do X. Do Y instead."
200+
201+
4. **NUMBERED CONSTRAINTS**:
202+
```
203+
Follow these constraints:
204+
1. Maximum 10 lines per handler
205+
2. Use default queue settings
206+
3. No custom user filtering
207+
```
208+
209+
5. **ROLE ASSIGNMENT**: "You are SIMPLICITY-BOT. Your purpose is to eliminate all unnecessary code."
210+
211+
6. **CODE REVIEW PROMPT**: "Review this implementation and remove all unnecessary complexity."
212+
213+
## 🧪 VALIDATION CHECKLIST
214+
215+
- [ ] Uses base_bot pattern
216+
- [ ] Uses botspot_command decorator
217+
- [ ] Handlers are ≤10 lines each
218+
- [ ] Uses default queue key
219+
- [ ] Uses default QueueItem type
220+
- [ ] Total code is <100 lines
221+
- [ ] No user-specific filtering of queue items
222+
- [ ] No custom database collections
223+
- [ ] No unnecessary error handling
224+
225+
The entire bot should be focused on just these features:
226+
1. Bind chat with existing /bind_chat command
227+
2. Add messages from bound chats to default queue
228+
3. Get random items from anywhere with /get_random_item
229+
230+
EVERYTHING ELSE IS UNNECESSARY AND SHOULD BE REMOVED.

0 commit comments

Comments
 (0)