-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackground.js
More file actions
162 lines (142 loc) · 5.81 KB
/
background.js
File metadata and controls
162 lines (142 loc) · 5.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
let engineReady = false;
let pendingResolve = null;
let bestMove = null;
let evalScore = null;
let mateScore = null;
let engineThreads = 4;
let engineHash = 256;
let offscreenCreated = false;
async function ensureOffscreen() {
if (offscreenCreated) {
console.log('[Neural Knight BG] Offscreen already created');
return;
}
console.log('[Neural Knight BG] Checking for existing offscreen contexts...');
const contexts = await chrome.runtime.getContexts({ contextTypes: ['OFFSCREEN_DOCUMENT'] });
if (contexts.length > 0) {
offscreenCreated = true;
console.log('[Neural Knight BG] Offscreen context found:', contexts.length);
return;
}
console.log('[Neural Knight BG] Creating offscreen document...');
try {
await chrome.offscreen.createDocument({
url: 'offscreen.html',
reasons: ['WORKERS'],
justification: 'Run Stockfish chess engine in a Web Worker'
});
offscreenCreated = true;
console.log('[Neural Knight BG] Offscreen document created successfully');
} catch (err) {
console.error('[Neural Knight BG] Failed to create offscreen:', err);
throw err;
}
}
async function initEngine() {
console.log('[Neural Knight BG] Initializing engine...');
engineReady = false;
await ensureOffscreen();
console.log('[Neural Knight BG] Sending engineInit to offscreen');
chrome.runtime.sendMessage({ type: 'engineInit', threads: engineThreads, hash: engineHash });
}
function sendCmd(command) {
try {
chrome.runtime.sendMessage({ type: 'engineCommand', command });
} catch (err) {
console.error('[Neural Knight BG] Failed to send command:', err);
}
}
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.type === 'engineOutput') {
const line = msg.line;
if (typeof line !== 'string') return;
if (line === 'readyok') {
engineReady = true;
console.log('[Neural Knight BG] Engine ready!');
}
if (line.startsWith('info') && line.includes(' pv ')) {
const score = line.match(/score (cp|mate) (-?\d+)/);
if (score) {
if (score[1] === 'cp') { evalScore = parseInt(score[2], 10) / 100; mateScore = null; }
else { mateScore = parseInt(score[2], 10); evalScore = null; }
}
const pv = line.match(/ pv (.+)/);
if (pv) bestMove = pv[1].split(' ')[0];
}
if (line.startsWith('bestmove')) {
const parts = line.split(' ');
if (parts[1] && parts[1] !== '(none)') bestMove = parts[1];
console.log('[Neural Knight BG] Analysis complete. Best move:', bestMove, 'Eval:', evalScore, 'Mate:', mateScore);
if (pendingResolve) {
pendingResolve({ continuation: bestMove || '', evaluation: evalScore, mate: mateScore });
pendingResolve = null;
}
bestMove = null; evalScore = null; mateScore = null;
}
return;
}
if (msg.action === 'analyze') {
console.log('[Neural Knight BG] Received analyze request, FEN:', msg.fen?.substring(0, 30) + '...');
const run = () => doAnalysis(msg.fen, msg.depth, sendResponse);
if (!offscreenCreated) {
console.log('[Neural Knight BG] Offscreen not created, initializing...');
initEngine().then(() => waitReady(run)).catch(err => {
console.error('[Neural Knight BG] Init failed:', err);
sendResponse({ continuation: '', evaluation: 0, mate: null });
});
return true;
}
if (!engineReady) {
console.log('[Neural Knight BG] Engine not ready, waiting...');
waitReady(run);
return true;
}
console.log('[Neural Knight BG] Running analysis immediately');
run();
return true;
}
if (msg.action === 'restartEngine') {
engineThreads = msg.threads || 4;
engineHash = msg.hash || 256;
console.log('[Neural Knight BG] Restarting engine with threads:', engineThreads, 'hash:', engineHash);
initEngine().catch(err => {
console.error('[Neural Knight BG] Restart failed:', err);
});
sendResponse({ ok: true });
return false;
}
});
function waitReady(cb) {
const poll = setInterval(() => {
if (engineReady) { clearInterval(poll); cb(); }
}, 100);
}
function doAnalysis(fen, depth, sendResponse) {
if (pendingResolve) {
console.log('[Neural Knight BG] Canceling previous analysis');
pendingResolve(null);
pendingResolve = null;
}
bestMove = null; evalScore = null; mateScore = null;
pendingResolve = sendResponse;
console.log('[Neural Knight BG] Starting analysis at depth', depth);
sendCmd('stop');
sendCmd('position fen ' + fen);
sendCmd('go depth ' + (depth || 14));
// Safety timeout - if engine doesn't respond in 30 seconds, fail gracefully
setTimeout(() => {
if (pendingResolve === sendResponse) {
console.error('[Neural Knight BG] Analysis timeout');
pendingResolve({ continuation: '', evaluation: 0, mate: null });
pendingResolve = null;
}
}, 30000);
}
chrome.storage.local.get(['engineThreads', 'engineHash'], (res) => {
engineThreads = res.engineThreads || 4;
engineHash = res.engineHash || 256;
console.log('[Neural Knight BG] Starting with threads:', engineThreads, 'hash:', engineHash);
initEngine().catch(err => {
console.error('[Neural Knight BG] Failed to initialize engine on startup:', err);
});
});