agentgui 1.0.94 → 1.0.96

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.
@@ -160,6 +160,12 @@ class AgentGUIClient {
160
160
  this.startExecution();
161
161
  }
162
162
  });
163
+
164
+ this.ui.messageInput.addEventListener('input', () => {
165
+ const el = this.ui.messageInput;
166
+ el.style.height = 'auto';
167
+ el.style.height = Math.min(el.scrollHeight, 150) + 'px';
168
+ });
163
169
  }
164
170
 
165
171
  // Setup theme toggle
@@ -193,66 +199,42 @@ class AgentGUIClient {
193
199
  }
194
200
  }
195
201
 
196
- /**
197
- * Handle incoming WebSocket message
198
- */
199
202
  handleWebSocketMessage(data) {
200
203
  try {
201
- // Route by message type
202
204
  switch (data.type) {
203
205
  case 'streaming_start':
204
206
  this.handleStreamingStart(data);
205
207
  break;
206
-
207
208
  case 'streaming_progress':
208
- this.queueEvent(data);
209
+ this.handleStreamingProgress(data);
209
210
  break;
210
-
211
211
  case 'streaming_complete':
212
212
  this.handleStreamingComplete(data);
213
213
  break;
214
-
215
- case 'file_read':
216
- case 'file_write':
217
- case 'command_execute':
218
- case 'git_status':
219
- case 'error':
220
- case 'text_block':
221
- case 'code_block':
222
- case 'thinking_block':
223
- case 'tool_use':
224
- this.queueEvent(data);
214
+ case 'streaming_error':
215
+ this.handleStreamingError(data);
225
216
  break;
226
-
227
217
  case 'conversation_created':
228
218
  this.handleConversationCreated(data);
229
219
  break;
230
-
231
220
  case 'message_created':
232
221
  this.handleMessageCreated(data);
233
222
  break;
234
-
223
+ case 'queue_status':
224
+ this.handleQueueStatus(data);
225
+ break;
235
226
  default:
236
- console.log('Unhandled message type:', data.type);
227
+ break;
237
228
  }
238
229
  } catch (error) {
239
230
  console.error('Message handling error:', error);
240
231
  }
241
232
  }
242
233
 
