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 +0 -0
- package/CHANGELOG.md +6 -0
- package/README.md +144 -244
- package/dist/services/cron-scheduling.js +109 -29
- package/package.json +1 -1
- package/docs/screenshots/00-Login.png +0 -0
- package/docs/screenshots/01-Chat-Dark-Conversation.png +0 -0
- package/docs/screenshots/02-Chat.png +0 -0
- package/docs/screenshots/03-Dashboard-Overview.png +0 -0
- package/docs/screenshots/04-AI-Models-and-Providers.png +0 -0
- package/docs/screenshots/05-Personality-Editor.png +0 -0
- package/docs/screenshots/06-Memory-Manager.png +0 -0
- package/docs/screenshots/07-Active-Sessions.png +0 -0
- package/docs/screenshots/08-File-Browser.png +0 -0
- package/docs/screenshots/09-Scheduled-Jobs.png +0 -0
- package/docs/screenshots/10-Custom-Tools.png +0 -0
- package/docs/screenshots/11-Plugins-and-MCP.png +0 -0
- package/docs/screenshots/12-Messaging-Platforms.png +0 -0
- package/docs/screenshots/12.1-Messaging-Platforms-WhatsApp-Groups-List.png +0 -0
- package/docs/screenshots/12.2-Messaging-Platforms-WA-Group-Details.png +0 -0
- package/docs/screenshots/13-User-Management.png +0 -0
- package/docs/screenshots/14-Web-Terminal.png +0 -0
- package/docs/screenshots/15-Maintenance-and-Health.png +0 -0
- package/docs/screenshots/16-Settings-and-Env.png +0 -0
- package/docs/screenshots/TG-commands.png +0 -0
- package/docs/screenshots/TG.png +0 -0
- package/docs/screenshots/_Mac-Installer.png +0 -0
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
|
|
3
|
+
> Your personal AI agent — on Telegram, WhatsApp, Discord, Slack, Signal, Terminal, and Web.
|
|
4
4
|
|
|
5
|
-
|
|
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-
|
|
61
|
-
- **Automatic
|
|
62
|
-
- **
|
|
63
|
-
- **
|
|
64
|
-
- **
|
|
65
|
-
- **
|
|
66
|
-
- **
|
|
67
|
-
- **
|
|
68
|
-
- **
|
|
69
|
-
- **
|
|
70
|
-
- **
|
|
71
|
-
- **
|
|
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** —
|
|
75
|
-
- **Slack** — Socket Mode
|
|
76
|
-
- **WhatsApp** —
|
|
77
|
-
- **
|
|
78
|
-
- **
|
|
79
|
-
- **
|
|
80
|
-
- **
|
|
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
|
-
- **
|
|
85
|
-
- **
|
|
86
|
-
- **MCP
|
|
87
|
-
- **Cron
|
|
88
|
-
- **Voice** —
|
|
89
|
-
- **Vision** —
|
|
90
|
-
- **
|
|
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
|
-
-
|
|
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
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
|
241
|
+
### Provider matrix
|
|
293
242
|
|
|
294
|
-
| Provider | Tool
|
|
295
|
-
|
|
296
|
-
| Claude SDK | ✅
|
|
297
|
-
| OpenAI
|
|
298
|
-
|
|
|
299
|
-
|
|
|
300
|
-
|
|
|
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
|
|
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
|
|
253
|
+
### Project layout
|
|
305
254
|
|
|
306
255
|
```
|
|
307
|
-
|
|
308
|
-
├──
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
│ ├──
|
|
315
|
-
│ ├──
|
|
316
|
-
│ ├──
|
|
317
|
-
│ ├──
|
|
318
|
-
│
|
|
319
|
-
|
|
320
|
-
├──
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
|
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
|
-
|
|
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 |
|
|
554
|
-
|
|
555
|
-
|
|
|
556
|
-
|
|
|
557
|
-
|
|
|
558
|
-
|
|
|
559
|
-
|
|
|
560
|
-
|
|
|
561
|
-
|
|
562
|
-
|
|
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
|
-
- [
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
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 (35 → 41+) + 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
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
114
|
-
*
|
|
115
|
-
*
|
|
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
|
|
119
|
-
* meaningful (a "daily" run from yesterday isn't what the user
|
|
120
|
-
* at 2pm today). Those jobs keep their scheduled future
|
|
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
|
-
//
|
|
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
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/screenshots/TG.png
DELETED
|
Binary file
|
|
Binary file
|