diff --git a/src/content/glow-animation.ts b/src/content/glow-animation.ts index 7093455e..8e1f423d 100644 --- a/src/content/glow-animation.ts +++ b/src/content/glow-animation.ts @@ -8,6 +8,10 @@ const GLOW_STYLES_ID = 'nxtscape-glow-styles' const GLOW_INITIALIZED_KEY = 'nxtscape-glow-initialized' const GLOW_ENABLED_KEY = 'nxtscape-glow-enabled' // Stored in chrome.storage.local + + // Glow thickness controls - adjust these to change glow intensity + const GLOW_THICKNESS = 1.0 // Multiplier for all glow values (0.5 = thinner, 1.5 = thicker) + const GLOW_OPACITY = 0.6 // Final opacity of the glow overlay (0.0 - 1.0) // Check if already initialized to prevent duplicate listeners if ((window as any)[GLOW_INITIALIZED_KEY]) { @@ -23,39 +27,42 @@ if (document.getElementById(GLOW_STYLES_ID)) { return } - + + // Calculate glow values based on thickness multiplier + const t = GLOW_THICKNESS + const style = document.createElement('style') style.id = GLOW_STYLES_ID style.textContent = ` @keyframes nxtscape-glow-pulse { 0% { box-shadow: - inset 0 0 42px 19px transparent, - inset 0 0 36px 16px rgba(251, 102, 24, 0.06), - inset 0 0 30px 13px rgba(251, 102, 24, 0.12), - inset 0 0 24px 10px rgba(251, 102, 24, 0.18); + inset 0 0 ${58 * t}px ${26 * t}px transparent, + inset 0 0 ${50 * t}px ${22 * t}px rgba(251, 102, 24, 0.06), + inset 0 0 ${42 * t}px ${18 * t}px rgba(251, 102, 24, 0.12), + inset 0 0 ${34 * t}px ${14 * t}px rgba(251, 102, 24, 0.18); } 50% { box-shadow: - inset 0 0 52px 25px transparent, - inset 0 0 46px 23px rgba(251, 102, 24, 0.10), - inset 0 0 39px 19px rgba(251, 102, 24, 0.18), - inset 0 0 33px 16px rgba(251, 102, 24, 0.24); + inset 0 0 ${72 * t}px ${35 * t}px transparent, + inset 0 0 ${64 * t}px ${32 * t}px rgba(251, 102, 24, 0.10), + inset 0 0 ${54 * t}px ${26 * t}px rgba(251, 102, 24, 0.18), + inset 0 0 ${46 * t}px ${22 * t}px rgba(251, 102, 24, 0.24); } 100% { box-shadow: - inset 0 0 42px 19px transparent, - inset 0 0 36px 16px rgba(251, 102, 24, 0.06), - inset 0 0 30px 13px rgba(251, 102, 24, 0.12), - inset 0 0 24px 10px rgba(251, 102, 24, 0.18); + inset 0 0 ${58 * t}px ${26 * t}px transparent, + inset 0 0 ${50 * t}px ${22 * t}px rgba(251, 102, 24, 0.06), + inset 0 0 ${42 * t}px ${18 * t}px rgba(251, 102, 24, 0.12), + inset 0 0 ${34 * t}px ${14 * t}px rgba(251, 102, 24, 0.18); } } - + @keyframes nxtscape-glow-fade-in { from { opacity: 0; } - to { opacity: 0.6; } + to { opacity: ${GLOW_OPACITY}; } } - + #${GLOW_OVERLAY_ID} { position: fixed !important; top: 0 !important; @@ -66,7 +73,7 @@ z-index: 2147483647 !important; opacity: 0; will-change: opacity; - animation: + animation: nxtscape-glow-pulse 3s ease-in-out infinite, nxtscape-glow-fade-in 420ms cubic-bezier(0.22, 1, 0.36, 1) forwards !important; } diff --git a/src/lib/agent/TeachWebSocketAgent.ts b/src/lib/agent/TeachWebSocketAgent.ts index 86542774..360bac91 100644 --- a/src/lib/agent/TeachWebSocketAgent.ts +++ b/src/lib/agent/TeachWebSocketAgent.ts @@ -7,6 +7,7 @@ import { TeachModeEventPayload } from "@/lib/pubsub/types"; import { Logging } from "@/lib/utils/Logging"; import { type SemanticWorkflow } from "@/lib/teach-mode/types"; import { GlowAnimationService } from '@/lib/services/GlowAnimationService'; +import { isDevelopmentMode } from '@/config'; interface PredefinedPlan { agentId: string; @@ -177,14 +178,7 @@ ${JSON.stringify(userTrajectorySteps, null, 2)}`; }); // Start glow animation - try { - const currentPage = await this.executionContext.browserContext.getCurrentPage(); - if (currentPage?.tabId && !this.glowService.isGlowActive(currentPage.tabId)) { - await this.glowService.startGlow(currentPage.tabId); - } - } catch (error) { - Logging.log("TeachWebSocketAgent", `Could not start glow animation: ${error}`, "warning"); - } + this._maybeStartGlow(); // Connect to WebSocket server await this._connect(); @@ -233,7 +227,7 @@ ${JSON.stringify(userTrajectorySteps, null, 2)}`; return new Promise((resolve, reject) => { const connectMsgId = PubSub.generateId('teach_ws_connect'); - this._emitThinking(connectMsgId, '🔗 Connecting to reasoning server...'); + this._emitThinking(connectMsgId, 'Getting ready...'); Logging.log("TeachWebSocketAgent", `Connecting to ${wsUrl}`, "info"); // Create WebSocket @@ -254,8 +248,6 @@ ${JSON.stringify(userTrajectorySteps, null, 2)}`; // WebSocket opened this.ws.onopen = () => { Logging.log("TeachWebSocketAgent", "WebSocket connection opened", "info"); - const openMsgId = PubSub.generateId('teach_ws_open'); - this._emitThinking(openMsgId, '✅ WebSocket opened, waiting for server...'); }; // WebSocket message received @@ -270,9 +262,6 @@ ${JSON.stringify(userTrajectorySteps, null, 2)}`; this.sessionId = data.data?.sessionId; this.isConnected = true; - const connectedMsgId = PubSub.generateId('teach_ws_connected'); - this._emitThinking(connectedMsgId, '✅ Connected to reasoning server'); - if (this.sessionId) { Logging.log( "TeachWebSocketAgent", @@ -428,26 +417,65 @@ ${formattedSteps}`; // Update last event time for timeout tracking this.lastEventTime = Date.now(); + this._maybeStartGlow(); + // Route based on message type - if (data.type === 'connection') { - // Already handled in _connect - return; - } + const isDev = isDevelopmentMode(); - if (data.type === 'completion') { - this._handleCompletion(data); - return; - } + switch (data.type) { + case 'connection': + // Already handled in _connect + break; - if (data.type === 'error') { - this._handleError(data); - return; - } + case 'completion': + this._handleCompletion(data); + break; + + case 'error': + this._handleError(data); + break; + + case 'init': + if (isDev && data.content) { + const msgId = PubSub.generateId('teach_ws_server'); + this._emitThinking(msgId, data.content); + } + break; - // For all other types (response, tool_use, thinking, etc), emit as thinking - if (data.content) { - const thinkingMsgId = PubSub.generateId('teach_ws_server'); - this._emitThinking(thinkingMsgId, data.content); + case 'thinking': + if (data.content) { + const msgId = PubSub.generateId('teach_ws_server'); + this._emitThinking(msgId, data.content); + } + break; + + case 'tool_use': + if (data.content) { + const msgId = PubSub.generateId('teach_ws_server'); + this._emitThinking(msgId, data.content); + } + break; + + case 'tool_result': + if (isDev && data.content) { + const msgId = PubSub.generateId('teach_ws_server'); + this._emitThinking(msgId, data.content); + } + break; + + case 'response': + if (data.content) { + const msgId = PubSub.generateId('teach_ws_server'); + this._emitThinking(msgId, data.content); + } + break; + + default: + if (isDev && data.content) { + Logging.log("TeachWebSocketAgent", `Unknown message type: ${data.type}`, "warning"); + const msgId = PubSub.generateId('teach_ws_server'); + this._emitThinking(msgId, data.content); + } } } catch (error) { @@ -558,6 +586,21 @@ ${formattedSteps}`; } } + /** + * Start glow animation (fire and forget) + */ + private _maybeStartGlow(): void { + this.executionContext.browserContext.getCurrentPage() + .then(page => { + if (page?.tabId && !this.glowService.isGlowActive(page.tabId)) { + return this.glowService.startGlow(page.tabId); + } + }) + .catch(error => { + Logging.log("TeachWebSocketAgent", `Could not start glow: ${error}`, "warning"); + }); + } + /** * Log execution metrics */ diff --git a/src/lib/agent/WebSocketAgent.ts b/src/lib/agent/WebSocketAgent.ts index 51e6d825..5812204f 100644 --- a/src/lib/agent/WebSocketAgent.ts +++ b/src/lib/agent/WebSocketAgent.ts @@ -4,6 +4,7 @@ import { AbortError } from "@/lib/utils/Abortable"; import { ExecutionMetadata } from "@/lib/types/messaging"; import { Logging } from "@/lib/utils/Logging"; import { GlowAnimationService } from '@/lib/services/GlowAnimationService'; +import { isDevelopmentMode } from '@/config'; interface PredefinedPlan { @@ -123,14 +124,7 @@ export class WebSocketAgent { Logging.log("WebSocketAgent", "Starting execution", "info"); // Start glow animation - try { - const currentPage = await this.executionContext.browserContext.getCurrentPage(); - if (currentPage?.tabId && !this.glowService.isGlowActive(currentPage.tabId)) { - await this.glowService.startGlow(currentPage.tabId); - } - } catch (error) { - Logging.log("WebSocketAgent", `Could not start glow animation: ${error}`, "warning"); - } + this._maybeStartGlow(); // Connect to WebSocket server await this._connect(); @@ -177,7 +171,7 @@ export class WebSocketAgent { const wsUrl = await this.executionContext.getAgentServerUrl(); return new Promise((resolve, reject) => { - this._publishMessage('🔗 Connecting to reasoning server...', 'thinking'); + this._publishMessage('Getting ready...', 'thinking'); Logging.log("WebSocketAgent", `Connecting to ${wsUrl}`, "info"); // Create WebSocket @@ -198,7 +192,6 @@ export class WebSocketAgent { // WebSocket opened this.ws.onopen = () => { Logging.log("WebSocketAgent", "WebSocket connection opened", "info"); - this._publishMessage('✅ WebSocket opened, waiting for server...', 'thinking'); }; // WebSocket message received @@ -213,8 +206,6 @@ export class WebSocketAgent { this.sessionId = data.data?.sessionId; this.isConnected = true; - this._publishMessage('✅ Connected to reasoning server', 'thinking'); - if (this.sessionId) { Logging.log( "WebSocketAgent", @@ -356,25 +347,60 @@ ${formattedSteps}`; // Update last event time for timeout tracking this.lastEventTime = Date.now(); + // Trigger glow + this._maybeStartGlow(); + // Route based on message type - if (data.type === 'connection') { - // Already handled in _connect - return; - } + const isDev = isDevelopmentMode(); - if (data.type === 'completion') { - this._handleCompletion(data); - return; - } + switch (data.type) { + case 'connection': + // Already handled in _connect + break; - if (data.type === 'error') { - this._handleError(data); - return; - } + case 'completion': + this._handleCompletion(data); + break; + + case 'error': + this._handleError(data); + break; + + case 'init': + if (isDev && data.content) { + this._publishMessage(data.content, 'thinking'); + } + break; - // For all other types (response, tool_use, thinking, etc), publish content - if (data.content) { - this._publishMessage(data.content, 'thinking'); + case 'thinking': + if (data.content) { + this._publishMessage(data.content, 'thinking'); + } + break; + + case 'tool_use': + if (data.content) { + this._publishMessage(data.content, 'thinking'); + } + break; + + case 'tool_result': + if (isDev && data.content) { + this._publishMessage(data.content, 'thinking'); + } + break; + + case 'response': + if (data.content) { + this._publishMessage(data.content, 'thinking'); + } + break; + + default: + if (isDev && data.content) { + Logging.log("WebSocketAgent", `Unknown message type: ${data.type}`, "warning"); + this._publishMessage(data.content, 'thinking'); + } } } catch (error) { @@ -466,6 +492,21 @@ ${formattedSteps}`; ); } + /** + * Start glow animation (fire and forget) + */ + private _maybeStartGlow(): void { + this.executionContext.browserContext.getCurrentPage() + .then(page => { + if (page?.tabId && !this.glowService.isGlowActive(page.tabId)) { + return this.glowService.startGlow(page.tabId); + } + }) + .catch(error => { + Logging.log("WebSocketAgent", `Could not start glow: ${error}`, "warning"); + }); + } + /** * Handle execution errors */