folderbot 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- folderbot-0.1.0/.gitignore +33 -0
- folderbot-0.1.0/PKG-INFO +112 -0
- folderbot-0.1.0/README.md +85 -0
- folderbot-0.1.0/folderbot/__init__.py +3 -0
- folderbot-0.1.0/folderbot/__main__.py +9 -0
- folderbot-0.1.0/folderbot/claude_client.py +68 -0
- folderbot-0.1.0/folderbot/cli.py +420 -0
- folderbot-0.1.0/folderbot/config.example.yaml +37 -0
- folderbot-0.1.0/folderbot/config.py +114 -0
- folderbot-0.1.0/folderbot/context_builder.py +117 -0
- folderbot-0.1.0/folderbot/session_manager.py +122 -0
- folderbot-0.1.0/folderbot/telegram_handler.py +224 -0
- folderbot-0.1.0/pyproject.toml +78 -0
- folderbot-0.1.0/tests/__init__.py +1 -0
- folderbot-0.1.0/tests/test_cli.py +238 -0
- folderbot-0.1.0/tests/test_config.py +152 -0
- folderbot-0.1.0/tests/test_context_builder.py +143 -0
- folderbot-0.1.0/tests/test_session_manager.py +142 -0
- folderbot-0.1.0/tests/test_telegram_handler.py +249 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Bot configuration (contains secrets)
|
|
2
|
+
folderbot/config.yaml
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.so
|
|
8
|
+
.Python
|
|
9
|
+
*.egg-info/
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
.eggs/
|
|
13
|
+
|
|
14
|
+
# Testing
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
htmlcov/
|
|
18
|
+
.tox/
|
|
19
|
+
|
|
20
|
+
# Type checking
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
|
|
23
|
+
# IDE
|
|
24
|
+
.vscode/
|
|
25
|
+
.idea/
|
|
26
|
+
|
|
27
|
+
# Local database
|
|
28
|
+
*.db
|
|
29
|
+
|
|
30
|
+
# Virtual environments
|
|
31
|
+
.venv/
|
|
32
|
+
venv/
|
|
33
|
+
env/
|
folderbot-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: folderbot
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Telegram bot for chatting with your folder using Claude AI
|
|
5
|
+
Project-URL: Homepage, https://github.com/jcardona/folderbot
|
|
6
|
+
Project-URL: Repository, https://github.com/jcardona/folderbot
|
|
7
|
+
Author: Jorge Cardona
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Keywords: ai,bot,claude,personal-assistant,telegram
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Requires-Dist: anthropic>=0.70.0
|
|
19
|
+
Requires-Dist: pathspec>=0.12.0
|
|
20
|
+
Requires-Dist: python-telegram-bot>=22.0
|
|
21
|
+
Requires-Dist: pyyaml>=6.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# Folderbot
|
|
29
|
+
|
|
30
|
+
A Telegram bot that lets you chat with your folder using Claude AI.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- **Pre-loaded context**: Configure which files to include via glob patterns
|
|
35
|
+
- **Persistent sessions**: Conversation history stored in SQLite
|
|
36
|
+
- **Auto-logging**: All conversations logged to markdown files
|
|
37
|
+
- **Access control**: Whitelist specific Telegram user IDs
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install folderbot
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or install from source:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/jcardona/folderbot
|
|
49
|
+
cd folderbot
|
|
50
|
+
pip install -e .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
Create `folderbot/config.yaml`:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
telegram_token: "YOUR_TELEGRAM_BOT_TOKEN"
|
|
59
|
+
anthropic_api_key: "YOUR_ANTHROPIC_API_KEY"
|
|
60
|
+
allowed_user_ids:
|
|
61
|
+
- 123456789 # Your Telegram user ID
|
|
62
|
+
|
|
63
|
+
root_folder: /path/to/your/folder
|
|
64
|
+
|
|
65
|
+
read_rules:
|
|
66
|
+
include:
|
|
67
|
+
- "**/*.md"
|
|
68
|
+
- "**/*.txt"
|
|
69
|
+
exclude:
|
|
70
|
+
- "**/docs/**"
|
|
71
|
+
- ".git/**"
|
|
72
|
+
|
|
73
|
+
auto_log_folder: logs/
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Get your Telegram user ID from [@userinfobot](https://t.me/userinfobot).
|
|
77
|
+
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
### Run directly
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
folderbot
|
|
84
|
+
# or
|
|
85
|
+
python -m folderbot
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Run as systemd service
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
systemctl --user enable folderbot
|
|
92
|
+
systemctl --user start folderbot
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Commands
|
|
96
|
+
|
|
97
|
+
- `/start` - Initialize bot
|
|
98
|
+
- `/clear` - Clear conversation history
|
|
99
|
+
- `/new` - Start new topic
|
|
100
|
+
- `/status` - Show session info
|
|
101
|
+
- `/files` - List files in context
|
|
102
|
+
|
|
103
|
+
## Development
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
pip install -e ".[dev]"
|
|
107
|
+
pytest
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Folderbot
|
|
2
|
+
|
|
3
|
+
A Telegram bot that lets you chat with your folder using Claude AI.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Pre-loaded context**: Configure which files to include via glob patterns
|
|
8
|
+
- **Persistent sessions**: Conversation history stored in SQLite
|
|
9
|
+
- **Auto-logging**: All conversations logged to markdown files
|
|
10
|
+
- **Access control**: Whitelist specific Telegram user IDs
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install folderbot
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or install from source:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/jcardona/folderbot
|
|
22
|
+
cd folderbot
|
|
23
|
+
pip install -e .
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Configuration
|
|
27
|
+
|
|
28
|
+
Create `folderbot/config.yaml`:
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
telegram_token: "YOUR_TELEGRAM_BOT_TOKEN"
|
|
32
|
+
anthropic_api_key: "YOUR_ANTHROPIC_API_KEY"
|
|
33
|
+
allowed_user_ids:
|
|
34
|
+
- 123456789 # Your Telegram user ID
|
|
35
|
+
|
|
36
|
+
root_folder: /path/to/your/folder
|
|
37
|
+
|
|
38
|
+
read_rules:
|
|
39
|
+
include:
|
|
40
|
+
- "**/*.md"
|
|
41
|
+
- "**/*.txt"
|
|
42
|
+
exclude:
|
|
43
|
+
- "**/docs/**"
|
|
44
|
+
- ".git/**"
|
|
45
|
+
|
|
46
|
+
auto_log_folder: logs/
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Get your Telegram user ID from [@userinfobot](https://t.me/userinfobot).
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
### Run directly
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
folderbot
|
|
57
|
+
# or
|
|
58
|
+
python -m folderbot
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Run as systemd service
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
systemctl --user enable folderbot
|
|
65
|
+
systemctl --user start folderbot
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Commands
|
|
69
|
+
|
|
70
|
+
- `/start` - Initialize bot
|
|
71
|
+
- `/clear` - Clear conversation history
|
|
72
|
+
- `/new` - Start new topic
|
|
73
|
+
- `/status` - Show session info
|
|
74
|
+
- `/files` - List files in context
|
|
75
|
+
|
|
76
|
+
## Development
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install -e ".[dev]"
|
|
80
|
+
pytest
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Claude API client wrapper."""
|
|
2
|
+
|
|
3
|
+
from anthropic import Anthropic
|
|
4
|
+
|
|
5
|
+
from .config import Config
|
|
6
|
+
from .session_manager import Message
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
SYSTEM_PROMPT = """You are Jorge's personal assistant with access to his "second brain" folder.
|
|
10
|
+
This folder contains his notes, logs, goals, and documentation about his life.
|
|
11
|
+
|
|
12
|
+
Your role:
|
|
13
|
+
- Answer questions based on the folder contents
|
|
14
|
+
- Help Jorge remember things he's documented
|
|
15
|
+
- Provide insights from his data (finances, health, relationships)
|
|
16
|
+
- Be direct and concise - Jorge is an engineer
|
|
17
|
+
- Don't be pushy or patronizing
|
|
18
|
+
|
|
19
|
+
The folder contents are provided below. Use this information to answer Jorge's questions.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
FOLDER CONTENTS:
|
|
23
|
+
{context}
|
|
24
|
+
---
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ClaudeClient:
|
|
29
|
+
"""Wrapper for Claude API interactions."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, config: Config):
|
|
32
|
+
self.config = config
|
|
33
|
+
self.client = Anthropic(api_key=config.anthropic_api_key)
|
|
34
|
+
|
|
35
|
+
def chat(self, user_message: str, context: str, history: list[Message]) -> str:
|
|
36
|
+
"""Send a message to Claude and get a response."""
|
|
37
|
+
# Build system prompt with context
|
|
38
|
+
system = SYSTEM_PROMPT.format(context=context)
|
|
39
|
+
|
|
40
|
+
# Build messages list from history
|
|
41
|
+
messages = []
|
|
42
|
+
for msg in history:
|
|
43
|
+
messages.append(
|
|
44
|
+
{
|
|
45
|
+
"role": msg["role"],
|
|
46
|
+
"content": msg["content"],
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Add the new user message
|
|
51
|
+
messages.append(
|
|
52
|
+
{
|
|
53
|
+
"role": "user",
|
|
54
|
+
"content": user_message,
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Call Claude API
|
|
59
|
+
response = self.client.messages.create(
|
|
60
|
+
model=self.config.model,
|
|
61
|
+
max_tokens=4096,
|
|
62
|
+
system=system,
|
|
63
|
+
messages=messages, # type: ignore[arg-type]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Extract text response
|
|
67
|
+
block = response.content[0]
|
|
68
|
+
return block.text if hasattr(block, "text") else str(block)
|