Skip to content

Commit 3c4dbe4

Browse files
authored
browserOS websocket agent - fixes (#160)
* websocket agent: keep only thinking, responses message for conciseness * update starting messages * configurable glow update * fix: glow service
1 parent 630d341 commit 3c4dbe4

File tree

3 files changed

+165
-74
lines changed

3 files changed

+165
-74
lines changed

src/content/glow-animation.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
const GLOW_STYLES_ID = 'nxtscape-glow-styles'
99
const GLOW_INITIALIZED_KEY = 'nxtscape-glow-initialized'
1010
const GLOW_ENABLED_KEY = 'nxtscape-glow-enabled' // Stored in chrome.storage.local
11+
12+
// Glow thickness controls - adjust these to change glow intensity
13+
const GLOW_THICKNESS = 1.0 // Multiplier for all glow values (0.5 = thinner, 1.5 = thicker)
14+
const GLOW_OPACITY = 0.6 // Final opacity of the glow overlay (0.0 - 1.0)
1115

1216
// Check if already initialized to prevent duplicate listeners
1317
if ((window as any)[GLOW_INITIALIZED_KEY]) {
@@ -23,39 +27,42 @@
2327
if (document.getElementById(GLOW_STYLES_ID)) {
2428
return
2529
}
26-
30+
31+
// Calculate glow values based on thickness multiplier
32+
const t = GLOW_THICKNESS
33+
2734
const style = document.createElement('style')
2835
style.id = GLOW_STYLES_ID
2936
style.textContent = `
3037
@keyframes nxtscape-glow-pulse {
3138
0% {
3239
box-shadow:
33-
inset 0 0 42px 19px transparent,
34-
inset 0 0 36px 16px rgba(251, 102, 24, 0.06),
35-
inset 0 0 30px 13px rgba(251, 102, 24, 0.12),
36-
inset 0 0 24px 10px rgba(251, 102, 24, 0.18);
40+
inset 0 0 ${58 * t}px ${26 * t}px transparent,
41+
inset 0 0 ${50 * t}px ${22 * t}px rgba(251, 102, 24, 0.06),
42+
inset 0 0 ${42 * t}px ${18 * t}px rgba(251, 102, 24, 0.12),
43+
inset 0 0 ${34 * t}px ${14 * t}px rgba(251, 102, 24, 0.18);
3744
}
3845
50% {
3946
box-shadow:
40-
inset 0 0 52px 25px transparent,
41-
inset 0 0 46px 23px rgba(251, 102, 24, 0.10),
42-
inset 0 0 39px 19px rgba(251, 102, 24, 0.18),
43-
inset 0 0 33px 16px rgba(251, 102, 24, 0.24);
47+
inset 0 0 ${72 * t}px ${35 * t}px transparent,
48+
inset 0 0 ${64 * t}px ${32 * t}px rgba(251, 102, 24, 0.10),
49+
inset 0 0 ${54 * t}px ${26 * t}px rgba(251, 102, 24, 0.18),
50+
inset 0 0 ${46 * t}px ${22 * t}px rgba(251, 102, 24, 0.24);
4451
}
4552
100% {
4653
box-shadow:
47-
inset 0 0 42px 19px transparent,
48-
inset 0 0 36px 16px rgba(251, 102, 24, 0.06),
49-
inset 0 0 30px 13px rgba(251, 102, 24, 0.12),
50-
inset 0 0 24px 10px rgba(251, 102, 24, 0.18);
54+
inset 0 0 ${58 * t}px ${26 * t}px transparent,
55+
inset 0 0 ${50 * t}px ${22 * t}px rgba(251, 102, 24, 0.06),
56+
inset 0 0 ${42 * t}px ${18 * t}px rgba(251, 102, 24, 0.12),
57+
inset 0 0 ${34 * t}px ${14 * t}px rgba(251, 102, 24, 0.18);
5158
}
5259
}
53-
60+
5461
@keyframes nxtscape-glow-fade-in {
5562
from { opacity: 0; }
56-
to { opacity: 0.6; }
63+
to { opacity: ${GLOW_OPACITY}; }
5764
}
58-
65+
5966
#${GLOW_OVERLAY_ID} {
6067
position: fixed !important;
6168
top: 0 !important;
@@ -66,7 +73,7 @@
6673
z-index: 2147483647 !important;
6774
opacity: 0;
6875
will-change: opacity;
69-
animation:
76+
animation:
7077
nxtscape-glow-pulse 3s ease-in-out infinite,
7178
nxtscape-glow-fade-in 420ms cubic-bezier(0.22, 1, 0.36, 1) forwards !important;
7279
}

src/lib/agent/TeachWebSocketAgent.ts

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { TeachModeEventPayload } from "@/lib/pubsub/types";
77
import { Logging } from "@/lib/utils/Logging";
88
import { type SemanticWorkflow } from "@/lib/teach-mode/types";
99
import { GlowAnimationService } from '@/lib/services/GlowAnimationService';
10+
import { isDevelopmentMode } from '@/config';
1011

1112
interface PredefinedPlan {
1213
agentId: string;
@@ -177,14 +178,7 @@ ${JSON.stringify(userTrajectorySteps, null, 2)}`;
177178
});
178179

