@agent-relay/dashboard-server 2.0.93 → 2.0.94
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/dist/routes/models.d.ts.map +1 -1
- package/dist/routes/models.js +39 -3
- package/dist/routes/models.js.map +1 -1
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +0 -1
- package/dist/services/index.js.map +1 -1
- package/dist/types/index.d.ts +0 -75
- package/dist/types/index.d.ts.map +1 -1
- package/dist/websocket/logs.d.ts +1 -25
- package/dist/websocket/logs.d.ts.map +1 -1
- package/dist/websocket/logs.js +0 -397
- package/dist/websocket/logs.js.map +1 -1
- package/out/404.html +1 -1
- package/out/_next/static/chunks/{3663-47290254b8f6f5dd.js → 3663-191a9aa9104061af.js} +1 -1
- package/out/_next/static/chunks/4201-d11188cf35739bff.js +1 -0
- package/out/_next/static/chunks/5787-f6fd7a3fbfe5eae6.js +73 -0
- package/out/_next/static/chunks/app/app/[[...slug]]/{page-c1376e695ba19e38.js → page-2b872f60e3d64014.js} +1 -1
- package/out/_next/static/chunks/app/{page-f2ebc7d0bc08e395.js → page-ca5511e5d65100a5.js} +1 -1
- package/out/about.html +1 -1
- package/out/about.txt +1 -1
- package/out/app/onboarding.html +1 -1
- package/out/app/onboarding.txt +1 -1
- package/out/app.html +1 -1
- package/out/app.txt +2 -2
- package/out/blog/go-to-bed-wake-up-to-a-finished-product.html +1 -1
- package/out/blog/go-to-bed-wake-up-to-a-finished-product.txt +1 -1
- package/out/blog/let-them-cook-multi-agent-orchestration.html +1 -1
- package/out/blog/let-them-cook-multi-agent-orchestration.txt +1 -1
- package/out/blog.html +1 -1
- package/out/blog.txt +1 -1
- package/out/careers.html +1 -1
- package/out/careers.txt +1 -1
- package/out/changelog.html +1 -1
- package/out/changelog.txt +1 -1
- package/out/cloud/link.html +1 -1
- package/out/cloud/link.txt +1 -1
- package/out/complete-profile.html +1 -1
- package/out/complete-profile.txt +1 -1
- package/out/connect-repos.html +1 -1
- package/out/connect-repos.txt +1 -1
- package/out/contact.html +1 -1
- package/out/contact.txt +1 -1
- package/out/dev/cli-tools.html +1 -1
- package/out/dev/cli-tools.txt +1 -1
- package/out/dev/log-viewer.html +1 -1
- package/out/dev/log-viewer.txt +1 -1
- package/out/docs.html +1 -1
- package/out/docs.txt +1 -1
- package/out/history.html +1 -1
- package/out/history.txt +2 -2
- package/out/index.html +1 -1
- package/out/index.txt +2 -2
- package/out/login.html +1 -1
- package/out/login.txt +1 -1
- package/out/metrics.html +1 -1
- package/out/metrics.txt +2 -2
- package/out/pricing.html +1 -1
- package/out/pricing.txt +1 -1
- package/out/privacy.html +1 -1
- package/out/privacy.txt +1 -1
- package/out/providers/setup/claude.html +1 -1
- package/out/providers/setup/claude.txt +1 -1
- package/out/providers/setup/codex.html +1 -1
- package/out/providers/setup/codex.txt +1 -1
- package/out/providers/setup/cursor.html +1 -1
- package/out/providers/setup/cursor.txt +1 -1
- package/out/providers.html +1 -1
- package/out/providers.txt +1 -1
- package/out/security.html +1 -1
- package/out/security.txt +1 -1
- package/out/signup.html +1 -1
- package/out/signup.txt +1 -1
- package/out/terms.html +1 -1
- package/out/terms.txt +1 -1
- package/package.json +6 -9
- package/dist/lib/attachment-storage.d.ts +0 -10
- package/dist/lib/attachment-storage.d.ts.map +0 -1
- package/dist/lib/attachment-storage.js +0 -53
- package/dist/lib/attachment-storage.js.map +0 -1
- package/dist/lib/broadcast.d.ts +0 -18
- package/dist/lib/broadcast.d.ts.map +0 -1
- package/dist/lib/broadcast.js +0 -118
- package/dist/lib/broadcast.js.map +0 -1
- package/dist/lib/channel-state.d.ts +0 -32
- package/dist/lib/channel-state.d.ts.map +0 -1
- package/dist/lib/channel-state.js +0 -146
- package/dist/lib/channel-state.js.map +0 -1
- package/dist/lib/cli-auth.d.ts +0 -40
- package/dist/lib/cli-auth.d.ts.map +0 -1
- package/dist/lib/cli-auth.js +0 -144
- package/dist/lib/cli-auth.js.map +0 -1
- package/dist/lib/data-assembly.d.ts +0 -136
- package/dist/lib/data-assembly.d.ts.map +0 -1
- package/dist/lib/data-assembly.js +0 -550
- package/dist/lib/data-assembly.js.map +0 -1
- package/dist/lib/server-state.d.ts +0 -115
- package/dist/lib/server-state.d.ts.map +0 -1
- package/dist/lib/server-state.js +0 -138
- package/dist/lib/server-state.js.map +0 -1
- package/dist/lib/websocket-runtime.d.ts +0 -17
- package/dist/lib/websocket-runtime.d.ts.map +0 -1
- package/dist/lib/websocket-runtime.js +0 -76
- package/dist/lib/websocket-runtime.js.map +0 -1
- package/dist/routes/auth.d.ts +0 -45
- package/dist/routes/auth.d.ts.map +0 -1
- package/dist/routes/auth.js +0 -261
- package/dist/routes/auth.js.map +0 -1
- package/dist/routes/channels-integrated.d.ts +0 -84
- package/dist/routes/channels-integrated.d.ts.map +0 -1
- package/dist/routes/channels-integrated.js +0 -644
- package/dist/routes/channels-integrated.js.map +0 -1
- package/dist/routes/decisions.d.ts +0 -31
- package/dist/routes/decisions.d.ts.map +0 -1
- package/dist/routes/decisions.js +0 -109
- package/dist/routes/decisions.js.map +0 -1
- package/dist/routes/fleet.d.ts +0 -24
- package/dist/routes/fleet.d.ts.map +0 -1
- package/dist/routes/fleet.js +0 -131
- package/dist/routes/fleet.js.map +0 -1
- package/dist/routes/history.d.ts +0 -13
- package/dist/routes/history.d.ts.map +0 -1
- package/dist/routes/history.js +0 -205
- package/dist/routes/history.js.map +0 -1
- package/dist/routes/messaging.d.ts +0 -34
- package/dist/routes/messaging.d.ts.map +0 -1
- package/dist/routes/messaging.js +0 -306
- package/dist/routes/messaging.js.map +0 -1
- package/dist/routes/settings.d.ts +0 -6
- package/dist/routes/settings.d.ts.map +0 -1
- package/dist/routes/settings.js +0 -119
- package/dist/routes/settings.js.map +0 -1
- package/dist/routes/spawn.d.ts +0 -75
- package/dist/routes/spawn.d.ts.map +0 -1
- package/dist/routes/spawn.js +0 -521
- package/dist/routes/spawn.js.map +0 -1
- package/dist/routes/system.d.ts +0 -21
- package/dist/routes/system.d.ts.map +0 -1
- package/dist/routes/system.js +0 -186
- package/dist/routes/system.js.map +0 -1
- package/dist/routes/tasks.d.ts +0 -27
- package/dist/routes/tasks.d.ts.map +0 -1
- package/dist/routes/tasks.js +0 -103
- package/dist/routes/tasks.js.map +0 -1
- package/dist/routes/ui.d.ts +0 -6
- package/dist/routes/ui.d.ts.map +0 -1
- package/dist/routes/ui.js +0 -114
- package/dist/routes/ui.js.map +0 -1
- package/dist/server.d.ts +0 -4
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -481
- package/dist/server.js.map +0 -1
- package/dist/services/broker-spawn-reader.d.ts +0 -40
- package/dist/services/broker-spawn-reader.d.ts.map +0 -1
- package/dist/services/broker-spawn-reader.js +0 -155
- package/dist/services/broker-spawn-reader.js.map +0 -1
- package/dist/services/user-bridge.d.ts +0 -155
- package/dist/services/user-bridge.d.ts.map +0 -1
- package/dist/services/user-bridge.js +0 -385
- package/dist/services/user-bridge.js.map +0 -1
- package/dist/websocket/bridge.d.ts +0 -12
- package/dist/websocket/bridge.d.ts.map +0 -1
- package/dist/websocket/bridge.js +0 -33
- package/dist/websocket/bridge.js.map +0 -1
- package/dist/websocket/main.d.ts +0 -15
- package/dist/websocket/main.d.ts.map +0 -1
- package/dist/websocket/main.js +0 -84
- package/dist/websocket/main.js.map +0 -1
- package/dist/websocket/presence.d.ts +0 -74
- package/dist/websocket/presence.d.ts.map +0 -1
- package/dist/websocket/presence.js +0 -330
- package/dist/websocket/presence.js.map +0 -1
- package/out/_next/static/chunks/270-8c0b8109123a0c5f.js +0 -73
- package/out/_next/static/chunks/5518-3b96a248632a79c0.js +0 -1
- /package/out/_next/static/{9CykW6n4dJn75_XoFVN_X → wgSCX8AQnjVl_Rnx1gUp5}/_buildManifest.js +0 -0
- /package/out/_next/static/{9CykW6n4dJn75_XoFVN_X → wgSCX8AQnjVl_Rnx1gUp5}/_ssgManifest.js +0 -0
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
import { WebSocket } from 'ws';
|
|
2
|
-
/**
|
|
3
|
-
* Presence WebSocket handler and channel/direct message broadcasters.
|
|
4
|
-
*/
|
|
5
|
-
export function setupPresenceWebSocket(deps) {
|
|
6
|
-
const { wss, wssPresence, mainMessageBuffer, onlineUsers, presenceHealth, broadcastPresence, isValidUsername, isValidAvatarUrl, getUserBridge, debug, } = deps;
|
|
7
|
-
// Helper to broadcast channel messages to all connected clients.
|
|
8
|
-
// Broadcasts to both main wss (local mode) and wssPresence (cloud mode).
|
|
9
|
-
const broadcastChannelMessage = (message) => {
|
|
10
|
-
// Push into buffer and wrap with sequence ID for replay support.
|
|
11
|
-
const rawPayload = JSON.stringify(message);
|
|
12
|
-
const seq = mainMessageBuffer.push('channel_message', rawPayload);
|
|
13
|
-
const payload = JSON.stringify({ seq, ...message });
|
|
14
|
-
// Broadcast to main WebSocket clients (local mode).
|
|
15
|
-
wss.clients.forEach((client) => {
|
|
16
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
17
|
-
client.send(payload);
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
// Also broadcast to presence WebSocket clients (cloud mode).
|
|
21
|
-
wssPresence.clients.forEach((client) => {
|
|
22
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
23
|
-
client.send(payload);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
// Helper to broadcast direct messages to all connected clients.
|
|
28
|
-
// This enables agent replies to appear in the dashboard UI.
|
|
29
|
-
const broadcastDirectMessage = (message) => {
|
|
30
|
-
// Push into buffer and wrap with sequence ID for replay support.
|
|
31
|
-
const rawPayload = JSON.stringify(message);
|
|
32
|
-
const seq = mainMessageBuffer.push('direct_message', rawPayload);
|
|
33
|
-
const payload = JSON.stringify({ seq, ...message });
|
|
34
|
-
// Broadcast to main WebSocket clients (local mode).
|
|
35
|
-
const mainClients = Array.from(wss.clients).filter((c) => c.readyState === WebSocket.OPEN);
|
|
36
|
-
debug(`[dashboard] Broadcasting direct_message to ${mainClients.length} main clients`);
|
|
37
|
-
wss.clients.forEach((client) => {
|
|
38
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
39
|
-
client.send(payload);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
const presenceClients = Array.from(wssPresence.clients).filter((c) => c.readyState === WebSocket.OPEN);
|
|
43
|
-
if (presenceClients.length > 0) {
|
|
44
|
-
debug(`[dashboard] Broadcasting direct_message to ${presenceClients.length} presence clients`);
|
|
45
|
-
wssPresence.clients.forEach((client) => {
|
|
46
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
47
|
-
client.send(payload);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
// Helper to get online users list (without ws references).
|
|
53
|
-
const getOnlineUsersList = () => {
|
|
54
|
-
return Array.from(onlineUsers.values()).map((state) => state.info);
|
|
55
|
-
};
|
|
56
|
-
// Heartbeat to detect dead connections (30 seconds).
|
|
57
|
-
const PRESENCE_HEARTBEAT_INTERVAL = 30000;
|
|
58
|
-
const presenceHeartbeat = setInterval(() => {
|
|
59
|
-
wssPresence.clients.forEach((ws) => {
|
|
60
|
-
const health = presenceHealth.get(ws);
|
|
61
|
-
if (!health) {
|
|
62
|
-
presenceHealth.set(ws, { isAlive: true });
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
if (!health.isAlive) {
|
|
66
|
-
ws.terminate();
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
health.isAlive = false;
|
|
70
|
-
ws.ping();
|
|
71
|
-
});
|
|
72
|
-
}, PRESENCE_HEARTBEAT_INTERVAL);
|
|
73
|
-
wssPresence.on('close', () => {
|
|
74
|
-
clearInterval(presenceHeartbeat);
|
|
75
|
-
});
|
|
76
|
-
wssPresence.on('connection', (ws) => {
|
|
77
|
-
// Initialize health tracking (no log - too noisy).
|
|
78
|
-
presenceHealth.set(ws, { isAlive: true });
|
|
79
|
-
ws.on('pong', () => {
|
|
80
|
-
const health = presenceHealth.get(ws);
|
|
81
|
-
if (health)
|
|
82
|
-
health.isAlive = true;
|
|
83
|
-
});
|
|
84
|
-
let clientUsername;
|
|
85
|
-
ws.on('message', (data) => {
|
|
86
|
-
try {
|
|
87
|
-
const msg = JSON.parse(data.toString());
|
|
88
|
-
if (msg.type === 'presence') {
|
|
89
|
-
if (msg.action === 'join' && typeof msg.user === 'object' && msg.user !== null && 'username' in msg.user) {
|
|
90
|
-
const user = msg.user;
|
|
91
|
-
const username = user.username;
|
|
92
|
-
const avatarUrl = user.avatarUrl;
|
|
93
|
-
// Validate inputs.
|
|
94
|
-
if (!isValidUsername(username)) {
|
|
95
|
-
console.warn(`[dashboard] Invalid username rejected: ${username}`);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
if (!isValidAvatarUrl(avatarUrl)) {
|
|
99
|
-
console.warn(`[dashboard] Invalid avatar URL rejected for user ${username}`);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
clientUsername = username;
|
|
103
|
-
const now = new Date().toISOString();
|
|
104
|
-
// Check if user already has connections (multi-tab support).
|
|
105
|
-
const existing = onlineUsers.get(username);
|
|
106
|
-
if (existing) {
|
|
107
|
-
// Add this connection to existing user.
|
|
108
|
-
existing.connections.add(ws);
|
|
109
|
-
existing.info.lastSeen = now;
|
|
110
|
-
// Update userBridge to use the new WebSocket for message delivery.
|
|
111
|
-
getUserBridge()?.updateWebSocket(username, ws);
|
|
112
|
-
// Only log at milestones to reduce noise.
|
|
113
|
-
const count = existing.connections.size;
|
|
114
|
-
if (count === 2 || count === 5 || count === 10 || count % 50 === 0) {
|
|
115
|
-
console.log(`[dashboard] User ${username} has ${count} connections`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
// New user - create presence state.
|
|
120
|
-
onlineUsers.set(username, {
|
|
121
|
-
info: {
|
|
122
|
-
username,
|
|
123
|
-
avatarUrl,
|
|
124
|
-
connectedAt: now,
|
|
125
|
-
lastSeen: now,
|
|
126
|
-
},
|
|
127
|
-
connections: new Set([ws]),
|
|
128
|
-
});
|
|
129
|
-
console.log(`[dashboard] User ${username} came online`);
|
|
130
|
-
// Register user for messaging.
|
|
131
|
-
getUserBridge()?.registerUser(username, ws, { avatarUrl }).catch((err) => {
|
|
132
|
-
console.error(`[dashboard] Failed to register user ${username} with relay:`, err);
|
|
133
|
-
});
|
|
134
|
-
// Broadcast join to all other clients (only for truly new users).
|
|
135
|
-
broadcastPresence({
|
|
136
|
-
type: 'presence_join',
|
|
137
|
-
user: {
|
|
138
|
-
username,
|
|
139
|
-
avatarUrl,
|
|
140
|
-
connectedAt: now,
|
|
141
|
-
lastSeen: now,
|
|
142
|
-
},
|
|
143
|
-
}, ws);
|
|
144
|
-
}
|
|
145
|
-
// Send current online users list to the new client.
|
|
146
|
-
ws.send(JSON.stringify({
|
|
147
|
-
type: 'presence_list',
|
|
148
|
-
users: getOnlineUsersList(),
|
|
149
|
-
}));
|
|
150
|
-
}
|
|
151
|
-
else if (msg.action === 'leave') {
|
|
152
|
-
// Security: Only allow leaving your own username. Must be authenticated first.
|
|
153
|
-
if (!clientUsername) {
|
|
154
|
-
console.warn('[dashboard] Security: Unauthenticated leave attempt');
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (msg.username !== clientUsername) {
|
|
158
|
-
console.warn(`[dashboard] Security: User ${clientUsername} tried to remove ${String(msg.username)}`);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
// Remove this connection from the user's set.
|
|
162
|
-
const username = clientUsername;
|
|
163
|
-
const userState = onlineUsers.get(username);
|
|
164
|
-
if (userState) {
|
|
165
|
-
userState.connections.delete(ws);
|
|
166
|
-
// Only broadcast leave if no more connections.
|
|
167
|
-
if (userState.connections.size === 0) {
|
|
168
|
-
onlineUsers.delete(username);
|
|
169
|
-
console.log(`[dashboard] User ${username} went offline`);
|
|
170
|
-
broadcastPresence({
|
|
171
|
-
type: 'presence_leave',
|
|
172
|
-
username,
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
console.log(`[dashboard] User ${username} closed tab (${userState.connections.size} remaining)`);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
else if (msg.type === 'typing') {
|
|
182
|
-
// Must have authenticated first.
|
|
183
|
-
if (!clientUsername) {
|
|
184
|
-
console.warn('[dashboard] Security: Unauthenticated typing attempt');
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
// Validate typing message comes from authenticated user.
|
|
188
|
-
if (msg.username !== clientUsername) {
|
|
189
|
-
console.warn('[dashboard] Security: Typing message username mismatch');
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
// Update last seen.
|
|
193
|
-
const username = clientUsername;
|
|
194
|
-
const userState = onlineUsers.get(username);
|
|
195
|
-
if (userState) {
|
|
196
|
-
userState.info.lastSeen = new Date().toISOString();
|
|
197
|
-
}
|
|
198
|
-
// Broadcast typing indicator to all other clients.
|
|
199
|
-
broadcastPresence({
|
|
200
|
-
type: 'typing',
|
|
201
|
-
username,
|
|
202
|
-
avatarUrl: userState?.info.avatarUrl,
|
|
203
|
-
isTyping: msg.isTyping,
|
|
204
|
-
}, ws);
|
|
205
|
-
}
|
|
206
|
-
else if (msg.type === 'channel_join') {
|
|
207
|
-
// Join a channel.
|
|
208
|
-
if (!clientUsername) {
|
|
209
|
-
console.warn('[dashboard] Security: Unauthenticated channel_join attempt');
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
if (!msg.channel || typeof msg.channel !== 'string') {
|
|
213
|
-
console.warn('[dashboard] Invalid channel_join: missing channel');
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
getUserBridge()?.joinChannel(clientUsername, msg.channel).then((success) => {
|
|
217
|
-
ws.send(JSON.stringify({
|
|
218
|
-
type: 'channel_joined',
|
|
219
|
-
channel: msg.channel,
|
|
220
|
-
success,
|
|
221
|
-
}));
|
|
222
|
-
}).catch((err) => {
|
|
223
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
224
|
-
console.error('[dashboard] Channel join error:', err);
|
|
225
|
-
ws.send(JSON.stringify({
|
|
226
|
-
type: 'channel_joined',
|
|
227
|
-
channel: msg.channel,
|
|
228
|
-
success: false,
|
|
229
|
-
error: message,
|
|
230
|
-
}));
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
else if (msg.type === 'channel_leave') {
|
|
234
|
-
// Leave a channel.
|
|
235
|
-
if (!clientUsername) {
|
|
236
|
-
console.warn('[dashboard] Security: Unauthenticated channel_leave attempt');
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
if (!msg.channel || typeof msg.channel !== 'string') {
|
|
240
|
-
console.warn('[dashboard] Invalid channel_leave: missing channel');
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
getUserBridge()?.leaveChannel(clientUsername, msg.channel).then((success) => {
|
|
244
|
-
ws.send(JSON.stringify({
|
|
245
|
-
type: 'channel_left',
|
|
246
|
-
channel: msg.channel,
|
|
247
|
-
success,
|
|
248
|
-
}));
|
|
249
|
-
}).catch((err) => {
|
|
250
|
-
console.error('[dashboard] Channel leave error:', err);
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
else if (msg.type === 'channel_message') {
|
|
254
|
-
// Send message to channel.
|
|
255
|
-
if (!clientUsername) {
|
|
256
|
-
console.warn('[dashboard] Security: Unauthenticated channel_message attempt');
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
if (!msg.channel || typeof msg.channel !== 'string') {
|
|
260
|
-
console.warn('[dashboard] Invalid channel_message: missing channel');
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
if (!msg.body || typeof msg.body !== 'string') {
|
|
264
|
-
console.warn('[dashboard] Invalid channel_message: missing body');
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
getUserBridge()?.sendChannelMessage(clientUsername, msg.channel, msg.body, {
|
|
268
|
-
thread: typeof msg.thread === 'string' ? msg.thread : undefined,
|
|
269
|
-
}).catch((err) => {
|
|
270
|
-
console.error('[dashboard] Channel message error:', err);
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
else if (msg.type === 'direct_message') {
|
|
274
|
-
// Send direct message to user or agent.
|
|
275
|
-
if (!clientUsername) {
|
|
276
|
-
console.warn('[dashboard] Security: Unauthenticated direct_message attempt');
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
if (!msg.to || typeof msg.to !== 'string') {
|
|
280
|
-
console.warn("[dashboard] Invalid direct_message: missing 'to'");
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
if (!msg.body || typeof msg.body !== 'string') {
|
|
284
|
-
console.warn('[dashboard] Invalid direct_message: missing body');
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
getUserBridge()?.sendDirectMessage(clientUsername, msg.to, msg.body, {
|
|
288
|
-
thread: typeof msg.thread === 'string' ? msg.thread : undefined,
|
|
289
|
-
}).catch((err) => {
|
|
290
|
-
console.error('[dashboard] Direct message error:', err);
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
catch (err) {
|
|
295
|
-
console.error('[dashboard] Invalid presence message:', err);
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
ws.on('error', (err) => {
|
|
299
|
-
console.error('[dashboard] Presence WebSocket client error:', err);
|
|
300
|
-
});
|
|
301
|
-
ws.on('close', () => {
|
|
302
|
-
// Clean up on disconnect with multi-tab support.
|
|
303
|
-
if (clientUsername) {
|
|
304
|
-
const userState = onlineUsers.get(clientUsername);
|
|
305
|
-
if (userState) {
|
|
306
|
-
userState.connections.delete(ws);
|
|
307
|
-
// Only broadcast leave if no more connections.
|
|
308
|
-
if (userState.connections.size === 0) {
|
|
309
|
-
onlineUsers.delete(clientUsername);
|
|
310
|
-
console.log(`[dashboard] User ${clientUsername} disconnected`);
|
|
311
|
-
// Unregister from messaging bridge.
|
|
312
|
-
getUserBridge()?.unregisterUser(clientUsername);
|
|
313
|
-
broadcastPresence({
|
|
314
|
-
type: 'presence_leave',
|
|
315
|
-
username: clientUsername,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
console.log(`[dashboard] User ${clientUsername} closed connection (${userState.connections.size} remaining)`);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
});
|
|
325
|
-
return {
|
|
326
|
-
broadcastChannelMessage,
|
|
327
|
-
broadcastDirectMessage,
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
//# sourceMappingURL=presence.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/websocket/presence.ts"],"names":[],"mappings":"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"}
|