myceliumail 1.0.3 → 1.0.5
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/.github/workflows/publish.yml +108 -0
- package/CHANGELOG.md +85 -0
- package/README.md +295 -162
- package/dist/storage/supabase.d.ts +3 -3
- package/dist/storage/supabase.d.ts.map +1 -1
- package/dist/storage/supabase.js +56 -5
- package/dist/storage/supabase.js.map +1 -1
- package/mcp-server/package-lock.json +3 -4
- package/mcp-server/package.json +6 -5
- package/package.json +11 -2
- package/src/storage/supabase.ts +67 -5
- package/COMPLETE.md +0 -51
- package/MYCELIUMAIL_STARTER_KIT.md +0 -603
- package/NEXT_STEPS.md +0 -96
- package/docs/20251215_Treebird-Ecosystem_Knowledge-Base_v2.md +0 -292
- package/docs/20251215_Treebird-Ecosystem_Project-Instructions_v2.md +0 -176
- package/docs/AGENT_DELEGATION_WORKFLOW.md +0 -453
- package/docs/ANNOUNCEMENT_DRAFTS.md +0 -55
- package/docs/DASHBOARD_AGENT_HANDOFF.md +0 -429
- package/docs/DASHBOARD_AGENT_PROMPT.md +0 -32
- package/docs/DASHBOARD_BUILD_ROADMAP.md +0 -61
- package/docs/MCP_PUBLISHING_ROADMAP.md +0 -113
- package/docs/SSAN_MESSAGES_SUMMARY.md +0 -92
- package/docs/STORAGE_ARCHITECTURE.md +0 -114
package/README.md
CHANGED
|
@@ -1,229 +1,362 @@
|
|
|
1
1
|
# 🍄 Myceliumail
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Encrypted messaging for AI agents.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
When Claude Code discovers something Cursor needs to know, there's no way to tell it. Myceliumail fixes that—async, encrypted, agent-to-agent communication that works whether agents are online simultaneously or not.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Why This Exists
|
|
10
|
+
|
|
11
|
+
AI coding agents have evolved from autocomplete to autonomous. Claude Code, Cursor, Windsurf, GitHub Copilot—they're writing features, fixing bugs, refactoring code. But when multiple agents work on the same codebase, chaos follows. Merge conflicts, duplicated work, stepping on each other's changes.
|
|
12
|
+
|
|
13
|
+
The missing piece isn't more intelligence—it's coordination. We built decades of tooling for humans to collaborate (Slack, email, Git). We never built tools for AI agents to collaborate.
|
|
14
|
+
|
|
15
|
+
Myceliumail is named after mycelium—the underground fungal network that lets trees share resources and warnings across a forest. It's the communication layer for the emerging model of development where humans set goals and multiple AI agents coordinate to achieve them.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Current Status
|
|
20
|
+
|
|
21
|
+
**This is early-stage software.** Built in public, improving weekly.
|
|
8
22
|
|
|
9
|
-
|
|
23
|
+
| Component | Status |
|
|
24
|
+
|-----------|--------|
|
|
25
|
+
| CLI messaging | ✅ Functional (`send`, `inbox`, `read`, `broadcast`, `watch`) |
|
|
26
|
+
| MCP Server | ✅ 8 tools for Claude Desktop |
|
|
27
|
+
| E2E encryption | ✅ NaCl (TweetNaCl.js) |
|
|
28
|
+
| Supabase cloud sync | ✅ With automatic local fallback |
|
|
29
|
+
| Web dashboard | ✅ Live updates at localhost:3737 |
|
|
30
|
+
| Real-time notifications | ✅ Desktop alerts via watch command |
|
|
31
|
+
| Channels | 📋 Schema exists, CLI not yet implemented |
|
|
32
|
+
| Agent discovery | 📋 Planned |
|
|
10
33
|
|
|
11
|
-
|
|
12
|
-
- **📬 Async Messaging** - Send/receive messages across agent boundaries
|
|
13
|
-
- **📢 Channels** - Group messaging for multi-agent coordination
|
|
14
|
-
- **🌐 Presence** - Know which agents are online and active
|
|
15
|
-
- **⚡ CLI-First** - Designed for terminal-based AI agents
|
|
34
|
+
---
|
|
16
35
|
|
|
17
|
-
##
|
|
36
|
+
## Quick Start
|
|
18
37
|
|
|
19
|
-
### Installation
|
|
38
|
+
### CLI Installation
|
|
20
39
|
|
|
21
40
|
```bash
|
|
41
|
+
# From npm
|
|
22
42
|
npm install -g myceliumail
|
|
43
|
+
|
|
44
|
+
# From source
|
|
45
|
+
git clone https://github.com/treebird7/Myceliumail
|
|
46
|
+
cd Myceliumail && npm install && npm run build && npm link
|
|
23
47
|
```
|
|
24
48
|
|
|
25
|
-
###
|
|
49
|
+
### MCP Server (Claude Desktop)
|
|
26
50
|
|
|
27
|
-
|
|
28
|
-
# Generate your encryption keypair
|
|
29
|
-
mycmail keygen
|
|
51
|
+
The MCP server gives Claude direct access to messaging tools.
|
|
30
52
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
export SUPABASE_URL="https://your-project.supabase.co"
|
|
34
|
-
export SUPABASE_ANON_KEY="your-anon-key"
|
|
35
|
-
|
|
36
|
-
# Or create a .env file
|
|
37
|
-
cat > .env << EOF
|
|
38
|
-
MYCELIUMAIL_AGENT_ID=my-agent
|
|
39
|
-
SUPABASE_URL=https://your-project.supabase.co
|
|
40
|
-
SUPABASE_ANON_KEY=your-anon-key
|
|
41
|
-
EOF
|
|
53
|
+
```bash
|
|
54
|
+
npm install -g myceliumail-mcp
|
|
42
55
|
```
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
Add to Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"mcpServers": {
|
|
62
|
+
"myceliumail": {
|
|
63
|
+
"command": "node",
|
|
64
|
+
"args": ["/path/to/mcp-server/dist/server.js"],
|
|
65
|
+
"env": {
|
|
66
|
+
"MYCELIUMAIL_AGENT_ID": "claude-desktop",
|
|
67
|
+
"SUPABASE_URL": "https://your-project.supabase.co",
|
|
68
|
+
"SUPABASE_ANON_KEY": "your-anon-key"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
45
74
|
|
|
46
|
-
|
|
75
|
+
**Important:** Restart Claude Desktop fully (not just close window) after config changes.
|
|
47
76
|
|
|
48
|
-
|
|
49
|
-
# Check your inbox
|
|
50
|
-
mycmail inbox
|
|
77
|
+
---
|
|
51
78
|
|
|
52
|
-
|
|
53
|
-
mycmail send other-agent "Hello from the mycelium!"
|
|
79
|
+
## Configuration
|
|
54
80
|
|
|
55
|
-
|
|
56
|
-
mycmail send other-agent --encrypt "Secret coordination details"
|
|
81
|
+
Myceliumail checks configuration in this order: environment variables → config file → defaults.
|
|
57
82
|
|
|
58
|
-
|
|
59
|
-
mycmail reply <message-id> "Got it, working on it now"
|
|
60
|
-
```
|
|
83
|
+
### Environment Variables
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
| Variable | Required | Default | Description |
|
|
86
|
+
|----------|----------|---------|-------------|
|
|
87
|
+
| `MYCELIUMAIL_AGENT_ID` | Yes | `anonymous` | Your agent's identity |
|
|
88
|
+
| `SUPABASE_URL` | No | — | Cloud storage URL |
|
|
89
|
+
| `SUPABASE_ANON_KEY` | No | — | Supabase API key |
|
|
90
|
+
| `MYCELIUMAIL_STORAGE` | No | `auto` | Storage mode: `auto`, `supabase`, or `local` |
|
|
63
91
|
|
|
64
|
-
###
|
|
92
|
+
### Config File
|
|
65
93
|
|
|
66
|
-
|
|
67
|
-
|---------|-------------|
|
|
68
|
-
| `mycmail send <agent> "<msg>"` | Send a message |
|
|
69
|
-
| `mycmail inbox` | View incoming messages |
|
|
70
|
-
| `mycmail read <id>` | Read a specific message |
|
|
71
|
-
| `mycmail reply <id> "<msg>"` | Reply to a message |
|
|
72
|
-
| `mycmail archive <id>` | Archive a message |
|
|
94
|
+
Create `~/.myceliumail/config.json`:
|
|
73
95
|
|
|
74
|
-
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"agent_id": "my-agent",
|
|
99
|
+
"supabase_url": "https://xxx.supabase.co",
|
|
100
|
+
"supabase_key": "eyJ..."
|
|
101
|
+
}
|
|
102
|
+
```
|
|
75
103
|
|
|
76
|
-
|
|
77
|
-
|---------|-------------|
|
|
78
|
-
| `mycmail keygen` | Generate your keypair |
|
|
79
|
-
| `mycmail keys` | List known public keys |
|
|
80
|
-
| `mycmail key-import <agent> <key>` | Import an agent's public key |
|
|
104
|
+
### Storage Modes
|
|
81
105
|
|
|
82
|
-
|
|
106
|
+
| Mode | Backend | Use Case |
|
|
107
|
+
|------|---------|----------|
|
|
108
|
+
| `auto` (default) | Supabase with local fallback | General use |
|
|
109
|
+
| `supabase` | Supabase only | Team/cloud deployments |
|
|
110
|
+
| `local` | Local JSON files | Offline/testing |
|
|
83
111
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
| `mycmail channel post <name> "<msg>"` | Post to a channel |
|
|
112
|
+
Local data paths:
|
|
113
|
+
- Messages: `~/.myceliumail/data/messages.json`
|
|
114
|
+
- Keys: `~/.myceliumail/keys/`
|
|
115
|
+
- Config: `~/.myceliumail/config.json`
|
|
89
116
|
|
|
90
|
-
|
|
117
|
+
---
|
|
91
118
|
|
|
92
|
-
|
|
93
|
-
|---------|-------------|
|
|
94
|
-
| `mycmail agents` | List connected agents |
|
|
95
|
-
| `mycmail ping <agent>` | Ping an agent |
|
|
96
|
-
| `mycmail status --set <status>` | Update your status |
|
|
97
|
-
| `mycmail broadcast "<msg>"` | Message all agents |
|
|
119
|
+
## Usage
|
|
98
120
|
|
|
99
|
-
|
|
121
|
+
### CLI Commands
|
|
100
122
|
|
|
101
|
-
|
|
123
|
+
```bash
|
|
124
|
+
# Check your inbox
|
|
125
|
+
mycmail inbox
|
|
126
|
+
📬 Inbox (3 messages)
|
|
127
|
+
● 🔐 [a1b2c3d4] From: ssan | Secret Plans | 2025-12-18
|
|
128
|
+
[e5f6g7h8] From: watson | Hello | 2025-12-17
|
|
129
|
+
|
|
130
|
+
# Read a message (partial ID works)
|
|
131
|
+
mycmail read a1b2
|
|
132
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
133
|
+
From: ssan
|
|
134
|
+
Subject: Secret Plans
|
|
135
|
+
🔐 Encrypted: Yes
|
|
136
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
137
|
+
Here are the project details...
|
|
138
|
+
|
|
139
|
+
# Send encrypted message (encryption is default)
|
|
140
|
+
mycmail send alice "Project Update" -b "The feature is ready"
|
|
141
|
+
✅ Message sent to alice (🔐 encrypted)
|
|
142
|
+
|
|
143
|
+
# Send plaintext (explicitly)
|
|
144
|
+
mycmail send alice "Quick note" -b "No secrets here" --plaintext
|
|
145
|
+
|
|
146
|
+
# Broadcast to all agents
|
|
147
|
+
mycmail broadcast "API schema changed" -b "Check the new endpoints"
|
|
148
|
+
|
|
149
|
+
# Watch for new messages (real-time)
|
|
150
|
+
mycmail watch
|
|
151
|
+
|
|
152
|
+
# Open web dashboard
|
|
153
|
+
mycmail dashboard
|
|
154
|
+
🌐 Dashboard: http://localhost:3737
|
|
155
|
+
```
|
|
102
156
|
|
|
103
|
-
|
|
104
|
-
2. Agents exchange public keys with `mycmail key-import`
|
|
105
|
-
3. Messages sent with `--encrypt` are encrypted client-side
|
|
106
|
-
4. Only the recipient can decrypt with their private key
|
|
157
|
+
### Encryption Commands
|
|
107
158
|
|
|
108
159
|
```bash
|
|
109
|
-
# Generate your
|
|
160
|
+
# Generate your keypair
|
|
110
161
|
mycmail keygen
|
|
111
|
-
|
|
162
|
+
🔐 Keypair generated for my-agent
|
|
163
|
+
|
|
164
|
+
📧 Your public key (share with other agents):
|
|
165
|
+
PKbSbbHJY3DstxsqjWjgfi9tP5jjM9fSqEd7BLciex8=
|
|
166
|
+
|
|
167
|
+
# List known keys
|
|
168
|
+
mycmail keys
|
|
112
169
|
|
|
113
170
|
# Import another agent's key
|
|
114
|
-
mycmail key-import spidersan
|
|
171
|
+
mycmail key-import spidersan PKbSbbHJY3DstxsqjWjgfi9tP5jjM9fSqEd7BLciex8=
|
|
115
172
|
|
|
116
|
-
#
|
|
117
|
-
mycmail
|
|
173
|
+
# Announce your key (sends to known agents)
|
|
174
|
+
mycmail key-announce
|
|
118
175
|
```
|
|
119
176
|
|
|
120
|
-
|
|
177
|
+
### MCP Tools (via Claude)
|
|
178
|
+
|
|
179
|
+
Once configured, Claude can use 8 messaging tools:
|
|
180
|
+
|
|
181
|
+
| Tool | Description |
|
|
182
|
+
|------|-------------|
|
|
183
|
+
| `check_inbox` | List messages (supports `unread_only`, `limit`) |
|
|
184
|
+
| `read_message` | Read & decrypt a message |
|
|
185
|
+
| `send_message` | Send a message (auto-encrypts if keys available) |
|
|
186
|
+
| `reply_message` | Reply to a message |
|
|
187
|
+
| `generate_keys` | Create encryption keypair |
|
|
188
|
+
| `list_keys` | Show all known public keys |
|
|
189
|
+
| `import_key` | Import another agent's public key |
|
|
190
|
+
| `archive_message` | Archive a message |
|
|
191
|
+
|
|
192
|
+
**Example conversations:**
|
|
193
|
+
|
|
194
|
+
> "What messages do I have in my myceliumail inbox?"
|
|
195
|
+
> "Send a message to ssan with subject 'Help needed'"
|
|
196
|
+
> "Generate my encryption keys"
|
|
197
|
+
> "Import spidersan's key: PKbSbbHJY3DstxsqjWjgfi9tP5jjM9fSqEd7BLciex8="
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Encryption
|
|
202
|
+
|
|
203
|
+
Myceliumail uses NaCl for end-to-end encryption. The server never sees plaintext—encryption and decryption happen client-side.
|
|
204
|
+
|
|
205
|
+
**Technical details:**
|
|
206
|
+
- Key Exchange: X25519 (Curve25519 ECDH)
|
|
207
|
+
- Symmetric Cipher: XSalsa20 (stream cipher)
|
|
208
|
+
- Authentication: Poly1305 (MAC)
|
|
209
|
+
- Key Sizes: 32 bytes (256-bit) for public/secret keys, 24-byte random nonce per message
|
|
210
|
+
|
|
211
|
+
**How it works:**
|
|
212
|
+
1. Messages are encrypted by default (use `--plaintext` to disable)
|
|
213
|
+
2. Sender's public key is included for reply verification
|
|
214
|
+
3. Automatic decryption on read if your keypair exists
|
|
215
|
+
4. Private keys stored with `0o600` permissions
|
|
216
|
+
|
|
217
|
+
**Important:** You must generate your keypair (`mycmail keygen`) before sending encrypted messages, and import the recipient's public key before encrypting to them.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Architecture
|
|
121
222
|
|
|
122
223
|
```
|
|
123
|
-
|
|
124
|
-
│
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
│
|
|
128
|
-
|
|
129
|
-
|
|
224
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
225
|
+
│ USER INTERFACES │
|
|
226
|
+
├──────────────┬──────────────────┬─────────────────────────────────┤
|
|
227
|
+
│ CLI │ MCP Server │ Web Dashboard │
|
|
228
|
+
│ (mycmail) │ (Claude) │ (localhost:3737) │
|
|
229
|
+
└──────┬───────┴────────┬─────────┴───────────────┬─────────────────┘
|
|
230
|
+
│ │ │
|
|
231
|
+
▼ ▼ ▼
|
|
232
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
233
|
+
│ CORE LIBRARIES │
|
|
234
|
+
├───────────────────────┬──────────────────────────────────────────┤
|
|
235
|
+
│ lib/crypto.ts │ lib/config.ts │
|
|
236
|
+
│ (NaCl encryption) │ (env + file config) │
|
|
237
|
+
└───────────────────────┴────────────────┬─────────────────────────┘
|
|
238
|
+
│
|
|
239
|
+
▼
|
|
240
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
241
|
+
│ STORAGE ADAPTERS │
|
|
242
|
+
├───────────────────────┬──────────────────────────────────────────┤
|
|
243
|
+
│ storage/supabase.ts │ storage/local.ts │
|
|
244
|
+
│ (PostgreSQL REST) │ (~/.myceliumail/data/) │
|
|
245
|
+
└───────────────────────┴──────────────────────────────────────────┘
|
|
130
246
|
```
|
|
131
247
|
|
|
132
|
-
**
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
248
|
+
**Key dependencies:**
|
|
249
|
+
- `commander` — CLI framework
|
|
250
|
+
- `tweetnacl` — NaCl crypto (audited, no native deps)
|
|
251
|
+
- `@supabase/supabase-js` — Realtime subscriptions
|
|
252
|
+
- `fastify` — Web dashboard server
|
|
253
|
+
- `@modelcontextprotocol/sdk` — Official MCP SDK
|
|
254
|
+
- `node-notifier` — Desktop notifications
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Supabase Setup
|
|
259
|
+
|
|
260
|
+
For cloud sync and multi-machine messaging:
|
|
261
|
+
|
|
262
|
+
1. Create a project at [supabase.com](https://supabase.com)
|
|
263
|
+
2. Run `supabase/migrations/000_myceliumail_setup.sql` in the SQL Editor
|
|
264
|
+
3. Enable Realtime on the `agent_messages` table
|
|
265
|
+
4. Copy your project URL and anon key to config
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Known Limitations
|
|
270
|
+
|
|
271
|
+
**By design:**
|
|
272
|
+
- No key server — Keys exchanged manually out-of-band (prevents MITM via server)
|
|
273
|
+
- No deletion — Messages can only be archived
|
|
274
|
+
- Case-sensitive agent IDs — `alice` ≠ `Alice`
|
|
275
|
+
|
|
276
|
+
**Current limitations:**
|
|
277
|
+
- Channels exist in schema but not yet in CLI
|
|
278
|
+
- `npx` caching can cause MCP server update issues — use direct path to `server.js`
|
|
279
|
+
- Dashboard and watch require Supabase for real-time updates
|
|
280
|
+
|
|
281
|
+
**Platform notes:**
|
|
282
|
+
- **Windows:** Key file permissions may not work correctly — secure `~/.myceliumail` manually
|
|
283
|
+
- **Docker:** Mount a volume for `~/.myceliumail` to persist data
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Roadmap
|
|
137
288
|
|
|
138
|
-
|
|
289
|
+
Myceliumail is part of the **Treebird ecosystem**—a suite of tools for AI agent coordination.
|
|
139
290
|
|
|
140
291
|
```
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
│
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
│
|
|
148
|
-
│
|
|
149
|
-
|
|
150
|
-
│ │ └── ...
|
|
151
|
-
│ ├── lib/
|
|
152
|
-
│ │ ├── crypto.ts # NaCl encryption
|
|
153
|
-
│ │ ├── supabase.ts # Database client
|
|
154
|
-
│ │ └── config.ts # Configuration
|
|
155
|
-
│ └── types/
|
|
156
|
-
│ └── index.ts # TypeScript types
|
|
157
|
-
├── supabase/
|
|
158
|
-
│ └── migrations/ # Database migrations
|
|
159
|
-
├── CLAUDE.md # AI agent context
|
|
160
|
-
├── README.md
|
|
161
|
-
└── package.json
|
|
292
|
+
┌───────────┐ ┌───────────┐ ┌───────────┐
|
|
293
|
+
│ STARTERSAN│ → │ MAPPERSAN │ → │ SPIDERSAN │
|
|
294
|
+
│ Bootstrap│ │ Document │ │ Coordinate│
|
|
295
|
+
└───────────┘ └───────────┘ └───────────┘
|
|
296
|
+
↓
|
|
297
|
+
┌───────────┐
|
|
298
|
+
│MYCELIUMAIL│
|
|
299
|
+
│Communicate│
|
|
300
|
+
└───────────┘
|
|
162
301
|
```
|
|
163
302
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
-- Public keys table
|
|
189
|
-
CREATE TABLE public_keys (
|
|
190
|
-
agent_id TEXT PRIMARY KEY,
|
|
191
|
-
public_key TEXT NOT NULL,
|
|
192
|
-
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
193
|
-
);
|
|
194
|
-
```
|
|
303
|
+
**Near-term (Myceliumail):**
|
|
304
|
+
- [ ] Channel commands (create, join, post)
|
|
305
|
+
- [ ] Agent presence/status system
|
|
306
|
+
- [ ] Message threading
|
|
307
|
+
- [ ] Agent discovery (`mycmail agents`)
|
|
308
|
+
|
|
309
|
+
**Ecosystem:**
|
|
310
|
+
- [x] Spidersan (branch coordination) — Built
|
|
311
|
+
- [ ] Startersan (repo bootstrap)
|
|
312
|
+
- [ ] Mappersan (living documentation)
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Contributing
|
|
317
|
+
|
|
318
|
+
This is early-stage software being built in public. Contributions welcome!
|
|
319
|
+
|
|
320
|
+
**Ways to help:**
|
|
321
|
+
- Open issues for bugs or feature ideas
|
|
322
|
+
- Share use cases—how would you use agent-to-agent messaging?
|
|
323
|
+
- Test with different AI coding tools (Cursor, Windsurf, etc.)
|
|
324
|
+
- Documentation improvements
|
|
195
325
|
|
|
196
|
-
|
|
326
|
+
**Development:**
|
|
197
327
|
|
|
198
328
|
```bash
|
|
199
|
-
|
|
329
|
+
git clone https://github.com/treebird7/Myceliumail.git
|
|
330
|
+
cd Myceliumail
|
|
200
331
|
npm install
|
|
332
|
+
npm run build
|
|
333
|
+
npm test
|
|
334
|
+
```
|
|
201
335
|
|
|
202
|
-
|
|
203
|
-
npm run dev
|
|
336
|
+
---
|
|
204
337
|
|
|
205
|
-
|
|
206
|
-
npm run build
|
|
338
|
+
## About
|
|
207
339
|
|
|
208
|
-
|
|
209
|
-
npm test
|
|
340
|
+
Built by **treebird**—a developer who kept drowning in merge conflicts while orchestrating multiple AI coding agents. The insight: we built tools for humans to collaborate, but never tools for AI agents to collaborate.
|
|
210
341
|
|
|
211
|
-
|
|
212
|
-
npm link
|
|
213
|
-
```
|
|
342
|
+
Myceliumail is part of the Treebird ecosystem, born from the belief that AI agents are productive alone, but codebases thrive when they coordinate.
|
|
214
343
|
|
|
215
|
-
|
|
344
|
+
**Contact:** treebird@treebird.dev
|
|
216
345
|
|
|
217
|
-
|
|
346
|
+
**Support the project:**
|
|
347
|
+
- [GitHub Sponsors](https://github.com/sponsors/treebird7)
|
|
348
|
+
- [Buy Me a Coffee](https://buymeacoffee.com/tree.bird)
|
|
218
349
|
|
|
219
|
-
|
|
220
|
-
-
|
|
221
|
-
-
|
|
350
|
+
**Links:**
|
|
351
|
+
- GitHub: [github.com/treebird7/Myceliumail](https://github.com/treebird7/Myceliumail)
|
|
352
|
+
- Spidersan (branch coordination): [github.com/treebird7/Spidersan](https://github.com/treebird7/Spidersan)
|
|
353
|
+
|
|
354
|
+
---
|
|
222
355
|
|
|
223
|
-
##
|
|
356
|
+
## License
|
|
224
357
|
|
|
225
|
-
MIT ©
|
|
358
|
+
MIT © treebird
|
|
226
359
|
|
|
227
360
|
---
|
|
228
361
|
|
|
229
|
-
*
|
|
362
|
+
*"AI agents are productive alone. But codebases thrive when they coordinate."*
|
|
@@ -25,15 +25,15 @@ export declare function sendMessage(sender: string, recipient: string | string[]
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function getInbox(agentId: string, options?: InboxOptions): Promise<Message[]>;
|
|
27
27
|
/**
|
|
28
|
-
* Get a specific message
|
|
28
|
+
* Get a specific message (supports partial ID lookup)
|
|
29
29
|
*/
|
|
30
30
|
export declare function getMessage(id: string): Promise<Message | null>;
|
|
31
31
|
/**
|
|
32
|
-
* Mark message as read
|
|
32
|
+
* Mark message as read (supports partial ID)
|
|
33
33
|
*/
|
|
34
34
|
export declare function markAsRead(id: string, agentId?: string): Promise<boolean>;
|
|
35
35
|
/**
|
|
36
|
-
* Archive a message
|
|
36
|
+
* Archive a message (supports partial ID)
|
|
37
37
|
*/
|
|
38
38
|
export declare function archiveMessage(id: string): Promise<boolean>;
|
|
39
39
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/storage/supabase.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA2E/D;;GAEG;AACH,wBAAsB,WAAW,CAC7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACN,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9E,GACF,OAAO,CAAC,OAAO,CAAC,CA8DlB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAuD1F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/storage/supabase.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA2E/D;;GAEG;AACH,wBAAsB,WAAW,CAC7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACN,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9E,GACF,OAAO,CAAC,OAAO,CAAC,CA8DlB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAuD1F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA8FpE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwB/E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwBjE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAehE"}
|
package/dist/storage/supabase.js
CHANGED
|
@@ -159,13 +159,48 @@ export async function getInbox(agentId, options) {
|
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
|
-
* Get a specific message
|
|
162
|
+
* Get a specific message (supports partial ID lookup)
|
|
163
163
|
*/
|
|
164
164
|
export async function getMessage(id) {
|
|
165
165
|
const client = createClient();
|
|
166
166
|
if (!client) {
|
|
167
167
|
return local.getMessage(id);
|
|
168
168
|
}
|
|
169
|
+
// For partial IDs, fetch recent messages and filter client-side
|
|
170
|
+
// (PostgreSQL UUID type doesn't support LIKE operator)
|
|
171
|
+
if (id.length < 36) {
|
|
172
|
+
const results = await supabaseRequest(client, `/agent_messages?order=created_at.desc&limit=100`);
|
|
173
|
+
const r = results.find(row => row.id.startsWith(id));
|
|
174
|
+
if (!r)
|
|
175
|
+
return null;
|
|
176
|
+
// Parse encrypted message
|
|
177
|
+
let ciphertext, nonce, senderPublicKey, body = r.message;
|
|
178
|
+
if (r.encrypted && r.message) {
|
|
179
|
+
try {
|
|
180
|
+
const enc = JSON.parse(r.message);
|
|
181
|
+
ciphertext = enc.ciphertext;
|
|
182
|
+
nonce = enc.nonce;
|
|
183
|
+
senderPublicKey = enc.sender_public_key;
|
|
184
|
+
body = '';
|
|
185
|
+
}
|
|
186
|
+
catch { }
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
id: r.id,
|
|
190
|
+
sender: r.from_agent,
|
|
191
|
+
recipient: r.to_agent,
|
|
192
|
+
subject: r.subject || '',
|
|
193
|
+
body,
|
|
194
|
+
encrypted: r.encrypted,
|
|
195
|
+
ciphertext,
|
|
196
|
+
nonce,
|
|
197
|
+
senderPublicKey,
|
|
198
|
+
read: r.read,
|
|
199
|
+
archived: false,
|
|
200
|
+
createdAt: new Date(r.created_at),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
// Full UUID - exact match
|
|
169
204
|
const results = await supabaseRequest(client, `/agent_messages?id=eq.${id}`);
|
|
170
205
|
if (results.length === 0)
|
|
171
206
|
return null;
|
|
@@ -198,15 +233,23 @@ export async function getMessage(id) {
|
|
|
198
233
|
};
|
|
199
234
|
}
|
|
200
235
|
/**
|
|
201
|
-
* Mark message as read
|
|
236
|
+
* Mark message as read (supports partial ID)
|
|
202
237
|
*/
|
|
203
238
|
export async function markAsRead(id, agentId) {
|
|
204
239
|
const client = createClient();
|
|
205
240
|
if (!client) {
|
|
206
241
|
return local.markAsRead(id, agentId);
|
|
207
242
|
}
|
|
243
|
+
// For partial IDs, resolve full UUID first
|
|
244
|
+
let fullId = id;
|
|
245
|
+
if (id.length < 36) {
|
|
246
|
+
const msg = await getMessage(id);
|
|
247
|
+
if (!msg)
|
|
248
|
+
return false;
|
|
249
|
+
fullId = msg.id;
|
|
250
|
+
}
|
|
208
251
|
try {
|
|
209
|
-
await supabaseRequest(client, `/agent_messages?id=eq.${
|
|
252
|
+
await supabaseRequest(client, `/agent_messages?id=eq.${fullId}`, {
|
|
210
253
|
method: 'PATCH',
|
|
211
254
|
body: JSON.stringify({ read: true }),
|
|
212
255
|
});
|
|
@@ -217,15 +260,23 @@ export async function markAsRead(id, agentId) {
|
|
|
217
260
|
}
|
|
218
261
|
}
|
|
219
262
|
/**
|
|
220
|
-
* Archive a message
|
|
263
|
+
* Archive a message (supports partial ID)
|
|
221
264
|
*/
|
|
222
265
|
export async function archiveMessage(id) {
|
|
223
266
|
const client = createClient();
|
|
224
267
|
if (!client) {
|
|
225
268
|
return local.archiveMessage(id);
|
|
226
269
|
}
|
|
270
|
+
// For partial IDs, resolve full UUID first
|
|
271
|
+
let fullId = id;
|
|
272
|
+
if (id.length < 36) {
|
|
273
|
+
const msg = await getMessage(id);
|
|
274
|
+
if (!msg)
|
|
275
|
+
return false;
|
|
276
|
+
fullId = msg.id;
|
|
277
|
+
}
|
|
227
278
|
try {
|
|
228
|
-
await supabaseRequest(client, `/agent_messages?id=eq.${
|
|
279
|
+
await supabaseRequest(client, `/agent_messages?id=eq.${fullId}`, {
|
|
229
280
|
method: 'PATCH',
|
|
230
281
|
body: JSON.stringify({ archived: true }),
|
|
231
282
|
});
|