@geminixiang/mama 0.2.0-beta.4 → 0.2.0-beta.6
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/README.md +151 -417
- package/dist/adapter.d.ts +9 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +2 -1
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +71 -18
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +9 -2
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +5 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +69 -11
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +13 -3
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +1 -35
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +9 -2
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +15 -7
- package/dist/agent.js.map +1 -1
- package/dist/bindings.d.ts +2 -1
- package/dist/bindings.d.ts.map +1 -1
- package/dist/bindings.js.map +1 -1
- package/dist/commands/index.d.ts +5 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +15 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/login.d.ts +5 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +37 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/model.d.ts +14 -0
- package/dist/commands/model.d.ts.map +1 -0
- package/dist/commands/model.js +94 -0
- package/dist/commands/model.js.map +1 -0
- package/dist/commands/new.d.ts +9 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +28 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/registry.d.ts +7 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +14 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/session-view.d.ts +5 -0
- package/dist/commands/session-view.d.ts.map +1 -0
- package/dist/commands/session-view.js +38 -0
- package/dist/commands/session-view.js.map +1 -0
- package/dist/commands/types.d.ts +43 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/utils.d.ts +5 -0
- package/dist/commands/utils.d.ts.map +1 -0
- package/dist/commands/utils.js +9 -0
- package/dist/commands/utils.js.map +1 -0
- package/dist/config.d.ts +15 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +167 -56
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +74 -68
- package/dist/context.js.map +1 -1
- package/dist/execution-resolver.d.ts +6 -3
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +47 -14
- package/dist/execution-resolver.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/instrument.d.ts.map +1 -1
- package/dist/instrument.js +2 -3
- package/dist/instrument.js.map +1 -1
- package/dist/login/index.d.ts.map +1 -1
- package/dist/login/index.js +19 -8
- package/dist/login/index.js.map +1 -1
- package/dist/login/portal.d.ts.map +1 -1
- package/dist/login/portal.js +7 -7
- package/dist/login/portal.js.map +1 -1
- package/dist/login/session.d.ts +3 -2
- package/dist/login/session.d.ts.map +1 -1
- package/dist/login/session.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +107 -388
- package/dist/main.js.map +1 -1
- package/dist/provisioner.d.ts +11 -9
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +125 -87
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/session-runtime.d.ts +27 -0
- package/dist/runtime/session-runtime.d.ts.map +1 -0
- package/dist/runtime/session-runtime.js +303 -0
- package/dist/runtime/session-runtime.js.map +1 -0
- package/dist/sandbox/cloudflare.d.ts +14 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -0
- package/dist/sandbox/cloudflare.js +131 -0
- package/dist/sandbox/cloudflare.js.map +1 -0
- package/dist/sandbox/index.d.ts +6 -4
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +6 -3
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +5 -1
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/session-view/portal.d.ts.map +1 -1
- package/dist/session-view/portal.js +10 -1
- package/dist/session-view/portal.js.map +1 -1
- package/dist/session-view/service.d.ts.map +1 -1
- package/dist/session-view/service.js +36 -26
- package/dist/session-view/service.js.map +1 -1
- package/dist/session-view/store.d.ts +3 -2
- package/dist/session-view/store.d.ts.map +1 -1
- package/dist/session-view/store.js.map +1 -1
- package/dist/vault-routing.d.ts +3 -5
- package/dist/vault-routing.d.ts.map +1 -1
- package/dist/vault-routing.js +8 -20
- package/dist/vault-routing.js.map +1 -1
- package/dist/vault.d.ts +7 -5
- package/dist/vault.d.ts.map +1 -1
- package/dist/vault.js +101 -50
- package/dist/vault.js.map +1 -1
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -3,70 +3,33 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@geminixiang/mama)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
A multi-platform
|
|
6
|
+
A multi-platform AI assistant for Slack, Telegram, and Discord.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
This project is a **forked and extended version** of the `mom` package from [`badlogic/pi-mono`](https://github.com/badlogic/pi-mono) by Mario Zechner, licensed under MIT.
|
|
11
|
-
|
|
12
|
-
- **Original project**: [pi-mom](https://github.com/badlogic/pi-mono/tree/main/packages/mom) (22K+ stars)
|
|
13
|
-
- **Base version**: forked from pi-mom v0.57.1 (synchronized with `@mariozechner/*` packages)
|
|
14
|
-
- **Primary motivation**: Internal services urgently needed a multi-platform bot — this fork enables rapid iteration while preparing changes to contribute back upstream
|
|
15
|
-
|
|
16
|
-
## 🎯 Positioning & Roadmap
|
|
17
|
-
|
|
18
|
-
| Aspect | Description |
|
|
19
|
-
| ------------------ | ------------------------------------------------------------------------------ |
|
|
20
|
-
| **Current Status** | Temporary standalone fork for urgent internal deployment |
|
|
21
|
-
| **Ultimate Goal** | Merge all improvements back into pi-mono monorepo |
|
|
22
|
-
| **Unique Value** | Multi-platform support (Slack + Telegram + Discord) to be contributed upstream |
|
|
23
|
-
|
|
24
|
-
### Why a temporary fork?
|
|
25
|
-
|
|
26
|
-
Our internal services urgently needed a multi-platform bot, and we couldn't wait for upstream release cycles. This fork allows us to:
|
|
27
|
-
|
|
28
|
-
1. **Ship fast**: Deploy to production immediately while internal demand is high
|
|
29
|
-
2. **Iterate freely**: Test multi-platform adapters (Slack, Telegram, Discord) without monorepo constraints
|
|
30
|
-
3. **Contribute back**: All work here is intended to be merged into pi-mono — `mama` is not a replacement for `mom`
|
|
31
|
-
|
|
32
|
-
### Contribution Philosophy 🔄
|
|
33
|
-
|
|
34
|
-
> "This is not a separate product — it's a **temporary fork** for urgent internal needs, and all improvements will be contributed back to pi-mono."
|
|
35
|
-
|
|
36
|
-
We actively track the upstream `pi-mom` and plan to:
|
|
37
|
-
|
|
38
|
-
- ✅ Submit PRs for platform adapters (Telegram, Discord)
|
|
39
|
-
- ✅ Contribute cross-platform abstractions
|
|
40
|
-
- ✅ Keep dependencies synchronized with pi-mono releases
|
|
41
|
-
- ✅ Document what we learn from production use
|
|
42
|
-
|
|
43
|
-
---
|
|
8
|
+
Forked from [`badlogic/pi-mono`](https://github.com/badlogic/pi-mono)'s `mom` package (MIT, by Mario Zechner) at v0.57.1. This fork adds Telegram and Discord adapters and exists to ship internally while we prepare changes to upstream.
|
|
44
9
|
|
|
45
10
|
## Features
|
|
46
11
|
|
|
47
|
-
- **Multi-platform** — Slack, Telegram,
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
55
|
-
- **
|
|
56
|
-
- **Multi-provider** — configure any provider/model supported by `pi-ai`
|
|
12
|
+
- **Multi-platform** — Slack, Telegram, Discord adapters
|
|
13
|
+
- **Concurrent conversations** — Slack threads, Discord replies/threads, and Telegram reply chains run as independent sessions
|
|
14
|
+
- **Sandbox execution** — host, shared container, per-user managed container, Firecracker (alpha), or Cloudflare bridge (experimental)
|
|
15
|
+
- **Credential vaults** — `/login` stores credentials under `--state-dir` and injects env into sandbox runs
|
|
16
|
+
- **Web session viewer** — read-only web view of the current session via `session` / `/session`
|
|
17
|
+
- **Persistent memory** — workspace-level and channel-level `MEMORY.md`
|
|
18
|
+
- **Skills** — drop CLI tools into `skills/`
|
|
19
|
+
- **Events** — schedule one-shot or recurring tasks via JSON files
|
|
20
|
+
- **Multi-provider** — any provider/model supported by `pi-ai`
|
|
57
21
|
|
|
58
22
|
## Platform Session Model
|
|
59
23
|
|
|
60
|
-
| Platform |
|
|
61
|
-
| -------- |
|
|
62
|
-
| Slack |
|
|
63
|
-
| Discord |
|
|
64
|
-
| Telegram | private
|
|
24
|
+
| Platform | `sessionKey` Rule | Notes |
|
|
25
|
+
| -------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
26
|
+
| Slack | top-level / DM: `conversationId`; thread: `conversationId:threadTs` | thread inherits parent context at fork time only; branch changes do not merge back |
|
|
27
|
+
| Discord | DM: `channelId`; shared top-level: `channelId:messageId`; reply/thread: rooted id | replies in shared channels continue the root message session; DM replies do not fork |
|
|
28
|
+
| Telegram | private: `chatId`; shared top-level: `chatId:messageId`; reply chain: root reply | no native thread model; shared sessions are inferred from reply chains |
|
|
65
29
|
|
|
66
30
|
## Requirements
|
|
67
31
|
|
|
68
32
|
- Node.js >= 20
|
|
69
|
-
- One of the platform integrations below
|
|
70
33
|
|
|
71
34
|
## Installation
|
|
72
35
|
|
|
@@ -74,469 +37,240 @@ We actively track the upstream `pi-mom` and plan to:
|
|
|
74
37
|
npm install -g @geminixiang/mama
|
|
75
38
|
```
|
|
76
39
|
|
|
77
|
-
Or
|
|
40
|
+
Or from source:
|
|
78
41
|
|
|
79
42
|
```bash
|
|
80
|
-
npm install
|
|
81
|
-
npm run build
|
|
43
|
+
npm install && npm run build
|
|
82
44
|
```
|
|
83
45
|
|
|
84
|
-
---
|
|
85
|
-
|
|
86
46
|
## Quick Start
|
|
87
47
|
|
|
88
|
-
|
|
48
|
+
All platforms share the same CLI:
|
|
89
49
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- `app_mentions:read`, `channels:history`, `channels:read`, `chat:write`
|
|
93
|
-
- `files:read`, `files:write`, `groups:history`, `groups:read`
|
|
94
|
-
- `im:history`, `im:read`, `im:write`, `users:read`
|
|
95
|
-
- `assistant:write` — required for native "Thinking" status indicator
|
|
96
|
-
3. Enable the **Home Tab** and **Agent mode**:
|
|
97
|
-
- **App Home → Show Tabs** — toggle **Home Tab** on
|
|
98
|
-
- **App Home → Agents & AI Apps** — toggle **Agent or Assistant** on
|
|
99
|
-
4. Subscribe to **Bot Events**:
|
|
100
|
-
- `app_home_opened`, `app_mention`
|
|
101
|
-
- `assistant_thread_context_changed`, `assistant_thread_started`
|
|
102
|
-
- `message.channels`, `message.groups`, `message.im`
|
|
103
|
-
5. Enable **Interactivity** (Settings → Interactivity & Shortcuts → toggle on).
|
|
104
|
-
6. (Optional) Add **Slash Commands** such as `/pi-login` and `/pi-new` in the Slack app settings if you want dedicated commands with less naming conflict. `/pi-new` is intended for DM use only.
|
|
105
|
-
7. Copy the **App-Level Token** (`xapp-…`) and **Bot Token** (`xoxb-…`).
|
|
106
|
-
|
|
107
|
-
Or import this **App Manifest** directly (Settings → App Manifest → paste JSON):
|
|
108
|
-
|
|
109
|
-
<details>
|
|
110
|
-
<summary>Example App Manifest</summary>
|
|
111
|
-
|
|
112
|
-
```json
|
|
113
|
-
{
|
|
114
|
-
"display_information": {
|
|
115
|
-
"name": "mama"
|
|
116
|
-
},
|
|
117
|
-
"features": {
|
|
118
|
-
"app_home": {
|
|
119
|
-
"home_tab_enabled": true,
|
|
120
|
-
"messages_tab_enabled": false,
|
|
121
|
-
"messages_tab_read_only_enabled": false
|
|
122
|
-
},
|
|
123
|
-
"bot_user": {
|
|
124
|
-
"display_name": "mama",
|
|
125
|
-
"always_online": false
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
"oauth_config": {
|
|
129
|
-
"scopes": {
|
|
130
|
-
"bot": [
|
|
131
|
-
"app_mentions:read",
|
|
132
|
-
"assistant:write",
|
|
133
|
-
"channels:history",
|
|
134
|
-
"channels:read",
|
|
135
|
-
"chat:write",
|
|
136
|
-
"files:read",
|
|
137
|
-
"files:write",
|
|
138
|
-
"groups:history",
|
|
139
|
-
"groups:read",
|
|
140
|
-
"im:history",
|
|
141
|
-
"im:read",
|
|
142
|
-
"im:write",
|
|
143
|
-
"users:read"
|
|
144
|
-
]
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
"settings": {
|
|
148
|
-
"event_subscriptions": {
|
|
149
|
-
"bot_events": [
|
|
150
|
-
"app_home_opened",
|
|
151
|
-
"app_mention",
|
|
152
|
-
"assistant_thread_context_changed",
|
|
153
|
-
"assistant_thread_started",
|
|
154
|
-
"message.channels",
|
|
155
|
-
"message.groups",
|
|
156
|
-
"message.im"
|
|
157
|
-
]
|
|
158
|
-
},
|
|
159
|
-
"interactivity": {
|
|
160
|
-
"is_enabled": true
|
|
161
|
-
},
|
|
162
|
-
"org_deploy_enabled": false,
|
|
163
|
-
"socket_mode_enabled": true,
|
|
164
|
-
"token_rotation_enabled": false
|
|
165
|
-
}
|
|
166
|
-
}
|
|
50
|
+
```bash
|
|
51
|
+
mama [--state-dir=~/.mama] [--sandbox=<mode>] <working-directory>
|
|
167
52
|
```
|
|
168
53
|
|
|
169
|
-
|
|
54
|
+
Set the platform tokens you need (you can run multiple platforms at once):
|
|
170
55
|
|
|
171
56
|
```bash
|
|
172
|
-
export
|
|
173
|
-
export
|
|
174
|
-
|
|
175
|
-
|
|
57
|
+
export MAMA_SLACK_APP_TOKEN=xapp-...
|
|
58
|
+
export MAMA_SLACK_BOT_TOKEN=xoxb-...
|
|
59
|
+
export MAMA_TELEGRAM_BOT_TOKEN=123456:ABC-...
|
|
60
|
+
export MAMA_DISCORD_BOT_TOKEN=MTI...
|
|
176
61
|
```
|
|
177
62
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
- **Top-level channel messages** — share one persistent channel session.
|
|
181
|
-
- **Thread replies** — fork from the channel session into an isolated thread session.
|
|
182
|
-
- **DM top-level messages** — share one persistent DM session.
|
|
183
|
-
- **DM thread replies** — fork from the DM session into an isolated thread session.
|
|
184
|
-
- **Thread memory** — inherited at fork time only; thread changes do not merge back into the parent session automatically.
|
|
63
|
+
### Slack
|
|
185
64
|
|
|
186
|
-
|
|
65
|
+
Create a Socket Mode app with the scopes and event subscriptions listed in [docs/slack-bot-minimal-guide.md](docs/slack-bot-minimal-guide.md). The bot responds when `@mentioned` in channels and to all DMs.
|
|
187
66
|
|
|
188
67
|
### Telegram
|
|
189
68
|
|
|
190
|
-
|
|
191
|
-
2. Optionally disable privacy mode (`/setprivacy → Disable`) so the bot can read group messages without being `@mentioned`.
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
export MOM_TELEGRAM_BOT_TOKEN=123456:ABC-...
|
|
195
|
-
|
|
196
|
-
mama [--state-dir=~/.mama] [--sandbox=host|container:<container>|image:<image>|firecracker:<vm-id>:<path>] <working-directory>
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
- **Private chats** — every message is forwarded to the bot automatically.
|
|
200
|
-
- **Group chats** — the bot only responds when `@mentioned` by username.
|
|
201
|
-
- **Private chat session** — one persistent session per DM.
|
|
202
|
-
- **Group top-level mentions** — each mentioned message starts its own scoped session.
|
|
203
|
-
- **Reply chains** — replying to a previous message continues that reply-root session.
|
|
204
|
-
- Say `stop` or `/stop` to cancel a running task.
|
|
205
|
-
|
|
206
|
-
---
|
|
69
|
+
Create a bot via [@BotFather](https://t.me/BotFather) and copy the token. The bot responds to all private messages, and to `@mention` or reply chains in groups. Use `/login`, `/session`, `/new`, and `/stop` for controls.
|
|
207
70
|
|
|
208
71
|
### Discord
|
|
209
72
|
|
|
210
|
-
|
|
211
|
-
2. Under **Bot**, enable **Message Content Intent** (required to read message text).
|
|
212
|
-
3. Under **OAuth2 → URL Generator**, select scopes `bot` + permissions `Send Messages`, `Read Message History`, `Attach Files`. Invite the bot to your server with the generated URL.
|
|
213
|
-
4. Copy the **Bot Token**.
|
|
73
|
+
Create an application in the [Discord Developer Portal](https://discord.com/developers/applications), enable **Message Content Intent**, and invite the bot with `Send Messages`, `Read Message History`, `Attach Files`. The bot responds to `@mentions` in servers and to all DMs.
|
|
214
74
|
|
|
215
|
-
|
|
216
|
-
export MOM_DISCORD_BOT_TOKEN=MTI...
|
|
75
|
+
## Sandbox Modes
|
|
217
76
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
-
|
|
223
|
-
-
|
|
224
|
-
|
|
225
|
-
- **Threads and reply chains** — messages inside the same thread or reply root share a session.
|
|
226
|
-
- Say `stop` or `/stop` to cancel a running task.
|
|
227
|
-
|
|
228
|
-
---
|
|
77
|
+
| Mode | Description |
|
|
78
|
+
| ---------------------------- | ---------------------------------------------------------------------- |
|
|
79
|
+
| `host` (default) | Run on host; no vault env injection |
|
|
80
|
+
| `container:<name>` | Run in an existing shared container; uses vault key `container-<name>` |
|
|
81
|
+
| `image:<image>` | Auto-provision one Docker container per resolved vault/user |
|
|
82
|
+
| `firecracker:<vm-id>:<path>` | Firecracker microVM (alpha; not recommended) |
|
|
83
|
+
| `cloudflare:<sandbox-id>` | Cloudflare Worker bridge (experimental; no auto workspace sync) |
|
|
229
84
|
|
|
230
|
-
|
|
85
|
+
Vault routing: `image`, `firecracker`, and `cloudflare` look up `bindings.json` first, then fall back to the userId vault. See [docs/sandbox.md](docs/sandbox.md) for the full matrix.
|
|
231
86
|
|
|
232
|
-
|
|
233
|
-
| -------------------------------------- | --------- | ------------------------------------------------------------------ |
|
|
234
|
-
| `--state-dir=<dir>` | `~/.mama` | Store settings, credential vaults, and bindings outside workspace |
|
|
235
|
-
| `--sandbox=host` | ✓ | Run commands directly on host; vault env is not injected |
|
|
236
|
-
| `--sandbox=container:<name>` | | Run commands in an existing shared container |
|
|
237
|
-
| `--sandbox=image:<image>` | | Auto-provision one Docker container per platform user |
|
|
238
|
-
| `--sandbox=firecracker:<vm-id>:<path>` | | Experimental Firecracker microVM mode (alpha; not recommended yet) |
|
|
239
|
-
| `--download <channel-id>` | | Download channel history to stdout and exit (Slack only) |
|
|
240
|
-
|
|
241
|
-
### Sandbox and Vault Semantics
|
|
242
|
-
|
|
243
|
-
- `host`: no vault env injection.
|
|
244
|
-
- `container:<name>`: one container maps to one shared vault key: `container-<name>`.
|
|
245
|
-
- `image:<image>`: mama creates one container per resolved vault/user and injects that vault's env and file mounts.
|
|
246
|
-
- `firecracker:*`: per-user vault routing via `bindings.json` first, then direct userId vault. This mode is still alpha and not recommended for normal deployments yet.
|
|
247
|
-
- `docker:*` is not supported; use `container:*` or `image:*`.
|
|
248
|
-
|
|
249
|
-
See [docs/sandbox.md](docs/sandbox.md) for the full sandbox/vault behavior matrix.
|
|
250
|
-
|
|
251
|
-
### Download channel history (Slack)
|
|
87
|
+
### Managed per-user containers (`image:*`)
|
|
252
88
|
|
|
253
89
|
```bash
|
|
254
|
-
|
|
90
|
+
docker pull ghcr.io/geminixiang/mama-sandbox:tools
|
|
91
|
+
mama --sandbox=image:ghcr.io/geminixiang/mama-sandbox:tools /path/to/workspace
|
|
255
92
|
```
|
|
256
93
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
For normal deployments, set `MOM_LINK_URL` to the externally reachable base URL of the web credential onboarding flow:
|
|
94
|
+
Or build locally:
|
|
260
95
|
|
|
261
96
|
```bash
|
|
262
|
-
|
|
263
|
-
# optional; defaults to 8181 when MOM_LINK_URL is set
|
|
264
|
-
export MOM_LINK_PORT=8181
|
|
97
|
+
docker build -f docker/mama-sandbox.Dockerfile -t mama-sandbox:tools .
|
|
265
98
|
```
|
|
266
99
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Users can then run `/login` in a private conversation with the bot. mama returns a 15-minute link for storing API keys or using built-in OAuth providers. `/login` is rejected in shared channels to avoid leaking onboarding links.
|
|
270
|
-
|
|
271
|
-
On Slack, you can also register native slash commands such as `/pi-login` and `/pi-new`.
|
|
272
|
-
|
|
273
|
-
- `/pi-login` in a shared channel opens a DM and continues the credential flow there.
|
|
274
|
-
- `/pi-new` only works in a Slack DM and resets that DM session context.
|
|
100
|
+
mama creates one container per vault, attaches each to its own bridge network, mounts the workspace at `/workspace`, injects vault env, mounts declared credential files, and stops idle containers.
|
|
275
101
|
|
|
276
|
-
|
|
102
|
+
### Firecracker / Cloudflare
|
|
277
103
|
|
|
278
|
-
|
|
104
|
+
See [docs/firecracker-setup.md](docs/firecracker-setup.md) and [examples/cloudflare-sandbox-bridge/README.md](examples/cloudflare-sandbox-bridge/README.md).
|
|
279
105
|
|
|
280
|
-
|
|
281
|
-
- mama returns an expiring read-only link to `/session?token=...`.
|
|
282
|
-
- The page shows the current branch timeline, including user messages, assistant replies, tool results, and compaction / branch summary events.
|
|
283
|
-
- For now, session links are only issued from private conversations to avoid leaking shared-channel history.
|
|
106
|
+
## `/login` and Web Session Viewer
|
|
284
107
|
|
|
285
|
-
|
|
108
|
+
```bash
|
|
109
|
+
export MAMA_LINK_URL="https://mama.example.com" # public base URL
|
|
110
|
+
export MAMA_LINK_PORT=8181 # optional, defaults to 8181
|
|
111
|
+
```
|
|
286
112
|
|
|
287
|
-
|
|
113
|
+
For local testing you can set just `MAMA_LINK_PORT`; mama will use `http://localhost:<port>`.
|
|
288
114
|
|
|
289
|
-
- [GitHub
|
|
290
|
-
-
|
|
115
|
+
- `/login` (DM only) returns a 15-minute link to store API keys or run built-in OAuth flows ([GitHub](docs/oauth/github.md), [Google Workspace](docs/oauth/google-workspace.md)).
|
|
116
|
+
- `session` / `/session` (DM only) returns a read-only link showing the current session timeline.
|
|
117
|
+
- `new` / `/new` (DM only) resets the current session and starts fresh.
|
|
118
|
+
- `model` / `/model` / `/pi-model provider/model[:thinking]` switches the LLM for the current conversation, e.g. `/pi-model anthropic/claude-sonnet-4-5:off`.
|
|
119
|
+
- `stop` / `/stop` stops the current run. On Slack, use text commands so thread-local stop routing remains accurate.
|
|
120
|
+
- On Slack you can also register native commands like `/pi-login`, `/pi-session`, `/pi-model`, and `/pi-new`.
|
|
291
121
|
|
|
292
|
-
Credentials are stored under `<state-dir>/vaults` (default `~/.mama/vaults`).
|
|
122
|
+
Credentials are stored under `<state-dir>/vaults` (default `~/.mama/vaults`). Vault env is only injected in `container`, `image`, `firecracker`, and `cloudflare` modes.
|
|
293
123
|
|
|
294
124
|
## Configuration
|
|
295
125
|
|
|
296
|
-
mama
|
|
126
|
+
mama reads global settings from `<state-dir>/settings.json` (default `~/.mama/settings.json`, override via `--state-dir` or `MAMA_STATE_DIR`). This file is required and is created explicitly with `mama --onboard`. Per-conversation settings live at `<workingDir>/<conversationId>/settings.json` and override global settings for that conversation.
|
|
297
127
|
|
|
298
128
|
```json
|
|
299
129
|
{
|
|
300
|
-
"
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
"
|
|
306
|
-
|
|
130
|
+
"llm": {
|
|
131
|
+
"provider": "anthropic",
|
|
132
|
+
"model": "claude-sonnet-4-5",
|
|
133
|
+
"thinkingLevel": "off"
|
|
134
|
+
},
|
|
135
|
+
"log": {
|
|
136
|
+
"format": "console",
|
|
137
|
+
"level": "info"
|
|
138
|
+
},
|
|
139
|
+
"sentry": {
|
|
140
|
+
"dsn": "https://examplePublicKey@o0.ingest.sentry.io/0"
|
|
141
|
+
},
|
|
142
|
+
"sandbox": {
|
|
143
|
+
"cpus": "0.5",
|
|
144
|
+
"memory": "512m"
|
|
145
|
+
}
|
|
307
146
|
}
|
|
308
147
|
```
|
|
309
148
|
|
|
310
|
-
| Field
|
|
311
|
-
|
|
|
312
|
-
| `provider` | `anthropic` | AI provider
|
|
313
|
-
| `model` | `claude-sonnet-4-5` | Model name
|
|
314
|
-
| `thinkingLevel` | `off` | `off` / `low` / `medium` / `high`
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
319
|
-
|
|
320
|
-
When `sentryDsn` is set, mama sends Sentry events with sensitive prompt/tool content redacted before upload.
|
|
321
|
-
|
|
322
|
-
### GCP Cloud Logging (Compute Engine)
|
|
323
|
-
|
|
324
|
-
Set `logFormat: "json"` to send structured logs directly to Cloud Logging via API — no Ops Agent or log file configuration needed.
|
|
325
|
-
|
|
326
|
-
**Requirements:**
|
|
327
|
-
|
|
328
|
-
1. VM service account has `roles/logging.logWriter`
|
|
329
|
-
2. `GOOGLE_CLOUD_PROJECT` env var is set
|
|
330
|
-
|
|
331
|
-
```bash
|
|
332
|
-
GOOGLE_CLOUD_PROJECT=<your-project-id> mama <working-directory>
|
|
333
|
-
```
|
|
149
|
+
| Field | Default | Description |
|
|
150
|
+
| ------------------- | ------------------- | -------------------------------------------------------- |
|
|
151
|
+
| `llm.provider` | `anthropic` | AI provider |
|
|
152
|
+
| `llm.model` | `claude-sonnet-4-5` | Model name |
|
|
153
|
+
| `llm.thinkingLevel` | `off` | `off` / `low` / `medium` / `high` |
|
|
154
|
+
| `log.format` | `console` | `console` (colored stdout) or `json` (GCP Cloud Logging) |
|
|
155
|
+
| `log.level` | `info` | `trace` / `debug` / `info` / `warn` / `error` |
|
|
156
|
+
| `sentry.dsn` | unset | Sentry DSN; sensitive prompt/tool content is redacted |
|
|
157
|
+
| `sandbox.cpus` | unset | CPU limit for managed containers |
|
|
158
|
+
| `sandbox.memory` | unset | Memory limit for managed containers |
|
|
334
159
|
|
|
335
|
-
|
|
160
|
+
Conversation-local settings written by `/pi-model` use the same shape and usually only include the override:
|
|
336
161
|
|
|
337
162
|
```json
|
|
338
163
|
{
|
|
339
|
-
"
|
|
340
|
-
|
|
164
|
+
"llm": {
|
|
165
|
+
"provider": "anthropic",
|
|
166
|
+
"model": "claude-sonnet-4-5",
|
|
167
|
+
"thinkingLevel": "off"
|
|
168
|
+
}
|
|
341
169
|
}
|
|
342
170
|
```
|
|
343
171
|
|
|
344
|
-
|
|
172
|
+
For GCP Cloud Logging, set `log.format: "json"`, give the VM service account `roles/logging.logWriter`, and export `GOOGLE_CLOUD_PROJECT`. Logs land under log name `mama`.
|
|
345
173
|
|
|
346
|
-
##
|
|
174
|
+
## Layout
|
|
347
175
|
|
|
348
176
|
```
|
|
349
177
|
<state-dir>/
|
|
350
|
-
├── settings.json
|
|
178
|
+
├── settings.json
|
|
351
179
|
└── vaults/
|
|
352
|
-
├── bindings.json
|
|
353
|
-
├── vault.json
|
|
180
|
+
├── bindings.json # platform user -> vault mapping
|
|
181
|
+
├── vault.json
|
|
354
182
|
└── <vault-id>/
|
|
355
|
-
├── env
|
|
356
|
-
└── ...
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
## Working Directory Layout
|
|
183
|
+
├── env
|
|
184
|
+
└── ... # credential files
|
|
360
185
|
|
|
361
|
-
```
|
|
362
186
|
<working-directory>/
|
|
363
|
-
├──
|
|
364
|
-
├──
|
|
365
|
-
├──
|
|
366
|
-
├──
|
|
367
|
-
├── events/ # Scheduled event files
|
|
187
|
+
├── MEMORY.md # global memory
|
|
188
|
+
├── SYSTEM.md # installed packages / env log
|
|
189
|
+
├── skills/ # global skills
|
|
190
|
+
├── events/ # scheduled events
|
|
368
191
|
└── <conversation-id>/
|
|
369
|
-
├── MEMORY.md
|
|
370
|
-
├── log.jsonl
|
|
371
|
-
├── attachments/
|
|
372
|
-
├── scratch/
|
|
373
|
-
├── skills/
|
|
192
|
+
├── MEMORY.md
|
|
193
|
+
├── log.jsonl
|
|
194
|
+
├── attachments/
|
|
195
|
+
├── scratch/
|
|
196
|
+
├── skills/
|
|
374
197
|
└── sessions/
|
|
375
|
-
├── current # Pointer for the persistent top-level / direct session
|
|
376
|
-
├── 2026-04-05T18-04-31-010Z_1d92b3ad.jsonl
|
|
377
|
-
└── <session-suffix>.jsonl # Fixed-path scoped session (thread / reply root)
|
|
378
198
|
```
|
|
379
199
|
|
|
380
|
-
##
|
|
381
|
-
|
|
382
|
-
```bash
|
|
383
|
-
# Create a container (mount your working directory to /workspace)
|
|
384
|
-
docker run -d --name mama-tools \
|
|
385
|
-
-v /path/to/workspace:/workspace \
|
|
386
|
-
alpine:latest sleep infinity
|
|
387
|
-
|
|
388
|
-
# Start mama with container sandbox
|
|
389
|
-
mama --sandbox=container:mama-tools /path/to/workspace
|
|
390
|
-
```
|
|
200
|
+
## Events
|
|
391
201
|
|
|
392
|
-
|
|
202
|
+
Drop JSON files into `<working-directory>/events/`:
|
|
393
203
|
|
|
394
|
-
|
|
204
|
+
```json
|
|
205
|
+
// Immediate
|
|
206
|
+
{"type": "immediate", "platform": "slack", "conversationId": "C0123456789", "conversationKind": "shared", "text": "Deploy finished"}
|
|
395
207
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
# Release builds publish :tools, :<version>, and :latest / :beta
|
|
399
|
-
# Pushes to main also publish :edge
|
|
400
|
-
docker pull ghcr.io/geminixiang/mama-sandbox:tools
|
|
208
|
+
// One-shot
|
|
209
|
+
{"type": "one-shot", "platform": "telegram", "conversationId": "574247312", "conversationKind": "direct", "text": "Standup", "at": "2025-12-15T09:00:00+08:00"}
|
|
401
210
|
|
|
402
|
-
|
|
403
|
-
|
|
211
|
+
// Periodic (cron)
|
|
212
|
+
{"type": "periodic", "platform": "discord", "conversationId": "1498975469343739948", "conversationKind": "shared", "text": "Check inbox", "schedule": "0 9 * * 1-5", "timezone": "Asia/Taipei"}
|
|
404
213
|
```
|
|
405
214
|
|
|
406
|
-
|
|
215
|
+
## Skills
|
|
407
216
|
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
|
|
217
|
+
```
|
|
218
|
+
skills/my-tool/
|
|
219
|
+
├── SKILL.md # name + description frontmatter, usage docs
|
|
220
|
+
└── run.sh
|
|
411
221
|
```
|
|
412
222
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
Firecracker provides lightweight VM isolation with the security benefits of a hypervisor. Unlike Docker containers, Firecracker runs a full Linux kernel, providing stronger isolation.
|
|
420
|
-
|
|
421
|
-
### Requirements
|
|
422
|
-
|
|
423
|
-
- SSH access to the Firecracker VM
|
|
424
|
-
- SSH key-based authentication configured
|
|
425
|
-
- Host workspace must be mounted at `/workspace` inside the VM
|
|
426
|
-
|
|
427
|
-
### Format
|
|
223
|
+
```yaml
|
|
224
|
+
---
|
|
225
|
+
name: my-tool
|
|
226
|
+
description: Does something useful
|
|
227
|
+
---
|
|
428
228
|
|
|
429
|
-
|
|
430
|
-
--sandbox=firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]
|
|
229
|
+
Usage: {baseDir}/run.sh <args>
|
|
431
230
|
```
|
|
432
231
|
|
|
433
|
-
|
|
434
|
-
| ----------- | ------- | ------------------------------ |
|
|
435
|
-
| `vm-id` | - | VM identifier (hostname or IP) |
|
|
436
|
-
| `host-path` | - | Working directory on the host |
|
|
437
|
-
| `ssh-user` | `root` | SSH username |
|
|
438
|
-
| `ssh-port` | `22` | SSH port |
|
|
439
|
-
|
|
440
|
-
### Examples
|
|
232
|
+
## Slack: Download channel history
|
|
441
233
|
|
|
442
234
|
```bash
|
|
443
|
-
|
|
444
|
-
mama --sandbox=firecracker:192.168.1.100:/home/user/workspace /home/user/workspace
|
|
445
|
-
|
|
446
|
-
# Custom SSH user
|
|
447
|
-
mama --sandbox=firecracker:192.168.1.100:/home/user/workspace:ubuntu /home/user/workspace
|
|
448
|
-
|
|
449
|
-
# Custom SSH port
|
|
450
|
-
mama --sandbox=firecracker:192.168.1.100:/home/user/workspace:root:2222 /home/user/workspace
|
|
235
|
+
mama --download C0123456789
|
|
451
236
|
```
|
|
452
237
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
1. **Start a Firecracker VM** with your preferred method (fc-agent, firecracker-ctl, or manual)
|
|
456
|
-
|
|
457
|
-
2. **Configure SSH access** inside the VM:
|
|
458
|
-
|
|
459
|
-
```bash
|
|
460
|
-
# Inside the VM - allow password-less SSH for mama
|
|
461
|
-
sudo systemctl enable ssh
|
|
462
|
-
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
|
|
463
|
-
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
|
464
|
-
sudo systemctl restart ssh
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
3. **Mount your workspace** at `/workspace` inside the VM:
|
|
468
|
-
|
|
469
|
-
```bash
|
|
470
|
-
# Option A: 9pfs (recommended, from host)
|
|
471
|
-
sudo mount -t 9p -o trans=virtio,version=9p2000.L host0 /workspace
|
|
238
|
+
## Production deployment (PM2)
|
|
472
239
|
|
|
473
|
-
|
|
474
|
-
sudo mount -t nfs <host-ip>:/path/to/workspace /workspace
|
|
475
|
-
```
|
|
240
|
+
For long-running deployments, use [PM2](https://pm2.keymetrics.io/) as a process supervisor. It daemonizes mama, restarts on crash, and survives reboots.
|
|
476
241
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
The host path is mounted as `/workspace` inside the Firecracker VM. All bash commands will execute inside the VM.
|
|
483
|
-
|
|
484
|
-
## Events
|
|
485
|
-
|
|
486
|
-
Drop JSON files into `<working-directory>/events/` to trigger the agent:
|
|
487
|
-
|
|
488
|
-
```json
|
|
489
|
-
// Immediate — triggers as soon as mama sees the file
|
|
490
|
-
{"type": "immediate", "platform": "slack", "conversationId": "C0123456789", "conversationKind": "shared", "text": "New deployment finished"}
|
|
242
|
+
```bash
|
|
243
|
+
# 1. Install mama and pm2
|
|
244
|
+
npm i -g @geminixiang/mama pm2
|
|
491
245
|
|
|
492
|
-
|
|
493
|
-
|
|
246
|
+
# 2. Start the sandbox container (long-lived; mama execs into it)
|
|
247
|
+
docker pull ghcr.io/geminixiang/mama-sandbox:latest
|
|
494
248
|
|
|
495
|
-
|
|
496
|
-
|
|
249
|
+
# 3. Grab the ecosystem file, edit args + env tokens, then start
|
|
250
|
+
curl -O https://raw.githubusercontent.com/geminixiang/mama/main/deploy/pm2/ecosystem.config.cjs
|
|
251
|
+
pm2 start ecosystem.config.cjs
|
|
252
|
+
pm2 save
|
|
253
|
+
pm2 startup # run the printed command to enable boot autostart
|
|
497
254
|
```
|
|
498
255
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
Create reusable CLI tools by adding a directory with a `SKILL.md`:
|
|
256
|
+
Upgrade flow:
|
|
502
257
|
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
└── my-tool/
|
|
506
|
-
├── SKILL.md # name + description frontmatter, usage docs
|
|
507
|
-
└── run.sh # the actual script
|
|
258
|
+
```bash
|
|
259
|
+
npm i -g @geminixiang/mama && pm2 reload mama
|
|
508
260
|
```
|
|
509
261
|
|
|
510
|
-
`
|
|
511
|
-
|
|
512
|
-
```yaml
|
|
513
|
-
---
|
|
514
|
-
name: my-tool
|
|
515
|
-
description: Does something useful
|
|
516
|
-
---
|
|
262
|
+
`pm2 reload` sends SIGTERM and waits up to `kill_timeout` (60s in the shipped config) before SIGKILL. mama's internal graceful shutdown drains in-flight LLM turns within that window, so reloads do not interrupt active conversations.
|
|
517
263
|
|
|
518
|
-
|
|
519
|
-
```
|
|
264
|
+
See [`deploy/pm2/ecosystem.config.cjs`](deploy/pm2/ecosystem.config.cjs) for all tunables.
|
|
520
265
|
|
|
521
266
|
## Development
|
|
522
267
|
|
|
523
268
|
```bash
|
|
524
269
|
npm run dev # watch mode
|
|
525
|
-
npm test
|
|
526
|
-
npm run build
|
|
270
|
+
npm test
|
|
271
|
+
npm run build
|
|
527
272
|
```
|
|
528
273
|
|
|
529
|
-
## 📦 Dependencies & Versions
|
|
530
|
-
|
|
531
|
-
| Package | mama Version | pi-mom Synced Version |
|
|
532
|
-
| ------------------------------- | ------------ | -------------------------------- |
|
|
533
|
-
| `@mariozechner/pi-agent-core` | `^0.69.0` | ✅ Synchronized |
|
|
534
|
-
| `@mariozechner/pi-ai` | `^0.69.0` | ✅ Synchronized |
|
|
535
|
-
| `@mariozechner/pi-coding-agent` | `^0.69.0` | ✅ Synchronized |
|
|
536
|
-
| `@anthropic-ai/sandbox-runtime` | `^0.0.49` | ⚠️ Newer than original fork base |
|
|
537
|
-
|
|
538
274
|
## License
|
|
539
275
|
|
|
540
|
-
MIT — see [LICENSE](LICENSE).
|
|
541
|
-
|
|
542
|
-
**Note**: This project inherits the MIT license from pi-mom and aims to keep its contributions compatible with the upstream ecosystem.
|
|
276
|
+
MIT — see [LICENSE](LICENSE). Inherits from pi-mom.
|