JavaScript · 5760 bytes Raw Blame History
1 // Background script for LooseCannon - Fixed Connection Issues
2 console.log('[LooseCannon Background] Initialized');
3
4 class LooseCannonBackground {
5 constructor() {
6 this.serverUrl = 'http://localhost:8765'; // Local server URL
7 this.isConnected = false;
8 this.activeTabs = new Map();
9 this.personalities = [];
10 this.currentPersonality = 'default';
11 this.init();
12 }
13
14 init() {
15 this.setupMessageListeners();
16 this.checkServerConnection();
17 this.loadSettings();
18 }
19
20 setupMessageListeners() {
21 browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
22 console.log('[LooseCannon Background] Received message:', message.type);
23
24 switch (message.type) {
25 case 'NEW_MESSAGE':
26 this.handleNewMessage(message.data, sender.tab.id)
27 .then(sendResponse)
28 .catch(error => {
29 console.error('Error handling message:', error);
30 sendResponse({ error: error.message });
31 });
32 return true; // Keep channel open for async response
33
34 case 'TOGGLE_ACTIVE':
35 this.handleToggleActive(sender.tab.id, message.data.isActive);
36 sendResponse({ success: true });
37 break;
38
39 case 'GET_SERVER_STATUS':
40 // Check connection immediately when asked
41 this.checkServerConnection().then(() => {
42 sendResponse({ connected: this.isConnected });
43 });
44 return true; // Keep channel open for async response
45
46 case 'GET_PERSONALITIES':
47 sendResponse({ personalities: this.personalities });
48 break;
49
50 case 'SET_PERSONALITY':
51 this.currentPersonality = message.data.personality;
52 this.saveSettings();
53 sendResponse({ success: true });
54 break;
55
56 default:
57 console.warn('Unknown message type:', message.type);
58 }
59 });
60 }
61
62 async handleNewMessage(data, tabId) {
63 if (!this.isConnected) {
64 console.warn('[LooseCannon] Server not connected, cannot process message');
65 return { error: 'Server not connected' };
66 }
67
68 try {
69 // Send message to local server for LLM processing
70 const response = await fetch(`${this.serverUrl}/generate`, {
71 method: 'POST',
72 headers: {
73 'Content-Type': 'application/json',
74 },
75 body: JSON.stringify({
76 message: data.text,
77 personality: this.currentPersonality,
78 chatId: data.chatId,
79 timestamp: data.timestamp
80 })
81 });
82
83 if (!response.ok) {
84 throw new Error(`Server error: ${response.status}`);
85 }
86
87 const result = await response.json();
88 console.log('[LooseCannon] Generated response:', result.reply);
89
90 // Log conversation for debugging
91 this.logConversation(data.chatId, data.text, result.reply);
92
93 return { reply: result.reply };
94 } catch (error) {
95 console.error('[LooseCannon] Error generating response:', error);
96 return { error: error.message };
97 }
98 }
99
100 handleToggleActive(tabId, isActive) {
101 if (isActive) {
102 this.activeTabs.set(tabId, {
103 activated: new Date().toISOString(),
104 messageCount: 0
105 });
106 console.log(`[LooseCannon] Activated for tab ${tabId}`);
107 } else {
108 this.activeTabs.delete(tabId);
109 console.log(`[LooseCannon] Deactivated for tab ${tabId}`);
110 }
111 }
112
113 async checkServerConnection() {
114 try {
115 console.log('[LooseCannon] Checking server connection...');
116 const response = await fetch(`${this.serverUrl}/status`);
117
118 if (response.ok) {
119 const data = await response.json();
120 this.isConnected = true;
121 this.personalities = data.personalities || [];
122 console.log('[LooseCannon] Server connected successfully');
123 console.log('[LooseCannon] Available personalities:', this.personalities);
124 return true;
125 } else {
126 this.isConnected = false;
127 console.warn('[LooseCannon] Server responded with error:', response.status);
128 return false;
129 }
130 } catch (error) {
131 this.isConnected = false;
132 console.error('[LooseCannon] Could not connect to server:', error.message);
133
134 // Retry in 5 seconds
135 setTimeout(() => this.checkServerConnection(), 5000);
136 return false;
137 }
138 }
139
140 async loadSettings() {
141 try {
142 const settings = await browser.storage.local.get(['personality', 'serverUrl']);
143 if (settings.personality) {
144 this.currentPersonality = settings.personality;
145 }
146 if (settings.serverUrl) {
147 this.serverUrl = settings.serverUrl;
148 }
149 console.log('[LooseCannon] Settings loaded:', settings);
150 } catch (error) {
151 console.error('[LooseCannon] Error loading settings:', error);
152 }
153 }
154
155 async saveSettings() {
156 try {
157 await browser.storage.local.set({
158 personality: this.currentPersonality,
159 serverUrl: this.serverUrl
160 });
161 console.log('[LooseCannon] Settings saved');
162 } catch (error) {
163 console.error('[LooseCannon] Error saving settings:', error);
164 }
165 }
166
167 logConversation(chatId, userMessage, botReply) {
168 const log = {
169 timestamp: new Date().toISOString(),
170 chatId,
171 userMessage,
172 botReply
173 };
174
175 // Store conversation logs (with limit to prevent storage overflow)
176 browser.storage.local.get('conversationLogs').then(result => {
177 let logs = result.conversationLogs || [];
178 logs.push(log);
179
180 // Keep only last 100 messages
181 if (logs.length > 100) {
182 logs = logs.slice(-100);
183 }
184
185 browser.storage.local.set({ conversationLogs: logs });
186 });
187 }
188 }
189
190 // Initialize background script
191 const looseCannonBg = new LooseCannonBackground();