179180
// Start glow animation
180-
try {
181-
const currentPage = await this.executionContext.browserContext.getCurrentPage();
182-
if (currentPage?.tabId && !this.glowService.isGlowActive(currentPage.tabId)) {
183-
await this.glowService.startGlow(currentPage.tabId);
184-
}
185-
} catch (error) {
186-
Logging.log("TeachWebSocketAgent", `Could not start glow animation: ${error}`, "warning");
187-
}
181+
this._maybeStartGlow();
188182

189183
// Connect to WebSocket server
190184
await this._connect();
@@ -233,7 +227,7 @@ ${JSON.stringify(userTrajectorySteps, null, 2)}`;
233227

234228
return new Promise((resolve, reject) => {
235229
const connectMsgId = PubSub.generateId('teach_ws_connect');
236-
this._emitThinking(connectMsgId, '🔗 Connecting to reasoning server...');
230+
this._emitThinking(connectMsgId, 'Getting ready...');
237231
Logging.log("TeachWebSocketAgent", `Connecting to ${wsUrl}`, "info");
238232

239233
// Create WebSocket
@@ -254,8 +248,6 @@ ${JSON.stringify(userTrajectorySteps, null, 2)}`;
254248
// WebSocket opened
255249
this.ws.onopen = () => {
256250
Logging.log("TeachWebSocketAgent", "WebSocket connection opened", "info");
257-
const openMsgId = PubSub.generateId('teach_ws_open');
258-
this._emitThinking(openMsgId, '✅ WebSocket opened, waiting for server...');
259251
};
260252

261253
// WebSocket message received
@@ -270,9 +262,6 @@ ${JSON.stringify(userTrajectorySteps, null, 2)}`;
270262
this.sessionId = data.data?.sessionId;
271263
this.isConnected = true;
272264

273-
const connectedMsgId = PubSub.generateId('teach_ws_connected');
274-
this._emitThinking(connectedMsgId, '✅ Connected to reasoning server');
275-
276265
if (this.sessionId) {
277266
Logging.log(
278267
"TeachWebSocketAgent",
@@ -428,26 +417,65 @@ ${formattedSteps}`;
428417
// Update last event time for timeout tracking
429418
this.lastEventTime = Date.now();
430419

420+
this._maybeStartGlow();
421+
431422
// Route based on message type
432-
if (data.type === 'connection') {
433-
// Already handled in _connect
434-
return;
435-
}
423+
const isDev = isDevelopmentMode();
436424