243
- /**
244
- * Queue event for rendering
245
- */
246
234
  queueEvent(data) {
247
235
  try {
248
- // Process event
249
236
  const processed = this.eventProcessor.processEvent(data);
250
237
  if (!processed) return;
251
-
252
- // Queue for rendering
253
- this.renderer.queueEvent(processed);
254
-
255
- // Track session events
256
238
  if (data.sessionId && this.state.currentSession?.id === data.sessionId) {
257
239
  this.state.sessionEvents.push(processed);
258
240
  }
@@ -261,9 +243,6 @@ class AgentGUIClient {
261
243
  }
262
244
  }
263
245
 
264
- /**
265
- * Handle streaming start
266
- */
267
246
  handleStreamingStart(data) {
268
247
  console.log('Streaming started:', data);
269
248
  this.state.isStreaming = true;
@@ -273,60 +252,148 @@ class AgentGUIClient {
273
252
  agentId: data.agentId,
274
253
  startTime: Date.now()
275
254
  };
276
- this.state.currentConversation = { id: data.conversationId };
277
255
  this.state.sessionEvents = [];
256
+ this.state.streamingBlocks = [];
278
257
 
279
- // Auto-select the streaming conversation in the sidebar
280
- if (window.conversationManager) {
281
- window.conversationManager.select(data.conversationId);
258
+ if (this.wsManager.isConnected) {
259
+ this.wsManager.subscribeToSession(data.sessionId);
282
260
  }
283
261
 
284
- // Load the conversation to display it in real-time
285
- this.loadConversationMessages(data.conversationId).then(() => {
286
- // Clear output and prepare for streaming
287
- const outputEl = document.getElementById('output');
288
- if (outputEl) {
289
- outputEl.innerHTML = '';
262
+ const outputEl = document.getElementById('output');
263
+ if (outputEl) {
264
+ let messagesEl = outputEl.querySelector('.conversation-messages');
265
+ if (!messagesEl) {
266
+ outputEl.innerHTML = '<div class="conversation-messages"></div>';
267
+ messagesEl = outputEl.querySelector('.conversation-messages');
290
268
  }
291
- }).catch(err => {
292
- console.error('Failed to load conversation during streaming:', err);
293
- this.renderer.clear();
294
- });
295
-
296
- this.renderer.queueEvent({
297
- type: 'streaming_start',
298
- sessionId: data.sessionId,
299
- conversationId: data.conversationId,
300
- agentId: data.agentId,
301
- timestamp: data.timestamp || Date.now()
302
- });
269
+ const streamingDiv = document.createElement('div');
270
+ streamingDiv.className = 'message message-assistant streaming-message';
271
+ streamingDiv.id = `streaming-${data.sessionId}`;
272
+ streamingDiv.innerHTML = `
273
+ <div class="message-role">Assistant</div>
274
+ <div class="message-blocks streaming-blocks"></div>
275
+ <div class="streaming-indicator" style="display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0;color:var(--color-text-secondary);font-size:0.875rem;">
276
+ <span class="animate-spin" style="display:inline-block;width:1rem;height:1rem;border:2px solid var(--color-border);border-top-color:var(--color-primary);border-radius:50%;"></span>
277
+ Thinking...
278
+ </div>
279
+ `;
280
+ messagesEl.appendChild(streamingDiv);
281
+ this.scrollToBottom();
282
+ }
303
283
 
304
284
  this.disableControls();
305
285
  this.emit('streaming:start', data);
306
286
  }
307
287
 
308
- /**
309
- * Handle streaming complete
310
- */
288
+ handleStreamingProgress(data) {
289
+ if (!data.block) return;
290
+
291
+ const block = data.block;
292
+ if (!this.state.streamingBlocks) this.state.streamingBlocks = [];
293
+ this.state.streamingBlocks.push(block);
294
+
295
+ const sessionId = data.sessionId || this.state.currentSession?.id;
296
+ const streamingEl = document.getElementById(`streaming-${sessionId}`);
297
+ if (!streamingEl) return;
298
+
299
+ const blocksEl = streamingEl.querySelector('.streaming-blocks');
300
+ if (!blocksEl) return;
301
+
302
+ const indicator = streamingEl.querySelector('.streaming-indicator');
303
+
304
+ if (block.type === 'text' && block.text) {
305
+ const existingTextEl = blocksEl.querySelector('.streaming-text-current');
306
+ if (existingTextEl && !data.isResult) {
307
+ existingTextEl.innerHTML = this.renderBlockContent(block);
308
+ } else {
309
+ const div = document.createElement('div');
310
+ div.className = 'message-text streaming-text-current';
311
+ div.innerHTML = this.renderBlockContent(block);
312
+ blocksEl.appendChild(div);
313
+ }
314
+ } else if (block.type === 'tool_use') {
315
+ const prevTextEl = blocksEl.querySelector('.streaming-text-current');
316
+ if (prevTextEl) prevTextEl.classList.remove('streaming-text-current');
317
+
318
+ const div = document.createElement('div');
319
+ div.className = 'message-tool';
320
+ div.textContent = `[Tool: ${block.name || 'unknown'}]`;
321
+ blocksEl.appendChild(div);
322
+ } else if (block.type === 'tool_result') {
323
+ const div = document.createElement('div');
324
+ div.className = 'message-text';
325
+ div.innerHTML = `<em style="color:var(--color-text-secondary)">${this.escapeHtml(String(block.result || '').substring(0, 500))}</em>`;
326
+ blocksEl.appendChild(div);
327
+ }
328
+
329
+ if (indicator) indicator.querySelector('span:last-child')?.remove();
330
+ if (indicator) {
331
+ const label = document.createElement('span');
332
+ label.textContent = block.type === 'tool_use' ? `Using ${block.name}...` : 'Responding...';
333
+ indicator.appendChild(label);
334
+ }
335
+
336
+ this.scrollToBottom();
337
+ }
338
+
339
+ renderBlockContent(block) {
340
+ if (block.type === 'text' && block.text) {
341
+ const text = block.text;
342
+ if (text.includes('<') && (text.includes('</') || text.includes('/>'))) {
343
+ return text;
344
+ }
345
+ return this.escapeHtml(text);
346
+ }
347
+ return this.escapeHtml(JSON.stringify(block));
348
+ }
349
+
350
+ scrollToBottom() {
351
+ const scrollContainer = document.getElementById('output-scroll');
352
+ if (scrollContainer) {
353
+ requestAnimationFrame(() => {
354
+ scrollContainer.scrollTop = scrollContainer.scrollHeight;
355
+ });
356
+ }
357
+ }
358
+
359
+ handleStreamingError(data) {
360
+ console.error('Streaming error:', data);
361
+ this.state.isStreaming = false;
362
+
363
+ const sessionId = data.sessionId || this.state.currentSession?.id;
364
+ const streamingEl = document.getElementById(`streaming-${sessionId}`);
365
+ if (streamingEl) {
366
+ const indicator = streamingEl.querySelector('.streaming-indicator');
367
+ if (indicator) {
368
+ indicator.innerHTML = `<span style="color:var(--color-error);">Error: ${this.escapeHtml(data.error || 'Unknown error')}</span>`;
369
+ }
370
+ }
371
+
372
+ this.enableControls();
373
+ this.emit('streaming:error', data);
374
+ }
375
+
311
376
  handleStreamingComplete(data) {
312
377
  console.log('Streaming completed:', data);
313
378
  this.state.isStreaming = false;
314
379
 
315
- const duration = data.duration || (Date.now() - (this.state.currentSession?.startTime || Date.now()));
316
-
317
- this.renderer.queueEvent({
318
- type: 'streaming_complete',
319
- sessionId: data.sessionId,
320
- duration,
321
- timestamp: data.timestamp || Date.now()
322
- });
380
+ const sessionId = data.sessionId || this.state.currentSession?.id;
381
+ const streamingEl = document.getElementById(`streaming-${sessionId}`);
382
+ if (streamingEl) {
383
+ const indicator = streamingEl.querySelector('.streaming-indicator');
384
+ if (indicator) indicator.remove();
385
+ streamingEl.classList.remove('streaming-message');
386
+ const prevTextEl = streamingEl.querySelector('.streaming-text-current');
387
+ if (prevTextEl) prevTextEl.classList.remove('streaming-text-current');
388
+
389
+ const ts = document.createElement('div');
390
+ ts.className = 'message-timestamp';
391
+ ts.textContent = new Date().toLocaleString();
392
+ streamingEl.appendChild(ts);
393
+ }
323
394
 
324
395
  this.enableControls();
325
- this.emit('streaming:complete', {
326
- ...data,
327
- duration,
328
- eventCount: this.state.sessionEvents.length
329
- });
396
+ this.emit('streaming:complete', data);
330
397
  }
331
398
 
332
399
  /**
@@ -339,32 +406,55 @@ class AgentGUIClient {
339
406
  }
340
407
  }
341
408
 
342
- /**
343
- * Handle message created
344
- */
345
409
  handleMessageCreated(data) {
346
- // If the message is for the currently displayed conversation, append it to the output
347
- if (data.conversationId === this.state.currentConversation?.id && data.message) {
348
- const outputEl = document.querySelector('.conversation-messages');
349
- if (outputEl) {
350
- const messageHtml = `
351
- <div class="message message-${data.message.role}">
352
- <div class="message-role">${data.message.role.charAt(0).toUpperCase() + data.message.role.slice(1)}</div>
353
- ${this.renderMessageContent(data.message.content)}
354
- <div class="message-timestamp">${new Date(data.message.created_at).toLocaleString()}</div>
355
- </div>
356
- `;
357
- outputEl.insertAdjacentHTML('beforeend', messageHtml);
358
- // Scroll to bottom
359
- const scrollContainer = document.getElementById('output-scroll');
360
- if (scrollContainer) {
361
- scrollContainer.scrollTop = scrollContainer.scrollHeight;
362
- }
363
- }
410
+ if (data.conversationId !== this.state.currentConversation?.id || !data.message) {
411
+ this.emit('message:created', data);
412
+ return;
413
+ }
414
+
415
+ if (data.message.role === 'assistant' && this.state.isStreaming) {
416
+ this.emit('message:created', data);
417
+ return;
418
+ }
419
+
420
+ const outputEl = document.querySelector('.conversation-messages');
421
+ if (!outputEl) {
422
+ this.emit('message:created', data);
423
+ return;
364
424
  }
425
+
426
+ const messageHtml = `
427
+ <div class="message message-${data.message.role}" data-msg-id="${data.message.id}">
428
+ <div class="message-role">${data.message.role.charAt(0).toUpperCase() + data.message.role.slice(1)}</div>
429
+ ${this.renderMessageContent(data.message.content)}
430
+ <div class="message-timestamp">${new Date(data.message.created_at).toLocaleString()}</div>
431
+ </div>
432
+ `;
433
+ outputEl.insertAdjacentHTML('beforeend', messageHtml);
434
+ this.scrollToBottom();
365
435
  this.emit('message:created', data);
366
436
  }
367
437
 
438
+ handleQueueStatus(data) {
439
+ if (data.conversationId !== this.state.currentConversation?.id) return;
440
+
441
+ const outputEl = document.querySelector('.conversation-messages');
442
+ if (!outputEl) return;
443
+
444
+ let queueEl = outputEl.querySelector('.queue-indicator');
445
+ if (data.queueLength > 0) {
446
+ if (!queueEl) {
447
+ queueEl = document.createElement('div');
448
+ queueEl.className = 'queue-indicator';
449
+ queueEl.style.cssText = 'padding:0.5rem 1rem;margin:0.5rem 0;border-radius:0.375rem;background:var(--color-warning);color:#000;font-size:0.875rem;text-align:center;';
450
+ outputEl.appendChild(queueEl);
451
+ }
452
+ queueEl.textContent = `${data.queueLength} message${data.queueLength > 1 ? 's' : ''} queued`;
453
+ } else if (queueEl) {
454
+ queueEl.remove();
455
+ }
456
+ }
457
+
368
458
  /**
369
459
  * Parse markdown code blocks from text
370
460
  * Returns array of parts with type ('text' or 'code') and content/language/code
@@ -476,15 +566,7 @@ class AgentGUIClient {
476
566
  }
477
567
  }
478
568
 
479
- /**
480
- * Start execution
481
- */
482
569
  async startExecution() {
483
- if (this.state.isStreaming) {
484
- this.showError('Streaming already in progress');
485
- return;
486
- }
487
-
488
570
  const prompt = this.ui.messageInput?.value || '';
489
571
  const agentId = this.ui.agentSelector?.value || 'claude-code';
490
572
 
@@ -493,23 +575,31 @@ class AgentGUIClient {
493
575
  return;
494
576
  }
495
577
 
496
- try {
497
- this.disableControls();
578
+ if (this.ui.messageInput) {
579
+ this.ui.messageInput.value = '';
580
+ this.ui.messageInput.style.height = 'auto';
581
+ }
498
582
 
499
- const response = await fetch(window.__BASE_URL + '/api/conversations', {
500
- method: 'POST',
501
- headers: { 'Content-Type': 'application/json' },
502
- body: JSON.stringify({
503
- agentId,
504
- title: prompt.substring(0, 50)
505
- })
506
- });
583
+ try {
584
+ if (this.state.currentConversation?.id) {
585
+ await this.streamToConversation(this.state.currentConversation.id, prompt, agentId);
586
+ } else {
587
+ this.disableControls();
588
+ const response = await fetch(window.__BASE_URL + '/api/conversations', {
589
+ method: 'POST',
590
+ headers: { 'Content-Type': 'application/json' },
591
+ body: JSON.stringify({ agentId, title: prompt.substring(0, 50) })
592
+ });
593
+ const { conversation } = await response.json();
594
+ this.state.currentConversation = conversation;
507
595
 
508
- const { conversation } = await response.json();
509
- this.state.currentConversation = conversation;
596
+ if (window.conversationManager) {
597
+ window.conversationManager.loadConversations();
598
+ window.conversationManager.select(conversation.id);
599
+ }
510
600
 
511
- // Start streaming
512
- await this.streamToConversation(conversation.id, prompt, agentId);
601
+ await this.streamToConversation(conversation.id, prompt, agentId);
602
+ }
513
603
  } catch (error) {
514
604
  console.error('Execution error:', error);
515
605
  this.showError('Failed to start execution: ' + error.message);
@@ -517,33 +607,32 @@ class AgentGUIClient {
517
607
  }
518
608
  }
519
609
 
520
- /**
521
- * Stream execution to conversation
522
- */
523
610
  async streamToConversation(conversationId, prompt, agentId) {
524
611
  try {
612
+ if (this.wsManager.isConnected) {
613
+ this.wsManager.sendMessage({ type: 'subscribe', conversationId });
614
+ }
615
+
525
616
  const response = await fetch(`${window.__BASE_URL}/api/conversations/${conversationId}/stream`, {
526
617
  method: 'POST',
527
618
  headers: { 'Content-Type': 'application/json' },
528
- body: JSON.stringify({
529
- content: prompt,
530
- agentId,
531
- skipPermissions: false
532
- })
619
+ body: JSON.stringify({ content: prompt, agentId, skipPermissions: false })
533
620
  });
534
621
 
535
- if (!response.ok) {
536
- throw new Error(`HTTP ${response.status}`);
537
- }
622
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
538
623
 
539
- const { session, streamId } = await response.json();
624
+ const result = await response.json();
540
625
 
541
- // Subscribe to session events via WebSocket
542
- if (this.wsManager.isConnected) {
543
- this.wsManager.subscribeToSession(session.id);
626
+ if (result.queued) {
627
+ console.log('Message queued, position:', result.queuePosition);
628
+ return;
629
+ }
630
+
631
+ if (result.session && this.wsManager.isConnected) {
632
+ this.wsManager.subscribeToSession(result.session.id);
544
633
  }
545
634
 
546
- this.emit('execution:started', { session, streamId });
635
+ this.emit('execution:started', result);
547
636
  } catch (error) {
548
637
  console.error('Stream execution error:', error);
549
638
  this.showError('Failed to stream execution: ' + error.message);
@@ -675,37 +764,33 @@ class AgentGUIClient {
675
764
  }
676
765
  }
677
766
 
678
- /**
679
- * Load and display conversation messages
680
- */
681
767
  async loadConversationMessages(conversationId) {
682
768
  try {
683
- this.state.currentConversation = { id: conversationId };
684
-
685
- // Fetch conversation details
686
769
  const convResponse = await fetch(window.__BASE_URL + `/api/conversations/${conversationId}`);
687
770
  const { conversation } = await convResponse.json();
771
+ this.state.currentConversation = conversation;
688
772
 
689
- // Fetch messages
690
- const messagesResponse = await fetch(window.__BASE_URL + `/api/conversations/${conversationId}/messages`);
691
- if (!messagesResponse.ok) {
692
- throw new Error(`Failed to fetch messages: ${messagesResponse.status}`);
773
+ if (this.wsManager.isConnected) {
774
+ this.wsManager.sendMessage({ type: 'subscribe', conversationId });
693
775
  }
776
+
777
+ const messagesResponse = await fetch(window.__BASE_URL + `/api/conversations/${conversationId}/messages`);
778
+ if (!messagesResponse.ok) throw new Error(`Failed to fetch messages: ${messagesResponse.status}`);
694
779
  const messagesData = await messagesResponse.json();
695
780
 
696
- // Clear output and display conversation header
697
781
  const outputEl = document.getElementById('output');
698
782
  if (outputEl) {
699
- const wdInfo = conversation.workingDirectory ? ` ${this.escapeHtml(conversation.workingDirectory)}` : '';
783
+ const wdInfo = conversation.workingDirectory ? ` - ${this.escapeHtml(conversation.workingDirectory)}` : '';
700
784
  outputEl.innerHTML = `
701
785
  <div class="conversation-header">
702
786
  <h2>${this.escapeHtml(conversation.title || 'Conversation')}</h2>
703
- <p class="text-secondary">${conversation.agentType || 'unknown'} ${new Date(conversation.created_at).toLocaleDateString()}${wdInfo}</p>
787
+ <p class="text-secondary">${conversation.agentType || 'unknown'} - ${new Date(conversation.created_at).toLocaleDateString()}${wdInfo}</p>
704
788
  </div>
705
789
  <div class="conversation-messages">
706
790
  ${this.renderMessages(messagesData.messages || [])}
707
791
  </div>
708
792
  `;
793
+ this.scrollToBottom();
709
794
  }
710
795
  } catch (error) {
711
796
  console.error('Failed to load conversation messages:', error);
@@ -10,36 +10,39 @@
10
10
  let dragCounter = 0;
11
11
 
12
12
  function init() {
13
- setupHamburgerMenu();
13
+ setupSidebarToggle();
14
14
  setupDragAndDrop();
15
15
  setupViewToggle();
16
16
  setupConversationListener();
17
17
  }
18
18
 
19
- // --- Hamburger Menu & Mobile Sidebar ---
20
- function setupHamburgerMenu() {
21
- const hamburger = document.querySelector('[data-hamburger]');
22
- const sidebar = document.querySelector('[data-sidebar]');
23
- const overlay = document.querySelector('[data-sidebar-overlay]');
19
+ function setupSidebarToggle() {
20
+ var toggleBtn = document.querySelector('[data-sidebar-toggle]');
21
+ var sidebar = document.querySelector('[data-sidebar]');
22
+ var overlay = document.querySelector('[data-sidebar-overlay]');
24
23
 
25
- if (!hamburger || !sidebar) return;
24
+ if (!sidebar) return;
26
25
 
27
- hamburger.addEventListener('click', function(e) {
28
- e.stopPropagation();
29
- const isOpen = sidebar.classList.contains('mobile-visible');
30
- if (isOpen) {
31
- closeSidebar();
26
+ var savedState = localStorage.getItem('sidebar-collapsed');
27
+ if (savedState === 'true' && window.innerWidth > 768) {
28
+ sidebar.classList.add('collapsed');
29
+ }
30
+
31
+ function isMobile() { return window.innerWidth <= 768; }
32
+
33
+ function toggleSidebar() {
34
+ if (isMobile()) {
35
+ var isOpen = sidebar.classList.contains('mobile-visible');
36
+ if (isOpen) { closeSidebar(); } else { openSidebar(); }
32
37
  } else {
33
- openSidebar();
38
+ sidebar.classList.toggle('collapsed');
39
+ localStorage.setItem('sidebar-collapsed', sidebar.classList.contains('collapsed'));
34
40
  }
35
- });
36
-
37
- if (overlay) {
38
- overlay.addEventListener('click', closeSidebar);
39
41
  }
40
42
 
41
43
  function openSidebar() {
42
44
  sidebar.classList.add('mobile-visible');
45
+ sidebar.classList.remove('collapsed');
43
46
  if (overlay) overlay.classList.add('visible');
44
47
  }
45
48
 
@@ -48,17 +51,32 @@
48
51
  if (overlay) overlay.classList.remove('visible');
49
52
  }
50
53
 
51
- // Close sidebar when conversation is selected (mobile)
52
- window.addEventListener('conversation-selected', function() {
53
- if (window.innerWidth <= 768) {
54
- closeSidebar();
54
+ if (toggleBtn) {
55
+ toggleBtn.addEventListener('click', function(e) {
56
+ e.stopPropagation();
57
+ toggleSidebar();
58
+ });
59
+ }
60
+
61
+ if (overlay) {
62
+ overlay.addEventListener('click', closeSidebar);
63
+ }
64
+
65
+ document.addEventListener('keydown', function(e) {
66
+ if ((e.ctrlKey || e.metaKey) && e.key === 'b') {
67
+ e.preventDefault();
68
+ toggleSidebar();
55
69
  }
56
70
  });
57
71
 
58
- // Close sidebar on window resize to desktop
72
+ window.addEventListener('conversation-selected', function() {
73
+ if (isMobile()) closeSidebar();
74
+ });
75
+
59
76
  window.addEventListener('resize', function() {
60
- if (window.innerWidth > 768) {
61
- closeSidebar();
77
+ if (!isMobile()) {
78
+ sidebar.classList.remove('mobile-visible');
79
+ if (overlay) overlay.classList.remove('visible');
62
80
  }
63
81
  });
64
82
  }
@@ -175,7 +193,7 @@
175
193
  currentView = view;
176
194
  var bar = document.getElementById('viewToggleBar');
177
195
  var chatArea = document.getElementById('output-scroll');
178
- var execPanel = document.querySelector('.execution-panel');
196
+ var execPanel = document.querySelector('.input-section');
179
197
  var fileBrowser = document.getElementById('fileBrowserContainer');
180
198
  var iframe = document.getElementById('fileBrowserIframe');
181
199
 
@@ -50,7 +50,7 @@ class WebSocketManager {
50
50
  getWebSocketURL() {
51
51
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
52
52
  const baseURL = window.__BASE_URL || '/gm';
53
- return `${protocol}//${window.location.host}${baseURL}/ws`;
53
+ return `${protocol}//${window.location.host}${baseURL}/sync`;
54
54
  }
55
55
 
56
56
  /**