multis 0.1.0
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/.env.example +19 -0
- package/CLAUDE.md +66 -0
- package/README.md +98 -0
- package/package.json +32 -0
- package/skills/capture.md +60 -0
- package/skills/files.md +38 -0
- package/skills/shell.md +53 -0
- package/skills/weather.md +32 -0
- package/src/bot/handlers.js +712 -0
- package/src/bot/telegram.js +51 -0
- package/src/cli/setup-beeper.js +239 -0
- package/src/config.js +157 -0
- package/src/governance/audit.js +95 -0
- package/src/governance/validate.js +99 -0
- package/src/index.js +71 -0
- package/src/indexer/chunk.js +68 -0
- package/src/indexer/chunker.js +87 -0
- package/src/indexer/index.js +150 -0
- package/src/indexer/parsers.js +299 -0
- package/src/indexer/store.js +256 -0
- package/src/llm/anthropic.js +106 -0
- package/src/llm/base.js +38 -0
- package/src/llm/client.js +34 -0
- package/src/llm/ollama.js +148 -0
- package/src/llm/openai.js +107 -0
- package/src/llm/prompts.js +71 -0
- package/src/memory/capture.js +85 -0
- package/src/memory/manager.js +123 -0
- package/src/platforms/base.js +38 -0
- package/src/platforms/beeper.js +238 -0
- package/src/platforms/message.js +61 -0
- package/src/platforms/telegram.js +95 -0
- package/src/skills/executor.js +125 -0
package/.env.example
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Telegram Bot Token (get from @BotFather)
|
|
2
|
+
TELEGRAM_BOT_TOKEN=your_bot_token_here
|
|
3
|
+
|
|
4
|
+
# LLM Provider (anthropic, openai, ollama, gemini)
|
|
5
|
+
LLM_PROVIDER=anthropic
|
|
6
|
+
|
|
7
|
+
# API Keys (only needed for cloud providers)
|
|
8
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
9
|
+
OPENAI_API_KEY=sk-...
|
|
10
|
+
GEMINI_API_KEY=...
|
|
11
|
+
|
|
12
|
+
# LLM Model
|
|
13
|
+
LLM_MODEL=claude-sonnet-4-5-20250929
|
|
14
|
+
|
|
15
|
+
# Ollama URL (if using local Ollama)
|
|
16
|
+
OLLAMA_URL=http://localhost:11434
|
|
17
|
+
|
|
18
|
+
# Pairing Code (generated during init)
|
|
19
|
+
PAIRING_CODE=
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# multis
|
|
2
|
+
|
|
3
|
+
Personal chatbot/assistant that runs locally. Control your laptop and query your documents from Telegram, Beeper, or Matrix. Local-first, LLM-agnostic, governance-first.
|
|
4
|
+
|
|
5
|
+
## Tech Stack
|
|
6
|
+
|
|
7
|
+
- Node.js >= 20, vanilla (minimal deps)
|
|
8
|
+
- Telegraf (Telegram), better-sqlite3 (SQLite + FTS5), pdf-parse, mammoth
|
|
9
|
+
- Beeper Desktop API on localhost:23373 (opt-in)
|
|
10
|
+
- LLM: Anthropic, OpenAI, Ollama (configurable via .env)
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
npm install # install deps
|
|
16
|
+
npm start # node src/index.js
|
|
17
|
+
npm run dev # node --watch src/index.js
|
|
18
|
+
npm test # node --test test/**/*.test.js
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Project Layout
|
|
22
|
+
|
|
23
|
+
| Path | Purpose |
|
|
24
|
+
|------|---------|
|
|
25
|
+
| src/index.js | Entry point, starts platforms |
|
|
26
|
+
| src/config.js | Load ~/.multis/config.json + .env |
|
|
27
|
+
| src/bot/handlers.js | Message router, all command handlers |
|
|
28
|
+
| src/platforms/ | Platform adapters (telegram.js, beeper.js, base.js, message.js) |
|
|
29
|
+
| src/governance/ | Allowlist/denylist validation + audit log |
|
|
30
|
+
| src/skills/executor.js | Shell exec, file read |
|
|
31
|
+
| src/indexer/ | Doc parsing, chunking, SQLite FTS5 store |
|
|
32
|
+
| src/llm/ | LLM providers + RAG prompt builder |
|
|
33
|
+
| ~/.multis/ | Runtime data: config.json, governance.json, multis.db, audit.log |
|
|
34
|
+
|
|
35
|
+
## Key Patterns
|
|
36
|
+
|
|
37
|
+
1. **Platform abstraction**: All platforms implement base.js, emit normalized Message objects to a shared router in handlers.js
|
|
38
|
+
2. **Command routing**: Telegram uses `/` prefix, Beeper uses `//`. Plain text routes to implicit `/ask` (RAG pipeline)
|
|
39
|
+
3. **Owner model**: First paired user becomes owner. Owner-only commands: exec, read, index. Check with `isOwner(userId, config)`
|
|
40
|
+
|
|
41
|
+
## Config and Secrets
|
|
42
|
+
|
|
43
|
+
- API keys in `.env` (TELEGRAM_BOT_TOKEN, ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, LLM_PROVIDER, LLM_MODEL)
|
|
44
|
+
- Runtime config auto-created at ~/.multis/config.json from .multis-template/
|
|
45
|
+
- Pairing code auto-generated, printed on startup
|
|
46
|
+
|
|
47
|
+
## POC Status
|
|
48
|
+
|
|
49
|
+
POC 1-4 done (bot, skills, indexing, RAG). POC 5 next (memory + ACT-R). POC 6 (daemon), POC 7 (multi-platform) planned.
|
|
50
|
+
|
|
51
|
+
## Constraints
|
|
52
|
+
|
|
53
|
+
- Each POC < 500 lines
|
|
54
|
+
- No frameworks beyond Telegraf
|
|
55
|
+
- Single user, no shared hosting
|
|
56
|
+
- Telegraf: `bot.on('text')` fires for ALL messages including commands -- filter with `text.startsWith('/')`
|
|
57
|
+
|
|
58
|
+
## Adding Features
|
|
59
|
+
|
|
60
|
+
- New command: add handler in handlers.js, add case to createMessageRouter switch, update help text
|
|
61
|
+
- New LLM provider: extend LLMProvider in llm/base.js, add to llm/client.js factory, add env var to config.js
|
|
62
|
+
- New platform: extend platforms/base.js, add to index.js startup
|
|
63
|
+
|
|
64
|
+
## Deep Reference
|
|
65
|
+
|
|
66
|
+
-> docs/KNOWLEDGE_BASE.md (topic index with links to full docs)
|
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# multis
|
|
2
|
+
|
|
3
|
+
**A personal and business AI agent that lives in your chat apps** — answering questions from your documents, running commands on your machine, and auto-responding to contacts when you want it to.
|
|
4
|
+
|
|
5
|
+
Runs locally with persistent memory, governed by allowlists and audit logs.
|
|
6
|
+
|
|
7
|
+
## Why multis?
|
|
8
|
+
|
|
9
|
+
- **Local-first:** Your data never leaves your machine
|
|
10
|
+
- **All your chats, one config:** Telegram, WhatsApp, Signal, Discord — via Beeper bridges or self-hosted Matrix
|
|
11
|
+
- **LLM agnostic:** Anthropic, OpenAI, Ollama — swap providers without code changes
|
|
12
|
+
- **Persistent memory:** ACT-R activation decay keeps recent context hot, old conversations fade naturally
|
|
13
|
+
- **Document-aware:** Indexes PDFs and DOCX with hierarchical section-aware chunking, answers with citations
|
|
14
|
+
- **Governed:** Command allowlist/denylist + append-only audit logs
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install
|
|
20
|
+
cp .env.example .env # add your bot token + LLM API key
|
|
21
|
+
node src/index.js # start the bot
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Pair with your bot on Telegram using the pairing code shown on startup.
|
|
25
|
+
|
|
26
|
+
## How It Works
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
┌──────────────┐ ┌──────────────┐
|
|
30
|
+
│ Telegram │ │ Beeper │ (WhatsApp, Signal, Discord, ...)
|
|
31
|
+
│ Bot API │ │ Desktop API │
|
|
32
|
+
└──────┬───────┘ └──────┬───────┘
|
|
33
|
+
│ │
|
|
34
|
+
┌──────▼─────────────────▼──────────────────────┐
|
|
35
|
+
│ Message Router │
|
|
36
|
+
│ commands · RAG ask · chat modes · doc upload │
|
|
37
|
+
└──────┬─────────┬──────────┬───────────────────┘
|
|
38
|
+
│ │ │
|
|
39
|
+
┌──────▼──┐ ┌───▼────┐ ┌───▼──────────┐
|
|
40
|
+
│ Skills │ │ LLM │ │ Indexer │
|
|
41
|
+
│ (shell, │ │ (any │ │ (PDF, DOCX, │
|
|
42
|
+
│ files) │ │ provider│ │ MD → FTS5) │
|
|
43
|
+
└─────────┘ └────────┘ └──────────────┘
|
|
44
|
+
│ │ │
|
|
45
|
+
┌──────▼─────────▼──────────▼───────────────────┐
|
|
46
|
+
│ SQLite (FTS5 search · activation decay) │
|
|
47
|
+
│ Governance (allowlist · denylist · audit log) │
|
|
48
|
+
└────────────────────────────────────────────────┘
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Why Not openclaw?
|
|
52
|
+
|
|
53
|
+
Borrowed the good parts — daemon architecture, pairing flow, skill.md pattern — but made it simpler:
|
|
54
|
+
|
|
55
|
+
- **One config, all chats.** openclaw needs a separate API integration per channel (WhatsApp Baileys, Discord bot, Signal, etc). multis uses one config block and talks to Telegram + Beeper bridges + Matrix — all your networks through one setup.
|
|
56
|
+
- **Persistent activation-decay memory.** ACT-R model (ported from Aurora) means recent context stays hot, old conversations fade naturally. Not just a chat log — a memory with priorities.
|
|
57
|
+
- **Structured document chunking.** Hierarchical section-aware chunking for PDFs and DOCX (also from Aurora). The bot knows which chapter and section a chunk came from, not just raw text.
|
|
58
|
+
- **No gateway, no plugin system.** openclaw has a complex gateway + plugin architecture. multis is a flat router with skills — add a command in one file, done.
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
- **Ask questions** — `/ask` or just type naturally. RAG pipeline searches your docs, passes context to the LLM, answers with citations.
|
|
63
|
+
- **Run commands** — `/exec ls ~/Documents` with governance enforcement (allowlist/denylist)
|
|
64
|
+
- **Index documents** — Upload PDFs and DOCX files, or `/index <path>`. Hierarchical chunking preserves document structure.
|
|
65
|
+
- **Chat modes** — Set any Beeper chat to `personal` (self-use) or `business` (auto-respond to incoming messages)
|
|
66
|
+
- **Audit everything** — Append-only tamper-evident log of all commands and actions
|
|
67
|
+
|
|
68
|
+
## Roadmap
|
|
69
|
+
|
|
70
|
+
- [x] POC 1: Telegram bot + pairing
|
|
71
|
+
- [x] POC 2: Skills (shell exec, file read, governance)
|
|
72
|
+
- [x] POC 3: Document indexing (PDF/DOCX → FTS5)
|
|
73
|
+
- [x] POC 4: LLM RAG + chat modes
|
|
74
|
+
- [ ] POC 5: Memory (ACT-R activation decay + memory.md)
|
|
75
|
+
- [ ] POC 6: Daemon + CLI onboarding
|
|
76
|
+
- [ ] POC 7: Multi-platform (Beeper Desktop + self-hosted Matrix)
|
|
77
|
+
|
|
78
|
+
## Tech Stack
|
|
79
|
+
|
|
80
|
+
Node.js (vanilla, minimal deps) · Telegraf · better-sqlite3 · pdf-parse · mammoth
|
|
81
|
+
|
|
82
|
+
## Project Structure
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
src/
|
|
86
|
+
├── bot/handlers.js # Message router + all command handlers
|
|
87
|
+
├── platforms/ # Telegram + Beeper adapters, normalized Message
|
|
88
|
+
├── llm/ # Anthropic, OpenAI, Ollama providers + RAG prompts
|
|
89
|
+
├── indexer/ # PDF/DOCX parsing, chunking, SQLite FTS5 store
|
|
90
|
+
├── governance/ # Command validation + audit logging
|
|
91
|
+
├── skills/ # Shell exec, file read
|
|
92
|
+
├── config.js # ~/.multis/config.json + .env loader
|
|
93
|
+
└── index.js # Entry point
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "multis",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A personal chatbot and assistant that runs on your computer",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node src/index.js",
|
|
8
|
+
"dev": "node --watch src/index.js",
|
|
9
|
+
"test": "node --test test/**/*.test.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"chatbot",
|
|
13
|
+
"personal-assistant",
|
|
14
|
+
"telegram",
|
|
15
|
+
"llm",
|
|
16
|
+
"rag",
|
|
17
|
+
"local-first"
|
|
18
|
+
],
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20.0.0"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@matrix-org/matrix-sdk-crypto-nodejs": "^0.4.0",
|
|
26
|
+
"better-sqlite3": "^11.7.0",
|
|
27
|
+
"mammoth": "^1.8.0",
|
|
28
|
+
"matrix-bot-sdk": "^0.8.0",
|
|
29
|
+
"pdf-parse": "^1.1.1",
|
|
30
|
+
"telegraf": "^4.16.3"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: capture
|
|
3
|
+
description: Extract durable notes from conversation history for per-chat memory
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Conversation Capture
|
|
7
|
+
|
|
8
|
+
You are reviewing a conversation from a chat. Extract only what's worth remembering long-term. Skip small talk, greetings, and filler.
|
|
9
|
+
|
|
10
|
+
## What to extract
|
|
11
|
+
|
|
12
|
+
**Decisions made**
|
|
13
|
+
- What was decided, by whom, when
|
|
14
|
+
- "We agreed to..." or "Let's go with..."
|
|
15
|
+
|
|
16
|
+
**Action items**
|
|
17
|
+
- Who needs to do what, by when
|
|
18
|
+
- Follow-ups, next steps, deadlines
|
|
19
|
+
|
|
20
|
+
**Preferences stated**
|
|
21
|
+
- "I prefer...", "Always do X", "Don't ever..."
|
|
22
|
+
- Communication style, formatting preferences
|
|
23
|
+
|
|
24
|
+
**Key facts**
|
|
25
|
+
- Names, roles, relationships
|
|
26
|
+
- Dates, numbers, amounts
|
|
27
|
+
- Products, services, accounts mentioned
|
|
28
|
+
|
|
29
|
+
**Context that would be lost**
|
|
30
|
+
- Why a decision was made (not just what)
|
|
31
|
+
- Constraints or blockers mentioned
|
|
32
|
+
- Emotional tone if relevant (frustrated, happy, urgent)
|
|
33
|
+
|
|
34
|
+
## Output format
|
|
35
|
+
|
|
36
|
+
Bullet points, concise, present tense. Group by category. Skip categories with nothing to report.
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
## Decisions
|
|
40
|
+
- Using Anthropic for LLM provider (chosen over OpenAI for cost)
|
|
41
|
+
|
|
42
|
+
## Action items
|
|
43
|
+
- Alice to send contract by Friday
|
|
44
|
+
- Follow up on invoice #1234 next week
|
|
45
|
+
|
|
46
|
+
## Preferences
|
|
47
|
+
- Prefers formal tone in customer messages
|
|
48
|
+
- Wants responses under 3 sentences
|
|
49
|
+
|
|
50
|
+
## Key facts
|
|
51
|
+
- Alice is the project lead at Acme Corp
|
|
52
|
+
- Budget is $50k for Q1
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## What NOT to capture
|
|
56
|
+
|
|
57
|
+
- Greetings, sign-offs, pleasantries
|
|
58
|
+
- Questions that were fully answered (capture the answer, not the question)
|
|
59
|
+
- Repeated information already in memory
|
|
60
|
+
- Technical debugging back-and-forth (capture the resolution only)
|
package/skills/files.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: files
|
|
3
|
+
description: List and read files in allowed directories
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# File Operations
|
|
7
|
+
|
|
8
|
+
List and read files within allowed directories.
|
|
9
|
+
|
|
10
|
+
## Allowed Directories
|
|
11
|
+
|
|
12
|
+
By default, you can access:
|
|
13
|
+
- `~/Documents`
|
|
14
|
+
- `~/Downloads`
|
|
15
|
+
- `~/Projects`
|
|
16
|
+
- `~/Desktop`
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# List PDF files
|
|
22
|
+
/files ~/Documents/*.pdf
|
|
23
|
+
|
|
24
|
+
# List all files in directory
|
|
25
|
+
/files ~/Downloads
|
|
26
|
+
|
|
27
|
+
# Read a file
|
|
28
|
+
/read ~/Documents/notes.txt
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Denied Directories
|
|
32
|
+
|
|
33
|
+
These directories are off-limits:
|
|
34
|
+
- `/etc` - System configuration
|
|
35
|
+
- `/var` - System data
|
|
36
|
+
- `/usr` - System binaries
|
|
37
|
+
- `/System` - macOS system files
|
|
38
|
+
- `/bin`, `/sbin` - System binaries
|
package/skills/shell.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: shell
|
|
3
|
+
description: Execute safe shell commands (allowlisted by governance)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Shell Commands
|
|
7
|
+
|
|
8
|
+
Execute shell commands that are allowed by the governance policy.
|
|
9
|
+
|
|
10
|
+
## Allowed Commands
|
|
11
|
+
|
|
12
|
+
By default, these commands are allowed:
|
|
13
|
+
- `ls` - List files
|
|
14
|
+
- `pwd` - Print working directory
|
|
15
|
+
- `cat` - Display file contents
|
|
16
|
+
- `grep` - Search text
|
|
17
|
+
- `find` - Find files
|
|
18
|
+
- `df` - Disk usage
|
|
19
|
+
- `du` - Directory usage
|
|
20
|
+
- `ps` - Process list
|
|
21
|
+
- `curl` - Make HTTP requests
|
|
22
|
+
- `git` - Git operations (safe ones)
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# List files
|
|
28
|
+
/exec ls -la ~/Documents
|
|
29
|
+
|
|
30
|
+
# Search for text
|
|
31
|
+
/exec grep -r "TODO" ~/Projects
|
|
32
|
+
|
|
33
|
+
# Check disk space
|
|
34
|
+
/exec df -h
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Denied Commands
|
|
38
|
+
|
|
39
|
+
These commands are explicitly denied for safety:
|
|
40
|
+
- `rm` - Remove files (too dangerous)
|
|
41
|
+
- `sudo` - Superuser (security risk)
|
|
42
|
+
- `dd` - Disk operations (destructive)
|
|
43
|
+
- `mkfs` - Format disk (destructive)
|
|
44
|
+
- `shutdown` - System control
|
|
45
|
+
- `reboot` - System control
|
|
46
|
+
|
|
47
|
+
## Confirmation Required
|
|
48
|
+
|
|
49
|
+
These commands require user confirmation:
|
|
50
|
+
- `mv` - Move files
|
|
51
|
+
- `cp` - Copy files
|
|
52
|
+
- `git push` - Push to remote
|
|
53
|
+
- `npm publish` - Publish package
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: weather
|
|
3
|
+
description: Get current weather (no API key required)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Weather
|
|
7
|
+
|
|
8
|
+
Get weather using wttr.in (free, no API key needed).
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Quick weather
|
|
14
|
+
/exec curl -s "wttr.in/London?format=3"
|
|
15
|
+
# Output: London: ⛅️ +8°C
|
|
16
|
+
|
|
17
|
+
# Detailed weather
|
|
18
|
+
/exec curl -s "wttr.in/London"
|
|
19
|
+
# Shows full forecast
|
|
20
|
+
|
|
21
|
+
# Specific location
|
|
22
|
+
/exec curl -s "wttr.in/NewYork?format=%l:+%c+%t"
|
|
23
|
+
# Output: New York: ⛅️ +15°C
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Format Options
|
|
27
|
+
|
|
28
|
+
- `%l` - Location name
|
|
29
|
+
- `%c` - Weather emoji
|
|
30
|
+
- `%t` - Temperature
|
|
31
|
+
- `%h` - Humidity
|
|
32
|
+
- `%w` - Wind speed
|