437-
if (data.type === 'completion') {
438-
this._handleCompletion(data);
439-
return;
440-
}
425+
switch (data.type) {
426+
case 'connection':
427+
// Already handled in _connect
428+
break;
441429

442-
if (data.type === 'error') {
443-
this._handleError(data);
444-
return;
445-
}
430+
case 'completion':
431+
this._handleCompletion(data);
432+
break;
433+
434+
case 'error':
435+
this._handleError(data);
436+
break;
437+
438+
case 'init':
439+
if (isDev && data.content) {
440+
const msgId = PubSub.generateId('teach_ws_server');
441+
this._emitThinking(msgId, data.content);
442+
}
443+
break;
446444

447-
// For all other types (response, tool_use, thinking, etc), emit as thinking
448-
if (data.content) {
449-
const thinkingMsgId = PubSub.generateId('teach_ws_server');
450-
this._emitThinking(thinkingMsgId, data.content);
445+
case 'thinking':
446+
if (data.content) {
447+
const msgId = PubSub.generateId('teach_ws_server');
448+
this._emitThinking(msgId, data.content);
449+
}
450+
break;
451+
452+
case 'tool_use':
453+
if (data.content) {
454+
const msgId = PubSub.generateId('teach_ws_server');
455+
this._emitThinking(msgId, data.content);
456+
}
457+
break;
458+
459+
case 'tool_result':
460+
if (isDev && data.content) {
461+
const msgId = PubSub.generateId('teach_ws_server');
462+
this._emitThinking(msgId, data.content);
463+
}
464+
break;
465+
466+
case 'response':
467+
if (data.content) {
468+
const msgId = PubSub.generateId('teach_ws_server');
469+
this._emitThinking(msgId, data.content);
470+
}
471+
break;
472+
473+
default:
474+
if (isDev && data.content) {
475+
Logging.log("TeachWebSocketAgent", `Unknown message type: ${data.type}`, "warning");
476+
const msgId = PubSub.generateId('teach_ws_server');
477+
this._emitThinking(msgId, data.content);
478+
}
451479
}
452480

453481
} catch (error) {
@@ -558,6 +586,21 @@ ${formattedSteps}`;
558586
}
559587
}
560588

589+
/**
590+
* Start glow animation (fire and forget)
591+
*/
592+
private _maybeStartGlow(): void {
593+
this.executionContext.browserContext.getCurrentPage()
594+
.then(page => {
595+
if (page?.tabId && !this.glowService.isGlowActive(page.tabId)) {
596+
return this.glowService.startGlow(page.tabId);
597+
}
598+
})
599+
.catch(error => {
600+
Logging.log("TeachWebSocketAgent", `Could not start glow: ${error}`, "warning");
601+
});
602+
}
603+
561604
/**
562605
* Log execution metrics
563606
*/

src/lib/agent/WebSocketAgent.ts

Lines changed: 68 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { AbortError } from "@/lib/utils/Abortable";
44
import { ExecutionMetadata } from "@/lib/types/messaging";
55
import { Logging } from "@/lib/utils/Logging";
66
import { GlowAnimationService } from '@/lib/services/GlowAnimationService';
7+
import { isDevelopmentMode } from '@/config';
78

89

910
interface PredefinedPlan {
@@ -123,14 +124,7 @@ export class WebSocketAgent {
123124
Logging.log("WebSocketAgent", "Starting execution", "info");
124125

125126
// Start glow animation
126-
try {
127-
const currentPage = await this.executionContext.browserContext.getCurrentPage();
128-
if (currentPage?.tabId && !this.glowService.isGlowActive(currentPage.tabId)) {
129-
await this.glowService.startGlow(currentPage.tabId);
130-
}
131-
} catch (error) {
132-
Logging.log("WebSocketAgent", `Could not start glow animation: ${error}`, "warning");
133-
}
127+
this._maybeStartGlow();
134128

135129
// Connect to WebSocket server
136130
await this._connect();
@@ -177,7 +171,7 @@ export class WebSocketAgent {
177171
const wsUrl = await this.executionContext.getAgentServerUrl();
178172

179173
return new Promise((resolve, reject) => {
180-
this._publishMessage('🔗 Connecting to reasoning server...', 'thinking');
174+
this._publishMessage('Getting ready...', 'thinking');
181175
Logging.log("WebSocketAgent", `Connecting to ${wsUrl}`, "info");
182176

183177
// Create WebSocket
@@ -198,7 +192,6 @@ export class WebSocketAgent {
198192
// WebSocket opened
199193
this.ws.onopen = () => {
200194
Logging.log("WebSocketAgent", "WebSocket connection opened", "info");
201-
this._publishMessage('✅ WebSocket opened, waiting for server...', 'thinking');
202195
};
203196

204197
// WebSocket message received
@@ -213,8 +206,6 @@ export class WebSocketAgent {
213206
this.sessionId = data.data?.sessionId;
214207
this.isConnected = true;
215208

216-
this._publishMessage('✅ Connected to reasoning server', 'thinking');
217-
218209
if (this.sessionId) {
219210
Logging.log(
220211
"WebSocketAgent",
@@ -356,25 +347,60 @@ ${formattedSteps}`;
356347
// Update last event time for timeout tracking
357348
this.lastEventTime = Date.now();
358349

350+
// Trigger glow
351+
this._maybeStartGlow();
352+
359353
// Route based on message type
360-
if (data.type === 'connection') {
361-
// Already handled in _connect
362-
return;
363-
}
354+
const isDev = isDevelopmentMode();
364355

365-
if (data.type === 'completion') {
366-
this._handleCompletion(data);
367-
return;
368-
}
356+
switch (data.type) {
357+
case 'connection':
358+
// Already handled in _connect
359+
break;
369360

370-
if (data.type === 'error') {
371-
this._handleError(data);
372-
return;
373-
}
361+
case 'completion':
362+
this._handleCompletion(data);
363+
break;
364+
365+
case 'error':
366+
this._handleError(data);
367+
break;
368+
369+
case 'init':
370+
if (isDev && data.content) {
371+
this._publishMessage(data.content, 'thinking');
372+
}
373+
break;
374374

375-
// For all other types (response, tool_use, thinking, etc), publish content
376-
if (data.content) {
377-
this._publishMessage(data.content, 'thinking');
375+
case 'thinking':
376+
if (data.content) {
377+
this._publishMessage(data.content, 'thinking');
378+
}
379+
break;
380+
381+
case 'tool_use':
382+
if (data.content) {
383+
this._publishMessage(data.content, 'thinking');
384+
}
385+
break;
386+
387+
case 'tool_result':
388+
if (isDev && data.content) {
389+
this._publishMessage(data.content, 'thinking');
390+
}
391+
break;
392+
393+
case 'response':
394+
if (data.content) {
395+
this._publishMessage(data.content, 'thinking');
396+
}
397+
break;
398+
399+
default:
400+
if (isDev && data.content) {
401+
Logging.log("WebSocketAgent", `Unknown message type: ${data.type}`, "warning");
402+
this._publishMessage(data.content, 'thinking');
403+
}
378404
}
379405

380406
} catch (error) {
@@ -466,6 +492,21 @@ ${formattedSteps}`;
466492
);
467493
}
468494

495+
/**
496+
* Start glow animation (fire and forget)
497+
*/
498+
private _maybeStartGlow(): void {
499+
this.executionContext.browserContext.getCurrentPage()
500+
.then(page => {
501+
if (page?.tabId && !this.glowService.isGlowActive(page.tabId)) {
502+
return this.glowService.startGlow(page.tabId);
503+
}
504+
})
505+
.catch(error => {
506+
Logging.log("WebSocketAgent", `Could not start glow: ${error}`, "warning");
507+
});
508+
}
509+
469510
/**
470511
* Handle execution errors
471512
*/

0 commit comments

Comments
 (0)