myceliumail 1.0.2 → 1.0.4
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/.context7 +87 -0
- package/.eslintrc.json +29 -0
- package/.github/workflows/publish.yml +108 -0
- package/CHANGELOG.md +85 -0
- package/README.md +295 -162
- package/desktop/README.md +102 -0
- package/desktop/assets/icon.icns +0 -0
- package/desktop/assets/icon.iconset/icon_128x128.png +0 -0
- package/desktop/assets/icon.iconset/icon_128x128@2x.png +0 -0
- package/desktop/assets/icon.iconset/icon_16x16.png +0 -0
- package/desktop/assets/icon.iconset/icon_16x16@2x.png +0 -0
- package/desktop/assets/icon.iconset/icon_256x256.png +0 -0
- package/desktop/assets/icon.iconset/icon_256x256@2x.png +0 -0
- package/desktop/assets/icon.iconset/icon_32x32.png +0 -0
- package/desktop/assets/icon.iconset/icon_32x32@2x.png +0 -0
- package/desktop/assets/icon.iconset/icon_512x512.png +0 -0
- package/desktop/assets/icon.iconset/icon_512x512@2x.png +0 -0
- package/desktop/assets/icon.png +0 -0
- package/desktop/assets/tray-icon.png +0 -0
- package/desktop/main.js +257 -0
- package/desktop/package-lock.json +4198 -0
- package/desktop/package.json +48 -0
- package/desktop/preload.js +11 -0
- package/dist/bin/myceliumail.js +2 -0
- package/dist/bin/myceliumail.js.map +1 -1
- package/dist/commands/key-announce.d.ts +6 -0
- package/dist/commands/key-announce.d.ts.map +1 -0
- package/dist/commands/key-announce.js +63 -0
- package/dist/commands/key-announce.js.map +1 -0
- package/docs/AGENT_STARTER_KIT.md +145 -0
- package/docs/DEPLOYMENT.md +59 -0
- package/docs/LESSONS_LEARNED.md +127 -0
- package/docs/MCP_STARTER_KIT.md +117 -0
- package/mcp-server/README.md +143 -0
- package/mcp-server/assets/icon.png +0 -0
- package/mcp-server/myceliumail-mcp-1.0.0.tgz +0 -0
- package/mcp-server/package-lock.json +1141 -0
- package/mcp-server/package.json +50 -0
- package/mcp-server/src/lib/config.ts +55 -0
- package/mcp-server/src/lib/crypto.ts +150 -0
- package/mcp-server/src/lib/storage.ts +267 -0
- package/mcp-server/src/server.ts +387 -0
- package/mcp-server/tsconfig.json +26 -0
- package/package.json +13 -4
- package/src/bin/myceliumail.ts +54 -0
- package/src/commands/broadcast.ts +70 -0
- package/src/commands/dashboard.ts +19 -0
- package/src/commands/inbox.ts +75 -0
- package/src/commands/key-announce.ts +70 -0
- package/src/commands/key-import.ts +35 -0
- package/src/commands/keygen.ts +44 -0
- package/src/commands/keys.ts +55 -0
- package/src/commands/read.ts +97 -0
- package/src/commands/send.ts +89 -0
- package/src/commands/watch.ts +101 -0
- package/src/dashboard/public/app.js +523 -0
- package/src/dashboard/public/index.html +75 -0
- package/src/dashboard/public/styles.css +68 -0
- package/src/dashboard/routes.ts +128 -0
- package/src/dashboard/server.ts +33 -0
- package/src/lib/config.ts +104 -0
- package/src/lib/crypto.ts +210 -0
- package/src/lib/realtime.ts +109 -0
- package/src/storage/local.ts +209 -0
- package/src/storage/supabase.ts +336 -0
- package/src/types/index.ts +53 -0
- package/supabase/migrations/000_myceliumail_setup.sql +93 -0
- package/supabase/migrations/001_enable_realtime.sql +10 -0
- package/tsconfig.json +28 -0
package/desktop/main.js
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
const { app, BrowserWindow, Menu, Tray, shell, Notification } = require('electron');
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { createClient } = require('@supabase/supabase-js');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
let mainWindow;
|
|
9
|
+
let tray;
|
|
10
|
+
let dashboardProcess;
|
|
11
|
+
let supabaseClient;
|
|
12
|
+
let realtimeChannel;
|
|
13
|
+
const DASHBOARD_PORT = 3737;
|
|
14
|
+
|
|
15
|
+
// Load config from ~/.myceliumail/config.json
|
|
16
|
+
function loadConfig() {
|
|
17
|
+
const configPath = path.join(os.homedir(), '.myceliumail', 'config.json');
|
|
18
|
+
try {
|
|
19
|
+
if (fs.existsSync(configPath)) {
|
|
20
|
+
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
21
|
+
return JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
} catch (err) {
|
|
24
|
+
console.error('Failed to load config:', err);
|
|
25
|
+
}
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Setup Supabase Realtime subscription
|
|
30
|
+
function setupRealtimeNotifications(config) {
|
|
31
|
+
if (!config.supabase_url || !config.supabase_key) {
|
|
32
|
+
console.log('Supabase not configured, skipping realtime notifications');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const agentId = config.agent_id || 'anonymous';
|
|
37
|
+
console.log(`🍄 Setting up Realtime notifications for ${agentId}...`);
|
|
38
|
+
|
|
39
|
+
supabaseClient = createClient(config.supabase_url, config.supabase_key, {
|
|
40
|
+
realtime: {
|
|
41
|
+
params: { eventsPerSecond: 10 }
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
realtimeChannel = supabaseClient
|
|
46
|
+
.channel('desktop-notifications')
|
|
47
|
+
.on(
|
|
48
|
+
'postgres_changes',
|
|
49
|
+
{
|
|
50
|
+
event: 'INSERT',
|
|
51
|
+
schema: 'public',
|
|
52
|
+
table: 'agent_messages',
|
|
53
|
+
filter: `to_agent=eq.${agentId}`
|
|
54
|
+
},
|
|
55
|
+
(payload) => {
|
|
56
|
+
const message = payload.new;
|
|
57
|
+
showNotification(message);
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
.subscribe((status, err) => {
|
|
61
|
+
if (status === 'SUBSCRIBED') {
|
|
62
|
+
console.log('✅ Connected to Supabase Realtime');
|
|
63
|
+
} else if (status === 'CHANNEL_ERROR') {
|
|
64
|
+
console.error('❌ Realtime channel error:', err);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Show native Electron notification
|
|
70
|
+
function showNotification(message) {
|
|
71
|
+
const preview = message.encrypted
|
|
72
|
+
? '🔒 Encrypted message'
|
|
73
|
+
: message.message?.substring(0, 100) || '';
|
|
74
|
+
|
|
75
|
+
const notification = new Notification({
|
|
76
|
+
title: `📬 ${message.from_agent}: ${message.subject}`,
|
|
77
|
+
body: preview,
|
|
78
|
+
silent: false,
|
|
79
|
+
urgency: 'normal'
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
notification.on('click', () => {
|
|
83
|
+
if (mainWindow) {
|
|
84
|
+
mainWindow.show();
|
|
85
|
+
mainWindow.focus();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
notification.show();
|
|
90
|
+
console.log(`📬 Notification: ${message.from_agent} - ${message.subject}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Wait for dashboard to be ready
|
|
94
|
+
function waitForDashboard(url, timeout = 15000) {
|
|
95
|
+
return new Promise((resolve, reject) => {
|
|
96
|
+
const startTime = Date.now();
|
|
97
|
+
|
|
98
|
+
const check = () => {
|
|
99
|
+
const http = require('http');
|
|
100
|
+
// Use 127.0.0.1 to match the server binding
|
|
101
|
+
const checkUrl = url.replace('localhost', '127.0.0.1');
|
|
102
|
+
const req = http.get(checkUrl, (res) => {
|
|
103
|
+
resolve(true);
|
|
104
|
+
});
|
|
105
|
+
req.on('error', () => {
|
|
106
|
+
if (Date.now() - startTime > timeout) {
|
|
107
|
+
reject(new Error('Dashboard startup timeout'));
|
|
108
|
+
} else {
|
|
109
|
+
setTimeout(check, 300);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
req.end();
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Give the server a moment to start
|
|
116
|
+
setTimeout(check, 500);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Start the dashboard server
|
|
121
|
+
function startDashboard() {
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
const mycmailCmd = process.platform === 'win32' ? 'mycmail.cmd' : 'mycmail';
|
|
124
|
+
|
|
125
|
+
console.log('🍄 Starting Myceliumail dashboard...');
|
|
126
|
+
|
|
127
|
+
dashboardProcess = spawn(mycmailCmd, ['dashboard'], {
|
|
128
|
+
env: { ...process.env },
|
|
129
|
+
shell: true,
|
|
130
|
+
detached: false
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
dashboardProcess.stdout.on('data', (data) => {
|
|
134
|
+
console.log(`Dashboard: ${data}`);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
dashboardProcess.stderr.on('data', (data) => {
|
|
138
|
+
console.error(`Dashboard error: ${data}`);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
dashboardProcess.on('error', (err) => {
|
|
142
|
+
console.error('Failed to start dashboard:', err);
|
|
143
|
+
reject(err);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
waitForDashboard(`http://localhost:${DASHBOARD_PORT}`)
|
|
147
|
+
.then(resolve)
|
|
148
|
+
.catch(reject);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function createWindow() {
|
|
153
|
+
mainWindow = new BrowserWindow({
|
|
154
|
+
width: 1200,
|
|
155
|
+
height: 800,
|
|
156
|
+
minWidth: 800,
|
|
157
|
+
minHeight: 600,
|
|
158
|
+
title: 'Myceliumail',
|
|
159
|
+
icon: path.join(__dirname, 'assets', 'icon.png'),
|
|
160
|
+
webPreferences: {
|
|
161
|
+
nodeIntegration: false,
|
|
162
|
+
contextIsolation: true,
|
|
163
|
+
preload: path.join(__dirname, 'preload.js')
|
|
164
|
+
},
|
|
165
|
+
titleBarStyle: 'hiddenInset',
|
|
166
|
+
backgroundColor: '#030712',
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
mainWindow.loadURL(`http://127.0.0.1:${DASHBOARD_PORT}`);
|
|
170
|
+
mainWindow.webContents.setZoomFactor(0.9);
|
|
171
|
+
|
|
172
|
+
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
|
173
|
+
shell.openExternal(url);
|
|
174
|
+
return { action: 'deny' };
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
mainWindow.on('closed', () => {
|
|
178
|
+
mainWindow = null;
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
mainWindow.on('close', (event) => {
|
|
182
|
+
if (!app.isQuitting) {
|
|
183
|
+
event.preventDefault();
|
|
184
|
+
mainWindow.hide();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function createTray() {
|
|
190
|
+
tray = new Tray(path.join(__dirname, 'assets', 'tray-icon.png'));
|
|
191
|
+
|
|
192
|
+
const contextMenu = Menu.buildFromTemplate([
|
|
193
|
+
{
|
|
194
|
+
label: 'Open Myceliumail',
|
|
195
|
+
click: () => mainWindow.show()
|
|
196
|
+
},
|
|
197
|
+
{ type: 'separator' },
|
|
198
|
+
{
|
|
199
|
+
label: 'Quit',
|
|
200
|
+
click: () => {
|
|
201
|
+
app.isQuitting = true;
|
|
202
|
+
app.quit();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
]);
|
|
206
|
+
|
|
207
|
+
tray.setToolTip('Myceliumail');
|
|
208
|
+
tray.setContextMenu(contextMenu);
|
|
209
|
+
|
|
210
|
+
tray.on('click', () => {
|
|
211
|
+
mainWindow.show();
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
app.whenReady().then(async () => {
|
|
216
|
+
try {
|
|
217
|
+
// Load config and setup notifications
|
|
218
|
+
const config = loadConfig();
|
|
219
|
+
setupRealtimeNotifications(config);
|
|
220
|
+
|
|
221
|
+
await startDashboard();
|
|
222
|
+
createWindow();
|
|
223
|
+
// createTray(); // Uncomment to enable tray icon
|
|
224
|
+
|
|
225
|
+
app.on('activate', () => {
|
|
226
|
+
if (mainWindow === null) {
|
|
227
|
+
createWindow();
|
|
228
|
+
} else {
|
|
229
|
+
mainWindow.show();
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
} catch (err) {
|
|
233
|
+
console.error('Failed to start:', err);
|
|
234
|
+
app.quit();
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
app.on('window-all-closed', () => {
|
|
239
|
+
if (process.platform !== 'darwin') {
|
|
240
|
+
app.quit();
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
app.on('before-quit', () => {
|
|
245
|
+
app.isQuitting = true;
|
|
246
|
+
|
|
247
|
+
// Cleanup realtime subscription
|
|
248
|
+
if (realtimeChannel && supabaseClient) {
|
|
249
|
+
supabaseClient.removeChannel(realtimeChannel);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Kill the dashboard process
|
|
253
|
+
if (dashboardProcess) {
|
|
254
|
+
console.log('Stopping dashboard...');
|
|
255
|
+
dashboardProcess.kill();
|
|
256
|
+
}
|
|
257
|
+
});
|