watercooler 0.0.8 → 0.0.9

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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/public/app.js +12 -17
  3. package/server.ts +22 -22
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "watercooler",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "A beautiful 3D visualization of your mailbox messages as a village of coworkers",
5
5
  "type": "module",
6
6
  "main": "server.ts",
package/public/app.js CHANGED
@@ -9,7 +9,7 @@ let config = { user: '', mailbox: '', avatar: null };
9
9
  let messages = []; // Messages TO user (for main panel)
10
10
  let allMessages = []; // All messages involving user (for desk dialogs)
11
11
  let recipients = [];
12
- let avatarStates = {}; // Map of name -> {tool_name, timestamp}
12
+ let statusStates = {}; // Map of name -> {tool_name, timestamp}
13
13
  let scene, camera, renderer, controls;
14
14
  let agentMeshes = new Map();
15
15
  let connectionLines = [];
@@ -980,14 +980,9 @@ function updateVillage() {
980
980
  clearConnections();
981
981
 
982
982
  // Use recipients (from coworkers.db) as the authoritative list of agents
983
+ // Only show people in the coworker list, not random message senders
983
984
  const allAgents = new Set([config.user.toLowerCase(), ...recipients.map(r => r.toLowerCase())]);
984
985
 
985
- // Also add message participants
986
- messages.forEach(m => {
987
- allAgents.add(m.sender.toLowerCase());
988
- allAgents.add(m.recipient.toLowerCase());
989
- });
990
-
991
986
  // Arrange agents in a circle on the platform
992
987
  const agents = Array.from(allAgents);
993
988
  const radius = Math.min(20, Math.max(10, agents.length * 3));
@@ -998,8 +993,8 @@ function updateVillage() {
998
993
  const z = Math.sin(angle) * radius;
999
994
  const position = new THREE.Vector3(x, 0, z);
1000
995
 
1001
- const avatarState = avatarStates[agent.toLowerCase()];
1002
- const toolName = avatarState?.tool_name || null;
996
+ const statusState = statusStates[agent.toLowerCase()];
997
+ const toolName = statusState?.tool_name || null;
1003
998
 
1004
999
  if (!agentMeshes.has(agent)) {
1005
1000
  const group = createAgentDesk(agent, position, toolName);
@@ -1163,14 +1158,14 @@ async function loadData() {
1163
1158
  recipients = Array.isArray(recipientsData) ? recipientsData : [];
1164
1159
  allMessages = Array.isArray(allMessagesData) ? allMessagesData : [];
1165
1160
 
1166
- // Load avatar states if avatar DB is configured
1167
- if (config.avatar) {
1161
+ // Load status states if status DB is configured
1162
+ if (config.status) {
1168
1163
  try {
1169
- const avatarsRes = await fetch('/api/avatars');
1170
- avatarStates = await avatarsRes.json();
1164
+ const statusRes = await fetch('/api/status');
1165
+ statusStates = await statusRes.json();
1171
1166
  } catch (err) {
1172
- console.error('Error loading avatar states:', err);
1173
- avatarStates = {};
1167
+ console.error('Error loading status states:', err);
1168
+ statusStates = {};
1174
1169
  }
1175
1170
  }
1176
1171
 
@@ -1537,8 +1532,8 @@ function updateDeskLabels() {
1537
1532
  !m.read
1538
1533
  ).length;
1539
1534
 
1540
- const avatarState = avatarStates[name.toLowerCase()];
1541
- const toolName = avatarState?.tool_name || null;
1535
+ const statusState = statusStates[name.toLowerCase()];
1536
+ const toolName = statusState?.tool_name || null;
1542
1537
 
1543
1538
  const sprite = group.children.find(c => c.isSprite);
1544
1539
  if (sprite) {
package/server.ts CHANGED
@@ -13,7 +13,7 @@ const args = process.argv.slice(2);
13
13
  let user: string | null = null;
14
14
  let mailboxPath: string | null = null;
15
15
  let coworkerPath: string | null = null;
16
- let avatarPath: string | null = null;
16
+ let statusPath: string | null = null;
17
17
  let port: number = parseInt(process.env.PORT || '3000', 10);
18
18
  let host: string = process.env.HOST || '0.0.0.0';
19
19
 
@@ -24,8 +24,8 @@ for (let i = 0; i < args.length; i++) {
24
24
  mailboxPath = args[++i];
25
25
  } else if (args[i] === '--coworkers' || args[i] === '-c') {
26
26
  coworkerPath = args[++i];
27
- } else if (args[i] === '--avatars' || args[i] === '-a') {
28
- avatarPath = args[++i];
27
+ } else if (args[i] === '--status' || args[i] === '-s') {
28
+ statusPath = args[++i];
29
29
  } else if (args[i] === '--port' || args[i] === '-p') {
30
30
  const p = parseInt(args[++i], 10);
31
31
  if (!isNaN(p)) port = p;
@@ -35,7 +35,7 @@ for (let i = 0; i < args.length; i++) {
35
35
  }
36
36
 
37
37
  if (!user || !mailboxPath) {
38
- console.error('Usage: watercooler --user <name> --mailbox <path> [--coworkers <path>] [--avatars <path>] [--port <number>] [--host <address>]');
38
+ console.error('Usage: watercooler --user <name> --mailbox <path> [--coworkers <path>] [--status <path>] [--port <number>] [--host <address>]');
39
39
  process.exit(1);
40
40
  }
41
41
 
@@ -44,15 +44,15 @@ console.log(` Mailbox: ${mailboxPath}`);
44
44
  if (coworkerPath) {
45
45
  console.log(` Coworker DB: ${coworkerPath}`);
46
46
  }
47
- if (avatarPath) {
48
- console.log(` Avatar DB: ${avatarPath}`);
47
+ if (statusPath) {
48
+ console.log(` Status DB: ${statusPath}`);
49
49
  }
50
50
  console.log(` URL: http://${host}:${port}`);
51
51
 
52
52
  // Databases
53
53
  let db: Database.Database | null = null;
54
54
  let coworkerDb: Database.Database | null = null;
55
- let avatarDb: Database.Database | null = null;
55
+ let statusDb: Database.Database | null = null;
56
56
 
57
57
  try {
58
58
  db = new Database(mailboxPath);
@@ -71,12 +71,12 @@ if (coworkerPath) {
71
71
  }
72
72
  }
73
73
 
74
- if (avatarPath) {
74
+ if (statusPath) {
75
75
  try {
76
- avatarDb = new Database(avatarPath);
77
- console.log(' Avatar DB: connected');
76
+ statusDb = new Database(statusPath);
77
+ console.log(' Status DB: connected');
78
78
  } catch (err: any) {
79
- console.warn(' Avatar DB error:', err.message);
79
+ console.warn(' Status DB error:', err.message);
80
80
  }
81
81
  }
82
82
 
@@ -247,16 +247,16 @@ app.post('/api/messages/:id/read', (req, res) => {
247
247
  }
248
248
  });
249
249
 
250
- // API: Get avatar states (latest tool usage per coworker)
251
- app.get('/api/avatars', (req, res) => {
250
+ // API: Get status states (latest tool usage per coworker)
251
+ app.get('/api/status', (req, res) => {
252
252
  try {
253
- if (!avatarDb) {
253
+ if (!statusDb) {
254
254
  res.json({});
255
255
  return;
256
256
  }
257
257
 
258
258
  // Check if latest_tool_usage table exists
259
- const tableCheck = avatarDb.prepare(`
259
+ const tableCheck = statusDb.prepare(`
260
260
  SELECT name FROM sqlite_master
261
261
  WHERE type='table' AND name='latest_tool_usage'
262
262
  `).get();
@@ -267,7 +267,7 @@ app.get('/api/avatars', (req, res) => {
267
267
  }
268
268
 
269
269
  // Get latest tool usage per name
270
- const stmt = avatarDb.prepare(`
270
+ const stmt = statusDb.prepare(`
271
271
  SELECT name, tool_name, timestamp
272
272
  FROM latest_tool_usage
273
273
  ORDER BY timestamp DESC
@@ -276,26 +276,26 @@ app.get('/api/avatars', (req, res) => {
276
276
  const rows = stmt.all() as Array<{name: string; tool_name: string; timestamp: number}>;
277
277
 
278
278
  // Build map of name -> latest tool (first occurrence is latest due to ORDER BY)
279
- const avatarStates: Record<string, {tool_name: string; timestamp: number}> = {};
279
+ const statusStates: Record<string, {tool_name: string; timestamp: number}> = {};
280
280
  for (const row of rows) {
281
- if (!avatarStates[row.name]) {
282
- avatarStates[row.name] = {
281
+ if (!statusStates[row.name]) {
282
+ statusStates[row.name] = {
283
283
  tool_name: row.tool_name,
284
284
  timestamp: row.timestamp
285
285
  };
286
286
  }
287
287
  }
288
288
 
289
- res.json(avatarStates);
289
+ res.json(statusStates);
290
290
  } catch (err: any) {
291
- console.error('Error in /api/avatars:', err.message);
291
+ console.error('Error in /api/status:', err.message);
292
292
  res.status(500).json({ error: err.message });
293
293
  }
294
294
  });
295
295
 
296
296
  // Config endpoint
297
297
  app.get('/api/config', (req, res) => {
298
- res.json({ user, mailbox: mailboxPath, coworker: coworkerPath, avatar: avatarPath });
298
+ res.json({ user, mailbox: mailboxPath, coworker: coworkerPath, status: statusPath });
299
299
  });
300
300
 
301
301
  app.listen(port, host, () => {