alvin-bot 4.22.0 → 4.22.1

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.
package/02_yandex.png ADDED
Binary file
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to Alvin Bot are documented here.
4
4
 
5
+ ## [4.22.1] — 2026-05-09
6
+
7
+ ### Fixed
8
+
9
+ - **Cron scheduler:** prevent duplicate catch-up runs for already-attempted slots. When a daily/scheduled job fired but crashed before completion, the boot-time catch-up would re-fire it hours later (e.g. an `0 8 * * *` job retried at 11:00 after a 10:51 reboot). The catch-up now skips jobs whose current schedule slot has already been attempted: for cron expressions, `lastAttemptAt >= mostRecentPastTrigger` short-circuits the rewind; for interval schedules, `now - lastAttemptAt < intervalMs` does the same. Crashed runs from *previous* slots within the 6h grace window still catch up as before. New `prevCronRun()` helper in `cron-scheduling.ts`. ([#cron-catchup-bug](src/services/cron-scheduling.ts))
10
+
5
11
  ## [4.22.0] — 2026-05-05
6
12
 
7
13
  ### 🧠 Memory architecture overhaul: pluggable providers + smart inject
package/README.md CHANGED
@@ -1,104 +1,49 @@
1
1
  # 🤖 Alvin Bot — Autonomous AI Agent
2
2
 
3
- > Your personal AI assistant — on Telegram, WhatsApp, Discord, Signal, Terminal, and Web.
3
+ > Your personal AI agent — on Telegram, WhatsApp, Discord, Slack, Signal, Terminal, and Web.
4
4
 
5
- Alvin Bot is an open-source, self-hosted AI agent that lives where you chat. Built on a multi-model engine with full system access, memory, plugins, and a rich web dashboard. Not just a chatbot an autonomous agent that remembers, acts, and learns.
5
+ Open-source, self-hosted, multi-model. Lives where you chat, has full shell + filesystem access, remembers across sessions, and dispatches detached sub-agents for long-running work. Built on the Claude Agent SDK with a provider-agnostic engine that also drives OpenAI, Groq, Gemini, NVIDIA NIM, OpenRouter, and Ollama.
6
6
 
7
+ > **What's new — v4.22 (May 2026):** Pluggable memory backends — Gemini · OpenAI · Ollama · **FTS5 keyword fallback (zero-config)**. Users without an embedding API key now get a working indexed memory store out of the box. Smart inject mode trims ~25 k tokens per turn off long system prompts. [Full changelog →](CHANGELOG.md)
7
8
 
8
9
  ---
9
10
 
10
- ## 📸 Preview
11
-
12
- <table>
13
- <tr>
14
- <td align="center"><b>💬 Chat (Dark Mode)</b><br><img src="docs/screenshots/01-Chat-Dark-Conversation.png" width="400"></td>
15
- <td align="center"><b>📊 Dashboard</b><br><img src="docs/screenshots/03-Dashboard-Overview.png" width="400"></td>
16
- </tr>
17
- <tr>
18
- <td align="center"><b>🤖 AI Models & Providers</b><br><img src="docs/screenshots/04-AI-Models-and-Providers.png" width="400"></td>
19
- <td align="center"><b>🎭 Personality Editor</b><br><img src="docs/screenshots/05-Personality-Editor.png" width="400"></td>
20
- </tr>
21
- <tr>
22
- <td align="center"><b>💬 Telegram</b><br><img src="docs/screenshots/TG.png" width="400"></td>
23
- <td align="center"><b>📱 Messaging Platforms</b><br><img src="docs/screenshots/12-Messaging-Platforms.png" width="400"></td>
24
- </tr>
25
- <tr>
26
- <td align="center"><b>🔧 Custom Tools</b><br><img src="docs/screenshots/10-Custom-Tools.png" width="400"></td>
27
- <td align="center"><b>🩺 Health & Maintenance</b><br><img src="docs/screenshots/15-Maintenance-and-Health.png" width="400"></td>
28
- </tr>
29
- </table>
30
-
31
- <details>
32
- <summary><b>🖼️ More Screenshots</b> (click to expand)</summary>
33
- <br>
34
-
35
- | Feature | Screenshot |
36
- |---------|-----------|
37
- | Login | <img src="docs/screenshots/00-Login.png" width="500"> |
38
- | Chat (Light) | <img src="docs/screenshots/02-Chat.png" width="500"> |
39
- | Memory Manager | <img src="docs/screenshots/06-Memory-Manager.png" width="500"> |
40
- | Active Sessions | <img src="docs/screenshots/07-Active-Sessions.png" width="500"> |
41
- | File Browser | <img src="docs/screenshots/08-File-Browser.png" width="500"> |
42
- | Scheduled Jobs | <img src="docs/screenshots/09-Scheduled-Jobs.png" width="500"> |
43
- | Plugins & MCP | <img src="docs/screenshots/11-Plugins-and-MCP.png" width="500"> |
44
- | WhatsApp Groups | <img src="docs/screenshots/12.1-Messaging-Platforms-WhatsApp-Groups-List.png" width="500"> |
45
- | WA Group Details | <img src="docs/screenshots/12.2-Messaging-Platforms-WA-Group-Details.png" width="500"> |
46
- | User Management | <img src="docs/screenshots/13-User-Management.png" width="500"> |
47
- | Web Terminal | <img src="docs/screenshots/14-Web-Terminal.png" width="500"> |
48
- | Settings & Env | <img src="docs/screenshots/16-Settings-and-Env.png" width="500"> |
49
- | Telegram Commands | <img src="docs/screenshots/TG-commands.png" width="500"> |
50
- | macOS Installer | <img src="docs/screenshots/_Mac-Installer.png" width="500"> |
51
-
52
- </details>
53
-
54
- ---
55
-
56
-
57
11
  ## ✨ Features
58
12
 
59
13
  ### 🧠 Intelligence
60
- - **Multi-Model Engine** — Claude (Agent SDK with full tool use), OpenAI, Groq, NVIDIA NIM, Google Gemini, OpenRouter, or any OpenAI-compatible API
61
- - **Automatic Fallback** — If one provider fails, seamlessly tries the next
62
- - **Heartbeat Monitor** — Pings providers every 5 minutes, auto-failover after 2 failures, auto-recovery
63
- - **User-Configurable Fallback Order** — Rearrange provider priority via Telegram (`/fallback`), Web UI, or API
64
- - **Adjustable Thinking** — From quick answers (`/effort low`) to deep analysis (`/effort max`)
65
- - **Persistent Memory** — Remembers across sessions via vector-indexed knowledge base; session state (Claude SDK resume tokens, conversation history, language, effort) survives bot restarts (v4.11.0)
66
- - **Multi-Session Workspaces** — Run multiple parallel, context-isolated sessions on the same bot — one per Slack channel or per Telegram `/workspace` — each with its own working directory, purpose, and persona. Memory, skills, and sub-agents stay globally shared (v4.12.0). [How-to ↓](#-multi-session-workspaces-v4120)
67
- - **Truly Detached Sub-Agents** — Claude dispatches long-running research/audit tasks via the `alvin_dispatch_agent` MCP tool, which spawns independent `claude -p` subprocesses with their own PID + process group. Main session stays fully responsive, user can interrupt freely without killing sub-agents. Results deliver as separate messages. Works identically on Telegram, Slack, Discord, and WhatsApp (v4.13.0+ dispatch, v4.14.0 multi-platform)
68
- - **Smart Tool Discovery** — Scans your system at startup, knows exactly what CLI tools, plugins, and APIs are available
69
- - **Skill System** — 12 built-in SKILL.md files (code, data analysis, email, docs, research, sysadmin, browse, etc.) auto-activate based on message context
70
- - **Self-Awareness** — Knows it IS the AI model won't call external APIs for tasks it can do itself
71
- - **Automatic Language Detection** — Detects user language (EN/DE/ES/FR) and adapts; learns preference over time
14
+ - **Multi-model engine** — Claude Agent SDK · OpenAI · Groq · NVIDIA NIM · Gemini · OpenRouter · Ollama · Codex CLI · any OpenAI-compatible API
15
+ - **Automatic fallback + heartbeat monitor** — pings providers every 5 min, auto-failover after 2 failures, auto-recovery; reorder priority via Telegram `/fallback`, Web UI, or API
16
+ - **Adjustable thinking depth** — `/effort low` to `/effort max`
17
+ - **Pluggable memory backends (v4.22)** — Gemini · OpenAI · Ollama · FTS5 keyword fallback. Auto-detection picks the best available. Indexed search across `MEMORY.md`, daily logs, project files, hub memory, asset index. Override via `EMBEDDINGS_PROVIDER`.
18
+ - **Smart system-prompt injection (v4.22)** — once SQLite is populated, stops bulk-injecting `MEMORY.md` and surfaces only the chunks relevant to the user's current message. Cuts ~25 k tokens per turn for typical setups. `MEMORY_INJECT_MODE=auto|legacy|sqlite` to override.
19
+ - **Layered memory (L0–L3)** — `identity.md` + `preferences.md` always plain-text · project memories on topic match · daily logs / curated knowledge via semantic or keyword search
20
+ - **Persistent sessions** — Claude SDK resume tokens, conversation history, language, effort survive bot restarts
21
+ - **Multi-session workspaces** — parallel context-isolated sessions per Slack channel or `/workspace` switch, each with its own cwd, purpose, persona. Memory + skills stay globally shared. [How-to ↓](#-multi-session-workspaces-v4120)
22
+ - **Detached sub-agents** — `alvin_dispatch_agent` MCP tool spawns independent `claude -p` subprocesses that survive parent aborts. Results deliver as separate messages. Works identically on Telegram / Slack / Discord / WhatsApp.
23
+ - **Smart tool discovery** — scans your system at startup; typical install surfaces 30–70 tools depending on what's locally available
24
+ - **Skill system** — 14 SKILL.md files (see [Skills ↓](#-skills)) auto-activate based on message context
25
+ - **Self-awareness + auto-language** — knows it IS the AI · detects EN/DE/ES/FR and adapts; learns preference over time
72
26
 
73
27
  ### 💬 Multi-Platform
74
- - **Telegram** — Full-featured with streaming, inline keyboards, voice, photos, documents
75
- - **Slack** — Socket Mode bot via `@slack/bolt`, DMs + @mentions, file attachments, reactions, `assistant.threads.setStatus` typing indicator. **One channel = one isolated workspace.** See [Multi-Session Workspaces](#-multi-session-workspaces-v4120) below.
76
- - **WhatsApp** — Via WhatsApp Web: self-chat as AI notepad, group whitelist with per-contact access control, full media support (photos, docs, audio, video)
77
- - **WhatsApp Group Approval** — Owner gets approval requests via Telegram (or WhatsApp DM fallback) before the bot responds to group messages. Silent — group members see nothing.
78
- - **Discord** — Server bot with mention/reply detection, slash commands
79
- - **Signal** — Via signal-cli REST API with voice transcription
80
- - **Terminal** — Rich TUI with ANSI colors and streaming (`alvin-bot tui`)
81
- - **Web UI** — Full dashboard with chat, settings, file manager, terminal, workspace overview
28
+ - **Telegram** — streaming, inline keyboards, voice, photos, documents
29
+ - **Slack** — Socket Mode via `@slack/bolt`, DMs + @mentions, file attachments, `assistant.threads.setStatus` typing. **One channel = one isolated workspace.**
30
+ - **WhatsApp** — via WhatsApp Web; self-chat as AI notepad, group whitelist with per-contact access, full media. Owner approval gate routes to Telegram (DM / Discord / Signal fallback) before the bot replies.
31
+ - **Discord** — server bot with mention/reply detection and slash commands
32
+ - **Signal** — via signal-cli REST API, voice transcription
33
+ - **Terminal** — rich TUI with ANSI colors + streaming (`alvin-bot tui`)
34
+ - **Web UI** — full dashboard, chat, settings, file manager, terminal, workspace overview
82
35
 
83
36
  ### 🔧 Capabilities
84
- - **52+ Built-in Tools** — Shell, files, email, screenshots, PDF, media, git, system control
85
- - **Plugin System** — 6 built-in plugins (weather, finance, notes, calendar, email, smarthome)
86
- - **MCP Client** — Connect any Model Context Protocol server
87
- - **Cron Jobs** — Scheduled tasks with AI-driven creation ("check my email every morning")
88
- - **Voice** — Speech-to-text (Groq Whisper) + text-to-speech (Edge TTS)
89
- - **Vision** — Photo analysis, document scanning, screenshot understanding
90
- - **Image Generation** — Via Google Gemini / DALL·E (with API key)
91
- - **Web Browsing** — Fetch and summarize web pages
37
+ - **Tool layer** — Shell · files · Python · git · email · PDF · media · vision · screenshots · system control. Universal tool use across any provider that supports function calling; text-only fallback for those that don't.
38
+ - **6 built-in plugins** weather · finance · notes · calendar · email · smarthome
39
+ - **MCP client** — connect any Model Context Protocol server
40
+ - **Cron** — AI-driven scheduled tasks (`"check my email every morning"`)
41
+ - **Voice** — STT via Groq Whisper, TTS via Edge TTS or ElevenLabs
42
+ - **Vision + image generation** — photo / document analysis · Gemini / DALL·E generation with API key
43
+ - **Browser** — 4-tier strategy: WebFetch · stealth Playwright · CDP with persistent profile · agent-browser CLI (Tier-1.5, opt-in)
92
44
 
93
45
  ### 🖥️ Web Dashboard
94
- - **Live Chat** WebSocket streaming, same experience as Telegram
95
- - **Model Switcher** — Change AI models on the fly
96
- - **Platform Setup** — Configure all messengers and providers via UI, WhatsApp group management inline
97
- - **File Manager** — Browse, edit, create files in the working directory
98
- - **Memory Editor** — View and edit the agent's knowledge base
99
- - **Session Browser** — Inspect conversation history
100
- - **Terminal** — Run commands directly from the browser
101
- - **Maintenance** — Health checks, backups, bot controls
46
+ - WebSocket streaming chat · model switcher · platform & provider setup · file manager · memory editor · session browser · in-browser terminal · maintenance + health · workspace cards with cost aggregation
102
47
 
103
48
  ---
104
49
 
@@ -121,7 +66,7 @@ Free AI providers available — no credit card needed. **Privacy-first?** Pick t
121
66
 
122
67
  ### 📘 First-time setup walkthroughs
123
68
 
124
- Step-by-step guides with screenshots and screen-for-screen instructions:
69
+ Step-by-step printable PDF guides:
125
70
 
126
71
  | Platform | PDF (printable) |
127
72
  |---|---|
@@ -262,69 +207,72 @@ If your AI provider isn't working, run `doctor` — it tests the actual API conn
262
207
 
263
208
  ## 🏗️ Architecture
264
209
 
265
- ```
266
- ┌──────────────┐
267
- │ Web UI │ (Dashboard, Workspaces, Chat, Settings)
268
- └──────┬───────┘
269
- HTTP/WS
270
- ┌──────────┐ ┌───────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
271
- │ Telegram │ │ Slack │ │ WhatsApp │ │ Discord │ │ Signal │
272
- └────┬─────┘ └───┬───┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
273
- │ │ │ │ │
274
- └────────────┴───────────┴─────────────┴──────────────┘
275
-
276
- ┌─────────┴──────────┐
277
- Workspace Resolver (per-channel context: cwd + persona)
278
- └─────────┬──────────┘
279
-
280
- ┌──────┴───────┐
281
- │ Engine │ (Query routing, fallback)
282
- └──────┬───────┘
283
-
284
- ┌────────────────┼────────────────┐
285
- │ │ │
286
- ┌──────┴──────┐ ┌─────┴──────┐ ┌──────┴──────┐
287
- │ Claude SDK │ │ OpenAI │ │ Custom │
288
- (full agent)│ │ Compatible │ │ Models │
289
- └─────────────┘ └────────────┘ └─────────────┘
210
+ ```mermaid
211
+ flowchart TB
212
+ classDef ent fill:#1e293b,color:#e2e8f0,stroke:#475569
213
+ classDef core fill:#0f172a,color:#f1f5f9,stroke:#3b82f6,stroke-width:2px
214
+ classDef prov fill:#1e293b,color:#cbd5e1,stroke:#64748b
215
+ classDef mem fill:#1e293b,color:#cbd5e1,stroke:#10b981
216
+
217
+ TG[Telegram]:::ent
218
+ SL[Slack]:::ent
219
+ WA[WhatsApp]:::ent
220
+ DC[Discord]:::ent
221
+ SG[Signal]:::ent
222
+ WEB[Web UI · TUI · CLI]:::ent
223
+
224
+ TG & SL & WA & DC & SG & WEB --> WR
225
+
226
+ WR[Workspace Resolver<br/>per-channel cwd + persona]:::core
227
+ WR --> ENG[Engine<br/>routing · fallback · heartbeat]:::core
228
+
229
+ ENG --> CL[Claude SDK]:::prov
230
+ ENG --> OAI[OpenAI · Groq · Gemini ·<br/>NVIDIA · OpenRouter]:::prov
231
+ ENG --> OL[Ollama · Codex CLI ·<br/>OpenAI-compatible]:::prov
232
+
233
+ ENG -.reads.-> MEM
234
+ MEM[Memory Layer]:::mem
235
+ MEM --> L0[L0 / L1<br/>identity.md · preferences.md<br/>always plain-text]:::mem
236
+ MEM --> SQL[SQLite store · provider auto-detect<br/>Gemini · OpenAI · Ollama · FTS5]:::mem
237
+
238
+ ENG -.dispatches.-> SUB[Detached sub-agents<br/>independent claude -p]:::prov
290
239
  ```
291
240
 
292
- ### Provider Types
241
+ ### Provider matrix
293
242
 
294
- | Provider | Tool Use | Streaming | Vision | Auth |
295
- |----------|----------|-----------|--------|------|
296
- | Claude SDK | ✅ Full (native Bash, Read, Write, Web) | ✅ | ✅ | Claude CLI (OAuth) |
297
- | OpenAI, Groq, Gemini | ✅ Full (Shell, Files, Python, Web) | ✅ | Varies | API Key |
298
- | NVIDIA NIM | ✅ Full (Shell, Files, Python, Web) | ✅ | Varies | API Key (free) |
299
- | OpenRouter | ✅ Full (Shell, Files, Python, Web) | ✅ | | API Key |
300
- | Other OpenAI-compatible | ⚡ Auto-detect | ✅ | Varies | API Key |
243
+ | Provider | Tool use | Streaming | Vision | Auth |
244
+ |---|---|---|---|---|
245
+ | Claude SDK (Agent) | ✅ native (Bash, Read, Write, Web, MCP) | ✅ | ✅ | Claude CLI OAuth |
246
+ | OpenAI · Groq · Gemini · NVIDIA NIM · OpenRouter | ✅ universal tool use | ✅ | varies | API key |
247
+ | Ollama (local) | ✅ via tool-bridge | ✅ | varies | none |
248
+ | Codex CLI | ✅ subprocess | ✅ | | Codex CLI auth |
249
+ | Any OpenAI-compatible | ⚡ auto-detect | ✅ | varies | API key |
301
250
 
302
- > **Universal Tool Use:** Alvin Bot gives full agent capabilities to *any* provider that supports function calling — not just Claude. Shell commands, file operations, Python execution, web search, and more work across all major providers. If a provider doesn't support tool calls, Alvin Bot automatically falls back to text-only chat mode.
251
+ > **Universal tool use** Alvin gives full agent powers to any provider that supports function calling. Shell · files · Python · web work everywhere; providers without tool calls degrade cleanly to text-only chat.
303
252
 
304
- ### Project Structure
253
+ ### Project layout
305
254
 
306
255
  ```
307
- alvin-bot/
308
- ├── src/
309
- ├── index.ts # Entry point
310
- ├── engine.ts # Multi-model query engine
311
- ├── config.ts # Configuration
312
- ├── handlers/ # Message & command handlers
313
- ├── middleware/ # Auth & access control
314
- │ ├── platforms/ # Telegram, Slack, WhatsApp, Discord, Signal adapters
315
- │ ├── providers/ # AI provider implementations
316
- │ ├── services/ # Memory, voice, cron, plugins, workspaces, tool discovery
317
- │ ├── tui/ # Terminal UI
318
- └── web/ # Web server, APIs, setup wizard
319
- ├── web/public/ # Web UI (HTML/CSS/JS, zero build step)
320
- ├── plugins/ # Plugin directory (6 built-in)
321
- ├── docs/
322
- │ ├── install/ # Setup guides (macOS, Windows, Slack)
323
- │ └── custom-models.json # Custom model configurations
324
- ├── TOOLS.md # Custom tool definitions (Markdown)
325
- ├── SOUL.md # Agent personality
326
- ├── bin/cli.js # CLI entry point
327
- └── ecosystem.config.cjs # PM2 configuration
256
+ src/
257
+ ├── index.ts entry point
258
+ ├── engine.ts multi-model query engine
259
+ ├── handlers/ message + command handlers
260
+ ├── platforms/ Telegram · Slack · WhatsApp · Discord · Signal
261
+ ├── providers/ Claude SDK · OpenAI-compat · Ollama · Codex CLI
262
+ ├── services/
263
+ │ ├── embeddings/ v4.22 pluggable provider facade (Gemini/OpenAI/Ollama/FTS5)
264
+ │ ├── memory*.ts layered memory (L0-L3) + inject-mode resolver
265
+ │ ├── workspaces.ts per-channel cwd + persona registry
266
+ │ ├── alvin-dispatch.ts detached sub-agent orchestration
267
+ ├── browser-manager.ts 4-tier browser strategy
268
+ │ └── … cron · voice · skills · MCP · hooks · …
269
+ ├── tui/ terminal chat UI
270
+ └── web/ dashboard server + APIs
271
+ web/public/ zero-build HTML/CSS/JS UI
272
+ plugins/ 6 built-in plugins (hot-reload)
273
+ skills/ 14 SKILL.md files (hot-reload)
274
+ bin/cli.js CLI entry point
275
+ electron/ Electron wrapper for the .dmg build
328
276
  ```
329
277
 
330
278
  ---
@@ -368,7 +316,7 @@ The `cwd` auto-loads the project-specific `CLAUDE.md` via Claude SDK's `settingS
368
316
  ### Slack setup (5 minutes)
369
317
 
370
318
  1. Download the setup guide + manifest from the [latest release](https://github.com/alvbln/Alvin-Bot/releases/latest):
371
- - `slack-setup.md` — step-by-step instructions with screenshots
319
+ - `slack-setup.md` — step-by-step instructions
372
320
  - `slack-manifest.json` — copy-paste ready Slack App manifest
373
321
  2. Create a Slack App from the manifest at https://api.slack.com/apps → **Create New App** → **From an app manifest**
374
322
  3. Enable Socket Mode, generate an **App-Level Token** (starts with `xapp-`)
@@ -548,18 +496,26 @@ Plugins are auto-loaded at startup. Create your own by adding a directory with a
548
496
 
549
497
  ## 🎯 Skills
550
498
 
551
- Built-in skills in `skills/`:
499
+ Skills are markdown files in `skills/` that auto-activate when the user's message matches their trigger keywords. The skill body gets injected into the system prompt, giving the agent specialized expertise on demand. 14 ship built-in:
552
500
 
553
- | Skill | Triggers | Description |
554
- |-------|----------|-------------|
555
- | code-project | code, build, implement, debug, refactor | Software development workflows, architecture patterns |
556
- | data-analysis | analyze, chart, csv, excel, statistics | Data processing, visualization, statistical analysis |
557
- | document-creation | document, report, letter, pdf, write | Professional document creation and formatting |
558
- | email-summary | email, inbox, unread, newsletter | Email triage, summarization, priority sorting |
559
- | system-admin | server, deploy, docker, nginx, ssl | DevOps, deployment, system administration |
560
- | web-research | research, compare, find, review | Deep web research with source verification |
561
-
562
- Skills activate automatically when your message matches their trigger keywords. The skill's SKILL.md content is injected into the system prompt, giving the agent specialized expertise for that task.
501
+ | Skill | Description |
502
+ |---|---|
503
+ | **agent-browser** | Token-efficient web automation via the agent-browser CLI (accessibility-tree snapshots) Tier 1.5 of the browser stack |
504
+ | **apple-notes** | Read, create, search Apple Notes via AppleScript (macOS) |
505
+ | **browse** | 3-tier browser control: WebFetch · stealth Playwright · CDP with persistent profile |
506
+ | **code-project** | Software development workflows: build, debug, refactor, architecture patterns |
507
+ | **data-analysis** | CSV / JSON / Excel processing, charts, statistics via Python |
508
+ | **document-creation** | Professional PDFs, reports, letters with formatting |
509
+ | **email-summary** | Inbox triage, newsletter digests, priority sorting |
510
+ | **github** | Issues, PRs, releases, workflows via the `gh` CLI |
511
+ | **social-fetch** | Analyse Instagram / TikTok / YouTube / X URLs the user shares |
512
+ | **summarize** | Condense URLs, PDFs, long documents |
513
+ | **system-admin** | Server management, deploys, Docker, nginx, SSL |
514
+ | **weather** | Forecasts and conditions |
515
+ | **web-research** | Deep multi-source research with citation aggregation |
516
+ | **webcheck** | Security / SEO audit of a website |
517
+
518
+ Drop your own `<name>/SKILL.md` into `~/.alvin-bot/skills/` for hot-reload. List active skills via `/skills` or `alvin-bot skills`.
563
519
 
564
520
  ---
565
521
 
@@ -586,96 +542,40 @@ alvin-bot version # Show version
586
542
 
587
543
  ## 🗺️ Roadmap
588
544
 
589
- - [x] **Phase 1** Multi-Model Engine (provider abstraction, fallback chains)
590
- - [x] **Phase 2** — Memory System (vector search, user profiles, smart context)
591
- - [x] **Phase 3** — Rich Interactions (video messages, browser automation, email)
592
- - [x] **Phase 4** — Plugins & Tools (plugin ecosystem, MCP client, custom tools)
593
- - [x] **Phase 5** CLI Installer (setup wizard, Docker, health check)
594
- - [x] **Phase 6** — Web Dashboard (chat, settings, file manager, terminal)
595
- - [x] **Phase 7** — Multi-Platform (Telegram, Discord, WhatsApp, Signal adapters)
596
- - [x] **Phase 8** Universal Tool Use *(NEW)*All providers get agent powers:
597
- - Shell execution, file read/write/edit, directory listing
598
- - Python execution (Excel, PDF, charts, data processing)
599
- - Web fetch & search
600
- - Auto-detect function calling support per provider
601
- - Graceful fallback to text-only for providers without tool support
602
- - [x] **Phase 9** — Skill System + Self-Awareness + Language Adaptation:
603
- - SKILL.md files for specialized domain knowledge (email, data analysis, code, docs, research, sysadmin)
604
- - ✅ Auto-matching: skill triggers activate contextual expertise on demand
605
- - Self-Awareness Core: agent knows it IS the AI (no external LLM calls for text tasks)
606
- - ✅ Automatic language detection and adaptation (EN default, learns user preference)
607
- - Human-readable cron schedules + visual schedule builder in WebUI
608
- - ✅ Platform Manager refactor: all adapters via unified registration system
609
- - Cron notifications for all platforms (Telegram, WhatsApp, Discord, Signal)
610
- - ✅ PM2 auto-refresh on Maintenance page
611
- - WhatsApp group whitelist with per-contact access control
612
- - Owner approval gate (TelegramWhatsApp DM Discord Signal fallback)
613
- - Full media processing: photos, documents, audio/voice, video across all platforms
614
- - File Browser: create, edit, delete files with safety guards
615
- - Git history sanitized (personal data removed via git-filter-repo)
616
- - [x] **Phase 10** Anthropic API Provider + WebUI Provider Management
617
- - [x] Anthropic API key test case in WebUI (validation endpoint)
618
- - [x] "Add Provider" flow in WebUI add new providers post-setup without editing `.env`
619
- - [x] Claude SDK guided setup from WebUI (install check, login status, step-by-step)
620
- - [x] `.env.example` update with `ANTHROPIC_API_KEY`
621
- - [x] **Phase 11** — WebUI Professional Redesign
622
- - [x] Replace emoji icons with Lucide SVG icons (60+ icons, sidebar, pages, buttons)
623
- - [x] i18n framework (`i18n.js`) — bilingual DE/EN with browser-locale detection (~400 keys)
624
- - [x] Language toggle in sidebar footer (DE | EN)
625
- - [x] Typography upgrade (Inter webfont via Google Fonts)
626
- - [x] Gradient accents + subtle glassmorphism on cards
627
- - [x] Smooth page transitions (fade animation on page switch)
628
- - [x] Skeleton loading states + status pulse animations
629
- - [x] Command Palette (Cmd+K / Ctrl+K) with fuzzy search
630
- - [x] **Phase 12** — Native Installers (Non-Techie Friendly)
631
- - [x] Electron wrapper (embedded Node.js + WebUI + tray icon)
632
- - [x] macOS `.dmg` build via electron-builder (arm64)
633
- - [ ] Windows `.exe` (NSIS) via electron-builder
634
- - [ ] Linux `.AppImage` + `.deb` via electron-builder
635
- - [x] Auto-update mechanism (electron-updater)
636
- - [x] GUI Setup Wizard (provider selection, Telegram token, first-run experience)
637
- - [ ] Homebrew formula (`brew install alvin-bot`)
638
- - [ ] Scoop manifest for Windows
639
- - [ ] One-line install script
640
- - [x] Docker Compose polish (production-ready `docker-compose.yml`)
641
- - [x] **Phase 13** — npm publish (security audit)
642
- - [x] **Phase 14** — Async Sub-Agents (v4.10.0)
643
- - [x] `run_in_background: true` system prompt hint for Claude SDK
644
- - [x] Async-agent watcher polling `outputFile` JSONL, delivering results as separate messages
645
- - [x] Session-bound sub-agents (each session spawns its own background workers)
646
- - [x] **Phase 15** — Memory Persistence + Smart Loading (v4.11.0)
647
- - [x] Session persistence across bot restarts (debounced atomic flush, v2 envelope)
648
- - [x] SDK memory injection (MEMORY.md in every system prompt, not just tool-call dependent)
649
- - [x] Semantic recall on SDK first-turn via embeddings
650
- - [x] Layered memory stack (L0 identity / L1 preferences / L2 projects / L3 vector search)
651
- - [x] Auto-fact extraction during compaction (Mem0-style)
652
- - [x] **Phase 16** — Multi-Session + Slack Interface (v4.12.0)
653
- - [x] Session-key fix: platform-message.ts routes through `buildSessionKey()`
654
- - [x] Workspace registry with hot-reload (`~/.alvin-bot/workspaces/*.md`)
655
- - [x] Workspace resolver in platform handlers (per-channel persona + cwd)
656
- - [x] Slack adapter polish: progress ticker (`chat.update`), typing status (`assistant.threads.setStatus`), channel name cache
657
- - [x] Telegram `/workspace` + `/workspaces` commands (feature parity)
658
- - [x] Per-workspace cost aggregation + Web UI workspace cards
659
- - [x] Slack setup guide + copy-paste app manifest (in GitHub Release assets)
660
- - [x] **Phase 17** — Truly detached sub-agents + multi-platform dispatch (v4.13.0 – v4.14.2, 2026-04-16)
661
- - [x] `alvin_dispatch_agent` MCP tool — spawns independent `claude -p` subprocesses that survive parent aborts (v4.13.0)
662
- - [x] Slack `/alvin` slash command (namespaced parent with subcommands: status / new / effort / help + LLM fallthrough) (v4.13.2)
663
- - [x] Sub-agent dispatch on Slack, Discord, WhatsApp via platform-aware delivery registry (v4.14.0)
664
- - [x] `/subagents list` merged view — v4.0.0 bot-level agents + v4.13+ detached dispatches in one list (v4.14.1)
665
- - [x] Watcher zombie guard — missing outputFile > 10 min delivers as failed instead of 12h timeout (v4.14.2)
666
- - [x] Staleness-based partial output recovery for interrupted sub-agents (v4.12.4)
667
- - [ ] SQLite migration of the embeddings index (currently 128 MB JSON)
668
- - [ ] Per-workspace memory layer (additive over global) — facts learned in one workspace stay there unless explicitly promoted to global
669
- - [ ] Per-workspace provider override (`provider:` in frontmatter) — e.g. one workspace uses Claude Opus, another uses a cheaper model
670
- - [ ] Per-workspace skill allowlist — scope Apple Notes to personal workspace, sysadmin only to devops workspace, etc.
671
- - [ ] Multi-User Slack (real `per-channel-peer` mode) — different users in the same Slack channel get their own sub-sessions
672
- - [ ] Workspace cloning / templates — `/workspace clone my-project as my-fork` spins up a new workspace from an existing one
673
- - [ ] Daily log decay / archive — older daily logs move to cold storage after N days
674
- - [ ] **Phase 18** — Security + Platform hardening (from v4.12.1 audit, prioritized)
675
- - [ ] **P1 — Electron major upgrade** (35 → 41+) — fixes 1 HIGH + 5 MODERATE Electron CVEs in the Desktop-Build path. Major version jump, requires full rebuild + test of `.dmg` flow. Separate release (likely bundled with Windows `.exe` work).
676
- - [ ] **P1 — Prompt injection defense strategy** — not a single fix but a design debate: heuristic filters vs allow-list vs no-sandbox-accept-the-risk. Currently handled as a documented design-constraint (README security section), not as a code filter. When we decide the policy, implement it across all message entry points.
677
- - [ ] **P2 — TypeScript 5 → 6 upgrade** — major release, likely breaking changes in strict mode. Needs a dedicated release + test sweep. Low priority since 5.x is still supported.
678
- - [ ] **P0 for v5.0 — MCP plugin sandboxing** — currently MCP servers run with full Node privileges. Plan: run each MCP in a child process with restricted FS + network policy (similar to deno-permission model). Architectural change, v5.0 territory.
545
+ > Per-version details: see [`CHANGELOG.md`](CHANGELOG.md). The roadmap is a forward-looking summary, not a changelog.
546
+
547
+ ### Recently shipped
548
+
549
+ | Version | Theme | Highlights |
550
+ |---|---|---|
551
+ | **v4.22** *(May 2026)* | Memory architecture overhaul | Pluggable embedding providers **Gemini · OpenAI · Ollama · FTS5 (zero-config keyword fallback)**. Auto-detection picks the best available, so users with no API key still get a working indexed memory store. Smart inject mode stops bulk-injecting `MEMORY.md` once SQLite is populated. |
552
+ | **v4.21** | Agent Browser skill | Tier-1.5 token-efficient web automation via the [agent-browser](https://github.com/vercel-labs/agent-browser) CLI opt-in by install. ~90 % token reduction vs Playwright on cooperative pages. |
553
+ | **v4.20** | SQLite-backed vector memory | Replaces the legacy 128 MB JSON index. Automatic migration on first start, per-chunk INSERT/UPDATE, lazy native binary load with graceful fallback. |
554
+ | **v4.18 – v4.19** | Reliability + per-workspace overrides | SDK auto-recovery on token rotation / quota exhaustion / empty streams. Per-workspace `effort` / `provider` / `voice` / `temperature` / `toolset`. |
555
+ | **v4.17** | Hardening audit | Disk cleanup service, hardening fixes from internal audit. |
556
+ | **v4.13 – v4.14** | Detached sub-agents | `alvin_dispatch_agent` MCP tool spawns independent `claude -p` subprocesses that survive parent aborts. Multi-platform dispatch (Slack / Discord / WhatsApp). Watcher zombie guard. |
557
+ | **v4.10 – v4.12** | Multi-session + Slack | Workspace registry with hot-reload, per-channel personas + cwd, Slack adapter with progress ticker + typing status, owner approval gate, async sub-agents. |
558
+
559
+ ### 🏛️ Foundations (built before v4.10)
560
+
561
+ Multi-model provider abstraction with fallback chains · plugin & skill ecosystems with hot-reload · multi-platform adapters (Telegram, WhatsApp, Discord, Signal, Slack) · Web UI with i18n + command palette · native macOS `.dmg` via Electron · Docker Compose · npm distribution · MCP client + custom tools · universal tool use across providers · full media pipeline (audio · video · photo · voice).
562
+
563
+ ### 🎯 On the radar
564
+
565
+ | Priority | Item | Why |
566
+ |---|---|---|
567
+ | **P0 v5.0** | MCP plugin sandboxing | MCP servers currently run with full Node privileges. Plan: child process with restricted FS + network policy (deno-permission style). Architectural change. |
568
+ | **P1** | Electron major upgrade (3541+) + Windows `.exe` | Closes desktop-build CVEs, unblocks the only platform still missing a native installer. |
569
+ | **P1** | Prompt injection defense policy | Needs a design decision (heuristic filter / allow-list / accept-the-risk with clearer warnings) and consistent enforcement at every message entry point. |
570
+ | **P2** | Per-workspace memory layer | Facts learned in one workspace stay scoped unless explicitly promoted. Builds on the v4.22 SQLite store. |
571
+ | **P2** | Per-workspace skill allowlist | Scope Apple Notes to personal workspace, sysadmin tools to devops only, etc. |
572
+ | **P2** | Multi-user Slack (`per-channel-peer`) | Different users in the same Slack channel get their own sub-sessions. |
573
+ | **P3** | Linux `.AppImage` / `.deb`, Homebrew formula, Scoop manifest, one-line install script | Platform reach for non-npm users. |
574
+ | **P3** | Daily-log decay / archive | Older daily logs move to cold storage after N days. |
575
+ | **P3** | Workspace cloning / templates | `/workspace clone my-project as my-fork` spins up a new workspace from an existing one. |
576
+ | **P3** | TypeScript 5 → 6 | 5.x still supported; strict-mode break-fix work, not urgent. |
577
+
578
+ Pull requests welcome see [`CONTRIBUTING.md`](CONTRIBUTING.md).
679
579
 
680
580
  ---
681
581
 
@@ -29,32 +29,40 @@ function parseInterval(input) {
29
29
  };
30
30
  return value * (mult[unit] || 60_000);
31
31
  }
32
- function nextCronRun(expression, after) {
32
+ function parseField(expr, min, max) {
33
+ if (expr === "*")
34
+ return Array.from({ length: max - min + 1 }, (_, i) => i + min);
35
+ if (expr.includes("/")) {
36
+ const [, step] = expr.split("/");
37
+ const s = parseInt(step);
38
+ return Array.from({ length: max - min + 1 }, (_, i) => i + min).filter((v) => v % s === 0);
39
+ }
40
+ if (expr.includes(","))
41
+ return expr.split(",").map(Number);
42
+ if (expr.includes("-")) {
43
+ const [a, b] = expr.split("-").map(Number);
44
+ return Array.from({ length: b - a + 1 }, (_, i) => i + a);
45
+ }
46
+ return [parseInt(expr)];
47
+ }
48
+ function parseCronFields(expression) {
33
49
  const parts = expression.trim().split(/\s+/);
34
50
  if (parts.length !== 5)
35
51
  return null;
36
52
  const [minExpr, hourExpr, dayExpr, monthExpr, weekdayExpr] = parts;
37
- function parseField(expr, min, max) {
38
- if (expr === "*")
39
- return Array.from({ length: max - min + 1 }, (_, i) => i + min);
40
- if (expr.includes("/")) {
41
- const [, step] = expr.split("/");
42
- const s = parseInt(step);
43
- return Array.from({ length: max - min + 1 }, (_, i) => i + min).filter((v) => v % s === 0);
44
- }
45
- if (expr.includes(","))
46
- return expr.split(",").map(Number);
47
- if (expr.includes("-")) {
48
- const [a, b] = expr.split("-").map(Number);
49
- return Array.from({ length: b - a + 1 }, (_, i) => i + a);
50
- }
51
- return [parseInt(expr)];
52
- }
53
- const minutes = parseField(minExpr, 0, 59);
54
- const hours = parseField(hourExpr, 0, 23);
55
- const days = parseField(dayExpr, 1, 31);
56
- const months = parseField(monthExpr, 1, 12);
57
- const weekdays = parseField(weekdayExpr, 0, 6);
53
+ return {
54
+ minutes: parseField(minExpr, 0, 59),
55
+ hours: parseField(hourExpr, 0, 23),
56
+ days: parseField(dayExpr, 1, 31),
57
+ months: parseField(monthExpr, 1, 12),
58
+ weekdays: parseField(weekdayExpr, 0, 6),
59
+ };
60
+ }
61
+ function nextCronRun(expression, after) {
62
+ const fields = parseCronFields(expression);
63
+ if (!fields)
64
+ return null;
65
+ const { minutes, hours, days, months, weekdays } = fields;
58
66
  const candidate = new Date(after);
59
67
  candidate.setSeconds(0, 0);
60
68
  candidate.setMinutes(candidate.getMinutes() + 1);
@@ -75,6 +83,39 @@ function nextCronRun(expression, after) {
75
83
  }
76
84
  return null;
77
85
  }
86
+ /**
87
+ * Find the most recent scheduled trigger at or before `before`. Returns
88
+ * null for non-cron schedules (interval strings) and for jobs whose
89
+ * cron expression has never matched in the search window.
90
+ *
91
+ * Used by the slot-aware catch-up rule: if a job's lastAttemptAt is
92
+ * at or after this trigger, the slot is "already attempted" and
93
+ * handleStartupCatchup leaves it alone.
94
+ */
95
+ export function prevCronRun(expression, before) {
96
+ const fields = parseCronFields(expression);
97
+ if (!fields)
98
+ return null;
99
+ const { minutes, hours, days, months, weekdays } = fields;
100
+ const candidate = new Date(before);
101
+ candidate.setSeconds(0, 0);
102
+ for (let i = 0; i < 366 * 24 * 60; i++) {
103
+ const m = candidate.getMinutes();
104
+ const h = candidate.getHours();
105
+ const d = candidate.getDate();
106
+ const mo = candidate.getMonth() + 1;
107
+ const wd = candidate.getDay();
108
+ if (minutes.includes(m) &&
109
+ hours.includes(h) &&
110
+ days.includes(d) &&
111
+ months.includes(mo) &&
112
+ weekdays.includes(wd)) {
113
+ return candidate;
114
+ }
115
+ candidate.setMinutes(candidate.getMinutes() - 1);
116
+ }
117
+ return null;
118
+ }
78
119
  /** Compute the next run relative to an explicit base timestamp.
79
120
  * Used by prepareForExecution to make the interval calculation stable
80
121
  * even when `lastRunAt` is stale or null. */
@@ -108,16 +149,49 @@ export function prepareForExecution(job, now) {
108
149
  // ── Startup catch-up ───────────────────────────────────────
109
150
  /** Default grace window for catching up an interrupted attempt on boot. */
110
151
  export const DEFAULT_CATCHUP_GRACE_MS = 6 * 60 * 60 * 1000; // 6 h
152
+ /**
153
+ * Returns true when the job's *current* schedule slot has already been
154
+ * attempted — i.e. the bot fired the job for this slot before the
155
+ * crash. Even if the attempt didn't complete, we treat the slot as
156
+ * spent and don't auto-retry on boot. Users can still manually rerun
157
+ * via `/cron run`.
158
+ *
159
+ * - Cron expression: the slot is the most recent past trigger time
160
+ * (e.g. for `0 8 * * *` at 11:00, the slot starts at today 08:00).
161
+ * `lastAttemptAt >= prevTrigger` → already attempted.
162
+ * - Interval (5m, 1h, …): the slot is one interval wide.
163
+ * `now - lastAttemptAt < intervalMs` → still inside the slot the
164
+ * crashed attempt belonged to.
165
+ */
166
+ function slotAlreadyAttempted(job, now) {
167
+ if (!job.lastAttemptAt)
168
+ return false;
169
+ const intervalMs = parseInterval(job.schedule);
170
+ if (intervalMs !== null) {
171
+ return now - job.lastAttemptAt < intervalMs;
172
+ }
173
+ const lastTrigger = prevCronRun(job.schedule, new Date(now));
174
+ if (!lastTrigger)
175
+ return false;
176
+ return job.lastAttemptAt >= lastTrigger.getTime();
177
+ }
111
178
  /**
112
179
  * Rewind `nextRunAt` to `now` for every enabled job whose most recent
113
- * attempt never completed AND is still inside the grace window. This
114
- * makes the very next scheduler tick pick the job up again, without
115
- * double-firing jobs that actually finished.
180
+ * attempt never completed AND is still inside the grace window AND
181
+ * whose current schedule slot hasn't already been attempted.
182
+ *
183
+ * The slot check (slotAlreadyAttempted) is the bug fix for the
184
+ * "duplicate daily run after reboot" report: if the daily 08:00 job
185
+ * fired at 08:00, crashed before completion, and the bot reboots at
186
+ * 11:00, the old logic would re-fire the job at 11:00. The new logic
187
+ * sees lastAttemptAt = 08:00 ≥ today's 08:00 trigger and leaves the
188
+ * job's nextRunAt pointing at tomorrow 08:00, accepting the loss.
116
189
  *
117
190
  * Jobs whose crashed attempt is older than the grace window are NOT
118
- * caught up — the assumption is that such a run is too stale to be
119
- * meaningful (a "daily" run from yesterday isn't what the user wants
120
- * at 2pm today). Those jobs keep their scheduled future nextRunAt.
191
+ * caught up either — the assumption is that such a run is too stale
192
+ * to be meaningful (a "daily" run from yesterday isn't what the user
193
+ * wants at 2pm today). Those jobs keep their scheduled future
194
+ * nextRunAt.
121
195
  *
122
196
  * PURE: returns a fresh array, never mutates the input.
123
197
  */
@@ -136,7 +210,13 @@ export function handleStartupCatchup(jobs, now, graceMs = DEFAULT_CATCHUP_GRACE_
136
210
  return job; // clock weirdness — skip
137
211
  if (ageMs > graceMs)
138
212
  return job; // outside grace — give up
139
- // Within grace, never completed catch up on next tick.
213
+ // The current schedule slot has already been attempted (even if it
214
+ // crashed). Skip catch-up so the user doesn't get a surprise rerun
215
+ // hours after the originally scheduled time.
216
+ if (slotAlreadyAttempted(job, now))
217
+ return job;
218
+ // Within grace, never completed, and current slot hasn't been
219
+ // attempted yet → catch up on next tick.
140
220
  return { ...job, nextRunAt: now };
141
221
  });
142
222
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alvin-bot",
3
- "version": "4.22.0",
3
+ "version": "4.22.1",
4
4
  "description": "Alvin Bot — Your personal AI agent on Telegram, WhatsApp, Discord, Signal, and Web.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
Binary file
Binary file
Binary file
Binary file
Binary file