# doit-fm

A background AI agent that lets you control your computer via Telegram.

## How it works

```
Telegram message → long-polling → AI model → structured JSON → OS tool → result → Telegram reply
```

You send a natural language message. The AI maps it to a tool + args. The tool runs as a real OS action. The result comes back to you in Telegram. In 2–5 seconds.

## Install

```bash
pip install doit-fm
```

Or from source:
```bash
git clone <repo>
cd doit-fm
pip install -e .
```

## Setup

```bash
doitfm init
```

The wizard walks you through:
1. Checking dependencies
2. Choosing AI provider + model (free options: Groq, OpenRouter, Ollama)
3. Connecting your Telegram bot
4. Sending a test message

## Run

```bash
doitfm run
```

Background:
```bash
nohup doitfm run &
```

## Commands

```
doitfm init     — Setup wizard
doitfm run      — Start the agent
doitfm stop     — Stop the agent
doitfm status   — Check if running
doitfm doctor   — Diagnostics
```

## Telegram commands

```
/health         — CPU, RAM, disk, battery
/ps             — Running processes
/disk           — Disk partitions
/ip             — Public IP
/time           — Date and time
/weather <city> — Weather
/volume [0-100] — Get/set volume
/ls [path]      — List directory
/run <cmd>      — Shell command (with confirmation)
/notes          — List notes
/note <text>    — Save note
/clear          — Clear AI conversation memory
/status         — Agent status
/help           — Help
```

Or just talk naturally:
- _"how's my system?"_
- _"what's the weather in Tokyo?"_
- _"remind me to call John in 30 minutes"_
- _"what's using all my CPU?"_
- _"take a screenshot"_
- _"what's my public IP?"_
- _"calculate 847 * 23"_

## AI Providers

| Provider | Free tier | Notes |
|----------|-----------|-------|
| Groq | ✅ Yes | Fast, free Llama/Mixtral |
| OpenRouter | ✅ Yes | Gemma 3, Llama 3.3 free |
| Ollama | ✅ Local | Fully offline |
| OpenAI | ❌ Paid | GPT-4o |
| Anthropic | ❌ Paid | Claude |
| Together AI | ❌ Paid | Various models |

## Tools

| Tool | Description | Dangerous |
|------|-------------|-----------|
| system_health | CPU, RAM, disk, battery | No |
| list_processes | Top processes by CPU | No |
| kill_process | Kill process by PID | **Yes** |
| run_shell | Execute shell command | **Yes** |
| list_directory | List files | No |
| read_file | Read text file | No |
| write_file | Write to file | **Yes** |
| delete_file | Delete file/dir | **Yes** |
| move_file | Move/rename | **Yes** |
| copy_file | Copy | No |
| find_files | Search by pattern | No |
| ping | Ping host | No |
| get_public_ip | Public IP | No |
| dns_lookup | DNS resolve | No |
| http_get | HTTP GET | No |
| speedtest | Speed test | No |
| weather | Weather by city | No |
| get_volume | Get volume | No |
| set_volume | Set volume | No |
| screenshot | Take screenshot | No |
| get_clipboard | Clipboard read | No |
| set_clipboard | Clipboard write | No |
| set_reminder | Set reminder | No |
| get_datetime | Date/time | No |
| calculate | Math expression | No |
| add_note | Save note | No |
| list_notes | Read notes | No |
| open_app | Launch app | No |
| disk_usage | Partition usage | No |
| network_interfaces | Network info | No |
| shutdown | Shutdown PC | **Yes** |
| reboot | Reboot PC | **Yes** |
| sleep | Suspend | No |
| list_pip_packages | pip list | No |

## Security

- Only your Telegram user ID can control the agent
- All other messages are silently rejected
- Dangerous tools require explicit tap-to-confirm via inline buttons
- API key is encrypted at rest (Fernet symmetric encryption)
- Encryption key stored at `~/.local/share/doit-fm/data/.enc_key` (chmod 600)

## Architecture

```
src/doitfm/
├── __init__.py   — package metadata
├── config.py     — constants, paths, provider registry
├── store.py      — encrypted config file (singleton)
├── tools.py      — 35 tool implementations + registry + dispatcher
├── ai.py         — AIEngine + ConversationMemory
├── bot.py        — TelegramAPI + TelegramBot
└── cli.py        — Click CLI
```

## Adding a new tool

1. Write an async function in `tools.py` — takes `**kwargs`, returns `dict`, never raises
2. Add one entry to `TOOLS` dict
3. Add one intent rule to the system prompt in `ai.py`
4. Optionally add a slash command in `bot.py`

## Adding a new AI provider

1. Add entry to `AI_PROVIDERS` in `config.py`
2. If not OpenAI-compatible, add a branch in `AIEngine` in `ai.py`

## License

MIT
