GeminiBot commited on
Commit
a118953
·
1 Parent(s): 4bca23b

Fix iframe crash in JSDOM and add verbose logging

Browse files
Files changed (2) hide show
  1. src/duckai.ts +33 -0
  2. src/server.ts +9 -5
src/duckai.ts CHANGED
@@ -27,6 +27,26 @@ export class DuckAI {
27
  window.screen = { width: 1920, height: 1080, availWidth: 1920, availHeight: 1080 };
28
  window.chrome = { runtime: {} };
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  // Robust Canvas Mock
31
  const originalGetContext = window.HTMLCanvasElement.prototype.getContext;
32
  window.HTMLCanvasElement.prototype.getContext = function (type: string, options?: any) {
@@ -148,11 +168,18 @@ export class DuckAI {
148
  "x-vqd-accept": "1"
149
  };
150
 
 
151
  const statusRes = await fetch("https://duckduckgo.com/duckchat/v1/status?q=1", { headers });
 
 
152
  const hashHeader = statusRes.headers.get("x-vqd-hash-1");
 
 
153
  if (!hashHeader) throw new Error("Missing x-vqd-hash-1 - DuckDuckGo might be blocking this IP or Challenge failed.");
154
 
 
155
  const solvedVqd = await this.solveChallenge(hashHeader, ua);
 
156
 
157
  const response = await fetch("https://duckduckgo.com/duckchat/v1/chat", {
158
  method: "POST",
@@ -160,12 +187,17 @@ export class DuckAI {
160
  body: JSON.stringify(request)
161
  });
162
 
 
 
163
  if (!response.ok) {
164
  const errorText = await response.text();
 
165
  throw new Error(`DuckDuckGo API Error (${response.status}): ${errorText.substring(0, 100)}`);
166
  }
167
 
168
  const text = await response.text();
 
 
169
  let llmResponse = "";
170
  const lines = text.split("\n");
171
  for (const line of lines) {
@@ -180,6 +212,7 @@ export class DuckAI {
180
  }
181
 
182
  if (!llmResponse) {
 
183
  throw new Error("Empty response from DuckDuckGo");
184
  }
185
 
 
27
  window.screen = { width: 1920, height: 1080, availWidth: 1920, availHeight: 1080 };
28
  window.chrome = { runtime: {} };
29
 
30
+ // Fix for 'Cannot read properties of null (reading 'contentDocument')'
31
+ // Some challenge scripts create an iframe and immediately access contentDocument
32
+ const originalCreateElement = window.document.createElement;
33
+ window.document.createElement = function(tagName: string) {
34
+ const element = originalCreateElement.call(this, tagName);
35
+ if (tagName.toLowerCase() === 'iframe') {
36
+ try {
37
+ Object.defineProperty(element, 'contentDocument', {
38
+ get: () => window.document, // Return main document as fallback or a dummy
39
+ configurable: true
40
+ });
41
+ Object.defineProperty(element, 'contentWindow', {
42
+ get: () => window,
43
+ configurable: true
44
+ });
45
+ } catch (e) {}
46
+ }
47
+ return element;
48
+ };
49
+
50
  // Robust Canvas Mock
51
  const originalGetContext = window.HTMLCanvasElement.prototype.getContext;
52
  window.HTMLCanvasElement.prototype.getContext = function (type: string, options?: any) {
 
168
  "x-vqd-accept": "1"
169
  };
170
 
171
+ console.log("[DuckAI] Fetching status...");
172
  const statusRes = await fetch("https://duckduckgo.com/duckchat/v1/status?q=1", { headers });
173
+ console.log(`[DuckAI] Status response: ${statusRes.status}`);
174
+
175
  const hashHeader = statusRes.headers.get("x-vqd-hash-1");
176
+ console.log(`[DuckAI] x-vqd-hash-1: ${hashHeader ? "FOUND" : "MISSING"}`);
177
+
178
  if (!hashHeader) throw new Error("Missing x-vqd-hash-1 - DuckDuckGo might be blocking this IP or Challenge failed.");
179
 
180
+ console.log("[DuckAI] Solving challenge...");
181
  const solvedVqd = await this.solveChallenge(hashHeader, ua);
182
+ console.log("[DuckAI] Challenge solved.");
183
 
184
  const response = await fetch("https://duckduckgo.com/duckchat/v1/chat", {
185
  method: "POST",
 
187
  body: JSON.stringify(request)
188
  });
189
 
190
+ console.log(`[DuckAI] Chat response status: ${response.status}`);
191
+
192
  if (!response.ok) {
193
  const errorText = await response.text();
194
+ console.log(`[DuckAI] Error body: ${errorText}`);
195
  throw new Error(`DuckDuckGo API Error (${response.status}): ${errorText.substring(0, 100)}`);
196
  }
197
 
198
  const text = await response.text();
199
+ // console.log(`[DuckAI] Raw response: ${text.substring(0, 200)}...`); // Uncomment for ultra verbose
200
+
201
  let llmResponse = "";
202
  const lines = text.split("\n");
203
  for (const line of lines) {
 
212
  }
213
 
214
  if (!llmResponse) {
215
+ console.log("[DuckAI] Warning: Empty LLM response extracted.");
216
  throw new Error("Empty response from DuckDuckGo");
217
  }
218
 
src/server.ts CHANGED
@@ -90,15 +90,19 @@ const server = createServer(async (req: IncomingMessage, res: ServerResponse) =>
90
  req.on("data", (chunk) => { body += chunk; });
91
  req.on("end", async () => {
92
  try {
93
- const jsonBody = JSON.parse(body);
94
- const lastMsg = jsonBody.messages?.[jsonBody.messages.length - 1]?.content || "";
95
- log(`REQ: ${lastMsg.substring(0, 50)}...`);
96
 
 
97
  const completion = await openAIService.createChatCompletion(jsonBody);
 
 
 
 
98
  sendJSON(200, completion);
99
  } catch (error: any) {
100
- log(`ERR: ${error.message}`);
101
- sendJSON(500, { error: error.message });
102
  }
103
  });
104
  return;
 
90
  req.on("data", (chunk) => { body += chunk; });
91
  req.on("end", async () => {
92
  try {
93
+ // Log full request for debugging
94
+ log(`INCOMING REQUEST:\n${body}`);
 
95
 
96
+ const jsonBody = JSON.parse(body);
97
  const completion = await openAIService.createChatCompletion(jsonBody);
98
+
99
+ // Log success summary
100
+ log(`SUCCESS: Sent response for ${jsonBody.model}`);
101
+
102
  sendJSON(200, completion);
103
  } catch (error: any) {
104
+ log(`ERROR: ${error.message}\nSTACK: ${error.stack}`);
105
+ sendJSON(500, { error: error.message, details: error.stack });
106
  }
107
  });
108
  return;