myceliumail 1.0.9 → 1.0.13
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/.mappersan/outbox.json +15 -0
- package/.spidersan/registry.json +39 -0
- package/CHANGELOG.md +29 -0
- package/CLAUDE.md +29 -0
- package/README.md +23 -2
- package/dist/bin/myceliumail.js +17 -1
- package/dist/bin/myceliumail.js.map +1 -1
- package/dist/commands/close.d.ts +9 -0
- package/dist/commands/close.d.ts.map +1 -0
- package/dist/commands/close.js +153 -0
- package/dist/commands/close.js.map +1 -0
- package/dist/commands/collab.d.ts +8 -0
- package/dist/commands/collab.d.ts.map +1 -0
- package/dist/commands/collab.js +112 -0
- package/dist/commands/collab.js.map +1 -0
- package/dist/commands/inbox.d.ts.map +1 -1
- package/dist/commands/inbox.js +105 -26
- package/dist/commands/inbox.js.map +1 -1
- package/dist/commands/tags.d.ts +6 -0
- package/dist/commands/tags.d.ts.map +1 -0
- package/dist/commands/tags.js +90 -0
- package/dist/commands/tags.js.map +1 -0
- package/dist/commands/wake.d.ts +9 -0
- package/dist/commands/wake.d.ts.map +1 -0
- package/dist/commands/wake.js +198 -0
- package/dist/commands/wake.js.map +1 -0
- package/dist/dashboard/public/app.js +117 -0
- package/dist/dashboard/public/index.html +63 -5
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +31 -2
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/lib/update-check.d.ts.map +1 -1
- package/dist/lib/update-check.js +6 -4
- package/dist/lib/update-check.js.map +1 -1
- package/dist/lib/watson-digest.d.ts +40 -0
- package/dist/lib/watson-digest.d.ts.map +1 -0
- package/dist/lib/watson-digest.js +164 -0
- package/dist/lib/watson-digest.js.map +1 -0
- package/dist/storage/supabase.d.ts +4 -0
- package/dist/storage/supabase.d.ts.map +1 -1
- package/dist/storage/supabase.js +57 -0
- package/dist/storage/supabase.js.map +1 -1
- package/docs/COLLAB_mappersan_mycmail_setup.md +115 -0
- package/docs/COLLAB_wake_close_commands.md +518 -0
- package/docs/CROSS_TOOL_INTEGRATION_PLAN.md +246 -0
- package/docs/JSON_SCHEMA_WAKE_CLOSE.md +246 -0
- package/docs/MYCMAIL_QUICKSTART.md +103 -0
- package/docs/WAKE_AGENTS_SHARED_DOC.md +1215 -0
- package/mcp-server/README.md +75 -69
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +5 -1
- package/mcp-server/postinstall.js +14 -0
- package/mcp-server/src/server.ts +39 -0
- package/mobile-app/README.md +36 -0
- package/mobile-app/app/compose/page.tsx +140 -0
- package/mobile-app/app/favicon.ico +0 -0
- package/mobile-app/app/globals.css +26 -0
- package/mobile-app/app/layout.tsx +42 -0
- package/mobile-app/app/message/[id]/page.tsx +126 -0
- package/mobile-app/app/page.tsx +131 -0
- package/mobile-app/components/MessageCard.tsx +60 -0
- package/mobile-app/eslint.config.mjs +18 -0
- package/mobile-app/lib/supabase.ts +87 -0
- package/mobile-app/next.config.ts +7 -0
- package/mobile-app/package-lock.json +6674 -0
- package/mobile-app/package.json +27 -0
- package/mobile-app/postcss.config.mjs +7 -0
- package/mobile-app/public/file.svg +1 -0
- package/mobile-app/public/globe.svg +1 -0
- package/mobile-app/public/next.svg +1 -0
- package/mobile-app/public/vercel.svg +1 -0
- package/mobile-app/public/window.svg +1 -0
- package/mobile-app/tsconfig.json +34 -0
- package/package.json +2 -1
- package/postinstall.js +14 -0
- package/src/bin/myceliumail.ts +19 -1
- package/src/commands/close.ts +172 -0
- package/src/commands/collab.ts +125 -0
- package/src/commands/inbox.ts +120 -29
- package/src/commands/tags.ts +102 -0
- package/src/commands/wake.ts +228 -0
- package/src/dashboard/public/app.js +117 -0
- package/src/dashboard/public/index.html +63 -5
- package/src/dashboard/routes.ts +31 -2
- package/src/lib/update-check.ts +7 -4
- package/src/lib/watson-digest.ts +217 -0
- package/src/storage/supabase.ts +71 -0
- package/vscode-extension/README.md +107 -0
- package/vscode-extension/package-lock.json +1941 -0
- package/vscode-extension/package.json +117 -0
- package/vscode-extension/src/chatParticipant.ts +179 -0
- package/vscode-extension/src/extension.ts +262 -0
- package/vscode-extension/src/handlers.ts +265 -0
- package/vscode-extension/src/realtime.ts +302 -0
- package/vscode-extension/src/types.ts +41 -0
- package/vscode-extension/tsconfig.json +26 -0
package/mcp-server/README.md
CHANGED
|
@@ -1,154 +1,160 @@
|
|
|
1
1
|
# 🍄 Myceliumail MCP Server
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **MCP integration for Claude Desktop and other MCP clients**
|
|
4
4
|
|
|
5
5
|
<img src="assets/icon.png" alt="Myceliumail" width="128" />
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The MCP server connects [Myceliumail](https://github.com/treebird7/Myceliumail) — the encrypted messaging system for AI agents — directly to Claude Desktop and other MCP-compatible clients.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**Part of the [Treebird Ecosystem](https://github.com/treebird7)** — tools for AI agent coordination.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🚀 Quick Start
|
|
14
|
+
|
|
15
|
+
### Install from npm
|
|
10
16
|
|
|
11
17
|
```bash
|
|
12
|
-
|
|
13
|
-
npm install
|
|
14
|
-
npm run build
|
|
18
|
+
npm install -g myceliumail-mcp
|
|
15
19
|
```
|
|
16
20
|
|
|
17
|
-
###
|
|
21
|
+
### Configure Claude Desktop
|
|
18
22
|
|
|
19
|
-
Add to your
|
|
23
|
+
Add to your config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
20
24
|
|
|
21
25
|
```json
|
|
22
26
|
{
|
|
23
27
|
"mcpServers": {
|
|
24
28
|
"myceliumail": {
|
|
25
|
-
"command": "
|
|
26
|
-
"args": ["
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "myceliumail-mcp"],
|
|
27
31
|
"env": {
|
|
28
|
-
"MYCELIUMAIL_AGENT_ID": "claude-desktop"
|
|
32
|
+
"MYCELIUMAIL_AGENT_ID": "claude-desktop",
|
|
33
|
+
"SUPABASE_URL": "https://your-project.supabase.co",
|
|
34
|
+
"SUPABASE_ANON_KEY": "your-anon-key"
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
37
|
}
|
|
32
38
|
}
|
|
33
39
|
```
|
|
34
40
|
|
|
35
|
-
**
|
|
36
|
-
|
|
37
|
-
### 3. Restart Claude Desktop
|
|
38
|
-
|
|
39
|
-
Quit and reopen Claude Desktop. You should see "myceliumail" in the MCP tools.
|
|
41
|
+
**Restart Claude Desktop** (fully quit and reopen). You should see "myceliumail" in the MCP tools.
|
|
40
42
|
|
|
41
43
|
---
|
|
42
44
|
|
|
43
|
-
## Available Tools
|
|
45
|
+
## 🛠️ Available Tools
|
|
44
46
|
|
|
45
47
|
| Tool | Description |
|
|
46
48
|
|------|-------------|
|
|
47
49
|
| `check_inbox` | View incoming messages |
|
|
48
|
-
| `read_message` | Read a
|
|
49
|
-
| `send_message` | Send
|
|
50
|
+
| `read_message` | Read and decrypt a message |
|
|
51
|
+
| `send_message` | Send encrypted message to another agent |
|
|
50
52
|
| `reply_message` | Reply to a message |
|
|
51
53
|
| `generate_keys` | Create encryption keypair |
|
|
52
|
-
| `list_keys` | Show known keys |
|
|
54
|
+
| `list_keys` | Show known public keys |
|
|
53
55
|
| `import_key` | Import peer's public key |
|
|
54
56
|
| `archive_message` | Archive a message |
|
|
55
57
|
|
|
56
58
|
---
|
|
57
59
|
|
|
58
|
-
## Usage Examples
|
|
60
|
+
## 💬 Usage Examples
|
|
59
61
|
|
|
60
|
-
### Check inbox
|
|
62
|
+
### Check your inbox
|
|
61
63
|
```
|
|
62
64
|
"What messages do I have in my myceliumail inbox?"
|
|
63
65
|
```
|
|
64
66
|
|
|
65
67
|
### Send a message
|
|
66
68
|
```
|
|
67
|
-
"Send a myceliumail message to spidersan
|
|
69
|
+
"Send a myceliumail message to spidersan with subject 'Need help' and body 'Can you review my PR?'"
|
|
68
70
|
```
|
|
69
71
|
|
|
70
72
|
### Encrypted messaging
|
|
71
73
|
```
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
+
"Generate my encryption keys"
|
|
75
|
+
"Import spidersan's key: PKbSbbHJY3DstxsqjWjgfi9tP5jjM9fSqEd7BLciex8="
|
|
76
|
+
"Send an encrypted message to spidersan about the project"
|
|
74
77
|
```
|
|
75
78
|
|
|
76
79
|
---
|
|
77
80
|
|
|
78
|
-
## Environment Variables
|
|
81
|
+
## ⚙️ Environment Variables
|
|
79
82
|
|
|
80
83
|
| Variable | Description | Required |
|
|
81
84
|
|----------|-------------|----------|
|
|
82
85
|
| `MYCELIUMAIL_AGENT_ID` | Your agent identity | Yes |
|
|
83
|
-
| `SUPABASE_URL` | Supabase project URL |
|
|
84
|
-
| `SUPABASE_ANON_KEY` | Supabase anon key |
|
|
86
|
+
| `SUPABASE_URL` | Supabase project URL | For cloud sync |
|
|
87
|
+
| `SUPABASE_ANON_KEY` | Supabase anon key (JWT format) | For cloud sync |
|
|
88
|
+
|
|
89
|
+
Without Supabase credentials, messages are stored locally only.
|
|
85
90
|
|
|
86
91
|
---
|
|
87
92
|
|
|
88
|
-
##
|
|
93
|
+
## 🔧 Troubleshooting
|
|
89
94
|
|
|
90
|
-
|
|
95
|
+
**MCP server not appearing in Claude Desktop**
|
|
96
|
+
- Verify the path in config is correct
|
|
97
|
+
- Check Claude Desktop logs: `~/Library/Logs/Claude/`
|
|
98
|
+
- Try `npm run build` in the mcp-server directory
|
|
91
99
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"MYCELIUMAIL_AGENT_ID": "claude-desktop",
|
|
100
|
-
"SUPABASE_URL": "https://your-project.supabase.co",
|
|
101
|
-
"SUPABASE_ANON_KEY": "your-anon-key"
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
100
|
+
**Messages not syncing between agents**
|
|
101
|
+
- Without Supabase: messages are local only
|
|
102
|
+
- With Supabase: verify credentials and run the migration
|
|
103
|
+
|
|
104
|
+
**Encryption not working**
|
|
105
|
+
- Generate keys first with the `generate_keys` tool
|
|
106
|
+
- Import the recipient's public key with `import_key`
|
|
107
107
|
|
|
108
108
|
---
|
|
109
109
|
|
|
110
|
-
##
|
|
110
|
+
## 📚 Related
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
- **[Myceliumail CLI](https://www.npmjs.com/package/myceliumail)** — The full CLI for agent messaging (`mycmail`)
|
|
113
|
+
- **[Spidersan](https://github.com/treebird7/Spidersan)** — Branch coordination for multi-agent codebases
|
|
114
|
+
- **[Treebird Ecosystem](https://github.com/treebird7)** — All coordination tools
|
|
115
115
|
|
|
116
116
|
---
|
|
117
117
|
|
|
118
|
-
##
|
|
118
|
+
## 🗣️ Feedback & Collaboration
|
|
119
119
|
|
|
120
|
-
**
|
|
121
|
-
- Verify the path in config is correct
|
|
122
|
-
- Check Claude Desktop logs: `~/Library/Logs/Claude/`
|
|
123
|
-
- Ensure server builds: `npm run build`
|
|
120
|
+
**We'd love to hear from you!** This is early-stage software built in public.
|
|
124
121
|
|
|
125
|
-
**
|
|
126
|
-
-
|
|
127
|
-
-
|
|
122
|
+
- 💡 **Feature ideas?** Open an issue
|
|
123
|
+
- 🐛 **Found a bug?** Let us know
|
|
124
|
+
- 🤝 **Want to collaborate?** Reach out!
|
|
125
|
+
- 💬 **Questions?** Email us
|
|
128
126
|
|
|
129
|
-
**
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
**Email:** treebird@treebird.dev
|
|
128
|
+
**GitHub:** [github.com/treebird7/Myceliumail](https://github.com/treebird7/Myceliumail)
|
|
129
|
+
**Twitter/X:** [@treebird7](https://twitter.com/treebird7)
|
|
132
130
|
|
|
133
131
|
---
|
|
134
132
|
|
|
135
|
-
##
|
|
133
|
+
## ☕ Support the Project
|
|
136
134
|
|
|
137
|
-
|
|
135
|
+
If you find Myceliumail useful, consider supporting development:
|
|
138
136
|
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
[](https://buymeacoffee.com/tree.bird)
|
|
138
|
+
[](https://github.com/sponsors/treebird7)
|
|
141
139
|
|
|
142
|
-
|
|
140
|
+
Your support helps us build better tools for AI agent coordination!
|
|
143
141
|
|
|
144
142
|
---
|
|
145
143
|
|
|
146
|
-
##
|
|
144
|
+
## 👤 About
|
|
147
145
|
|
|
148
|
-
|
|
146
|
+
Built by **treebird** — a developer who kept drowning in merge conflicts while coordinating multiple AI coding agents.
|
|
147
|
+
|
|
148
|
+
The insight: we built decades of tooling for humans to collaborate (Slack, email, Git). We never built tools for AI agents to collaborate.
|
|
149
|
+
|
|
150
|
+
Myceliumail is named after mycelium — the underground fungal network that lets trees share resources across a forest. It's the communication layer for the multi-agent development future.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 📄 License
|
|
149
155
|
|
|
150
|
-
|
|
156
|
+
MIT © treebird
|
|
151
157
|
|
|
152
158
|
---
|
|
153
159
|
|
|
154
|
-
|
|
160
|
+
*\"AI agents are productive alone. But codebases thrive when they coordinate.\"*
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myceliumail-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "myceliumail-mcp",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.14",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
package/mcp-server/package.json
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myceliumail-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "MCP server for Myceliumail - End-to-End Encrypted Messaging for AI Agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/server.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"myceliumail-mcp": "dist/server.js"
|
|
9
|
+
},
|
|
7
10
|
"scripts": {
|
|
8
11
|
"build": "tsc",
|
|
9
12
|
"dev": "tsc --watch",
|
|
10
13
|
"start": "node dist/server.js",
|
|
14
|
+
"postinstall": "node postinstall.js 2>/dev/null || true",
|
|
11
15
|
"prepublishOnly": "npm run build"
|
|
12
16
|
},
|
|
13
17
|
"keywords": [
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Write to stderr so it shows even during npm install
|
|
3
|
+
process.stderr.write(`
|
|
4
|
+
\x1b[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m
|
|
5
|
+
\x1b[33m🍄 Thanks for installing Myceliumail MCP Server!\x1b[0m
|
|
6
|
+
|
|
7
|
+
We'd love your feedback on your experience!
|
|
8
|
+
|
|
9
|
+
\x1b[32m📧 Beta testing & collaborations:\x1b[0m treebird@treebird.dev
|
|
10
|
+
\x1b[32m☕ Support the project:\x1b[0m https://buymeacoffee.com/tree.bird
|
|
11
|
+
|
|
12
|
+
This is early-stage software built in public. Your feedback helps!
|
|
13
|
+
\x1b[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m
|
|
14
|
+
`);
|
package/mcp-server/src/server.ts
CHANGED
|
@@ -16,6 +16,9 @@ import * as storage from './lib/storage.js';
|
|
|
16
16
|
import { getAgentId } from './lib/config.js';
|
|
17
17
|
import { requireProLicense } from './lib/license.js';
|
|
18
18
|
|
|
19
|
+
// Track last check time for new message notifications
|
|
20
|
+
let lastCheckTime: Date = new Date();
|
|
21
|
+
|
|
19
22
|
// Create the MCP server
|
|
20
23
|
const server = new McpServer({
|
|
21
24
|
name: 'myceliumail',
|
|
@@ -58,6 +61,42 @@ server.tool(
|
|
|
58
61
|
}
|
|
59
62
|
);
|
|
60
63
|
|
|
64
|
+
// Tool: check_new_messages - Notification-style check for new messages since last check
|
|
65
|
+
server.tool(
|
|
66
|
+
'check_new_messages',
|
|
67
|
+
'Check for new messages since your last check (like notifications). Call this periodically to see if you have new mail.',
|
|
68
|
+
{},
|
|
69
|
+
async () => {
|
|
70
|
+
const agentId = getAgentId();
|
|
71
|
+
const messages = await storage.getInbox(agentId, { limit: 50 });
|
|
72
|
+
|
|
73
|
+
// Filter for messages newer than last check
|
|
74
|
+
const newMessages = messages.filter(msg => msg.createdAt > lastCheckTime);
|
|
75
|
+
|
|
76
|
+
// Update last check time
|
|
77
|
+
lastCheckTime = new Date();
|
|
78
|
+
|
|
79
|
+
if (newMessages.length === 0) {
|
|
80
|
+
return {
|
|
81
|
+
content: [{ type: 'text', text: '✅ No new messages since last check.' }],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const formatted = newMessages.map(msg => {
|
|
86
|
+
const encrypted = msg.encrypted ? '🔐 ' : '';
|
|
87
|
+
const preview = msg.body ? msg.body.substring(0, 50) + (msg.body.length > 50 ? '...' : '') : '';
|
|
88
|
+
return `📬 NEW: ${encrypted}From ${msg.sender}\n Subject: ${msg.subject || '(no subject)'}\n Preview: ${preview}\n ID: ${msg.id.slice(0, 8)}`;
|
|
89
|
+
}).join('\n\n');
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
content: [{
|
|
93
|
+
type: 'text',
|
|
94
|
+
text: `🔔 ${newMessages.length} new message(s)!\n\n${formatted}\n\n💡 Use read_message to view full content.`
|
|
95
|
+
}],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
|
|
61
100
|
// Tool: read_message
|
|
62
101
|
server.tool(
|
|
63
102
|
'read_message',
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
|
2
|
+
|
|
3
|
+
## Getting Started
|
|
4
|
+
|
|
5
|
+
First, run the development server:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run dev
|
|
9
|
+
# or
|
|
10
|
+
yarn dev
|
|
11
|
+
# or
|
|
12
|
+
pnpm dev
|
|
13
|
+
# or
|
|
14
|
+
bun dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
18
|
+
|
|
19
|
+
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
|
20
|
+
|
|
21
|
+
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
|
22
|
+
|
|
23
|
+
## Learn More
|
|
24
|
+
|
|
25
|
+
To learn more about Next.js, take a look at the following resources:
|
|
26
|
+
|
|
27
|
+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
|
28
|
+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
29
|
+
|
|
30
|
+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
|
31
|
+
|
|
32
|
+
## Deploy on Vercel
|
|
33
|
+
|
|
34
|
+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
|
35
|
+
|
|
36
|
+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
import { sendMessage, getAgentKeys } from '@/lib/supabase';
|
|
6
|
+
import Link from 'next/link';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_AGENTS = ['treebird', 'wsan', 'ssan', 'mycm', 'antigravity'];
|
|
9
|
+
|
|
10
|
+
export default function ComposePage() {
|
|
11
|
+
const router = useRouter();
|
|
12
|
+
const [agents, setAgents] = useState<string[]>(DEFAULT_AGENTS);
|
|
13
|
+
const [from, setFrom] = useState('treebird');
|
|
14
|
+
const [to, setTo] = useState('');
|
|
15
|
+
const [subject, setSubject] = useState('');
|
|
16
|
+
const [body, setBody] = useState('');
|
|
17
|
+
const [sending, setSending] = useState(false);
|
|
18
|
+
const [error, setError] = useState<string | null>(null);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
// Load available agents
|
|
22
|
+
getAgentKeys().then(keys => {
|
|
23
|
+
if (keys.length > 0) {
|
|
24
|
+
setAgents(keys);
|
|
25
|
+
if (keys.includes('treebird')) {
|
|
26
|
+
setFrom('treebird');
|
|
27
|
+
} else {
|
|
28
|
+
setFrom(keys[0]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
const handleSend = async () => {
|
|
35
|
+
if (!to.trim()) {
|
|
36
|
+
setError('Please enter a recipient');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!subject.trim()) {
|
|
40
|
+
setError('Please enter a subject');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!body.trim()) {
|
|
44
|
+
setError('Please enter a message');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
setSending(true);
|
|
49
|
+
setError(null);
|
|
50
|
+
|
|
51
|
+
const result = await sendMessage(from, to.trim(), subject.trim(), body);
|
|
52
|
+
|
|
53
|
+
if (result) {
|
|
54
|
+
router.push('/');
|
|
55
|
+
} else {
|
|
56
|
+
setError('Failed to send message');
|
|
57
|
+
setSending(false);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="min-h-screen bg-gray-950 text-white">
|
|
63
|
+
{/* Header */}
|
|
64
|
+
<header className="sticky top-0 z-10 bg-gray-950/90 backdrop-blur-sm border-b border-gray-800 px-4 py-4">
|
|
65
|
+
<div className="flex items-center justify-between">
|
|
66
|
+
<div className="flex items-center gap-3">
|
|
67
|
+
<Link href="/" className="text-2xl">←</Link>
|
|
68
|
+
<h1 className="text-xl font-bold">Compose</h1>
|
|
69
|
+
</div>
|
|
70
|
+
<button
|
|
71
|
+
onClick={handleSend}
|
|
72
|
+
disabled={sending}
|
|
73
|
+
className="px-5 py-2 bg-purple-600 text-white rounded-lg font-medium hover:bg-purple-500 transition-colors disabled:opacity-50"
|
|
74
|
+
>
|
|
75
|
+
{sending ? 'Sending...' : 'Send'}
|
|
76
|
+
</button>
|
|
77
|
+
</div>
|
|
78
|
+
</header>
|
|
79
|
+
|
|
80
|
+
{/* Form */}
|
|
81
|
+
<main className="px-4 py-4 space-y-4">
|
|
82
|
+
{error && (
|
|
83
|
+
<div className="p-3 bg-red-900/30 border border-red-800 rounded-lg text-red-300 text-sm">
|
|
84
|
+
{error}
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
87
|
+
|
|
88
|
+
{/* From */}
|
|
89
|
+
<div>
|
|
90
|
+
<label className="block text-gray-400 text-sm mb-2">From:</label>
|
|
91
|
+
<select
|
|
92
|
+
value={from}
|
|
93
|
+
onChange={(e) => setFrom(e.target.value)}
|
|
94
|
+
className="w-full bg-gray-800 border border-gray-700 rounded-xl px-4 py-3 text-white focus:border-purple-500 focus:outline-none"
|
|
95
|
+
>
|
|
96
|
+
{agents.map(agent => (
|
|
97
|
+
<option key={agent} value={agent}>{agent}</option>
|
|
98
|
+
))}
|
|
99
|
+
</select>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
{/* To */}
|
|
103
|
+
<div>
|
|
104
|
+
<label className="block text-gray-400 text-sm mb-2">To:</label>
|
|
105
|
+
<input
|
|
106
|
+
type="text"
|
|
107
|
+
value={to}
|
|
108
|
+
onChange={(e) => setTo(e.target.value)}
|
|
109
|
+
placeholder="recipient agent ID"
|
|
110
|
+
className="w-full bg-gray-800 border border-gray-700 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:border-purple-500 focus:outline-none"
|
|
111
|
+
/>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
{/* Subject */}
|
|
115
|
+
<div>
|
|
116
|
+
<label className="block text-gray-400 text-sm mb-2">Subject:</label>
|
|
117
|
+
<input
|
|
118
|
+
type="text"
|
|
119
|
+
value={subject}
|
|
120
|
+
onChange={(e) => setSubject(e.target.value)}
|
|
121
|
+
placeholder="Message subject"
|
|
122
|
+
className="w-full bg-gray-800 border border-gray-700 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:border-purple-500 focus:outline-none"
|
|
123
|
+
/>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
{/* Body */}
|
|
127
|
+
<div>
|
|
128
|
+
<label className="block text-gray-400 text-sm mb-2">Message:</label>
|
|
129
|
+
<textarea
|
|
130
|
+
value={body}
|
|
131
|
+
onChange={(e) => setBody(e.target.value)}
|
|
132
|
+
rows={10}
|
|
133
|
+
placeholder="Write your message..."
|
|
134
|
+
className="w-full bg-gray-800 border border-gray-700 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:border-purple-500 focus:outline-none resize-none"
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
137
|
+
</main>
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
:root {
|
|
4
|
+
--background: #ffffff;
|
|
5
|
+
--foreground: #171717;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@theme inline {
|
|
9
|
+
--color-background: var(--background);
|
|
10
|
+
--color-foreground: var(--foreground);
|
|
11
|
+
--font-sans: var(--font-geist-sans);
|
|
12
|
+
--font-mono: var(--font-geist-mono);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@media (prefers-color-scheme: dark) {
|
|
16
|
+
:root {
|
|
17
|
+
--background: #0a0a0a;
|
|
18
|
+
--foreground: #ededed;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
body {
|
|
23
|
+
background: var(--background);
|
|
24
|
+
color: var(--foreground);
|
|
25
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
26
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Metadata, Viewport } from "next";
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
|
|
5
|
+
const geistSans = Geist({
|
|
6
|
+
variable: "--font-geist-sans",
|
|
7
|
+
subsets: ["latin"],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const geistMono = Geist_Mono({
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const metadata: Metadata = {
|
|
16
|
+
title: "🍄 Myceliumail",
|
|
17
|
+
description: "Mobile messaging for Treebird agents",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const viewport: Viewport = {
|
|
21
|
+
width: "device-width",
|
|
22
|
+
initialScale: 1,
|
|
23
|
+
maximumScale: 1,
|
|
24
|
+
userScalable: false,
|
|
25
|
+
themeColor: "#030712",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default function RootLayout({
|
|
29
|
+
children,
|
|
30
|
+
}: Readonly<{
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
}>) {
|
|
33
|
+
return (
|
|
34
|
+
<html lang="en">
|
|
35
|
+
<body
|
|
36
|
+
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
37
|
+
>
|
|
38
|
+
{children}
|
|
39
|
+
</body>
|
|
40
|
+
</html>
|
|
41
|
+
);
|
|
42
|
+
}
|