decant-core 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -20
- package/ai/base.js +4 -4
- package/ai/chatgpt.js +356 -216
- package/ai/chatgpt_helper.js +46 -28
- package/ai/chatgpt_scroll_collector.js +36 -33
- package/ai/chub.js +90 -0
- package/ai/claude.js +119 -92
- package/ai/claude_react_reader.js +8 -6
- package/ai/copilot.js +158 -124
- package/ai/deepseek.js +36 -27
- package/ai/gemini.js +384 -230
- package/ai/gemini_cloud_assist.js +31 -22
- package/ai/google_ai_studio.js +45 -27
- package/ai/google_search_ai.js +32 -23
- package/ai/index.js +33 -19
- package/ai/joyland.js +85 -0
- package/ai/lumo.js +39 -28
- package/ai/meta.js +30 -24
- package/ai/mistral.js +21 -16
- package/ai/notebooklm.js +50 -34
- package/ai/perplexity.js +22 -19
- package/ai/qwen.js +29 -25
- package/ai/z_ai.js +34 -28
- package/detection/detect-platform.js +27 -19
- package/detection/domains.js +32 -24
- package/lib/turndown.js +352 -183
- package/package.json +24 -5
- package/utils/html-to-markdown.js +148 -112
- package/web/article.js +286 -0
- package/web/index.js +6 -0
- package/web/scoring.js +76 -0
package/ai/gemini.js
CHANGED
|
@@ -1,105 +1,126 @@
|
|
|
1
|
-
import { ChatParser } from
|
|
2
|
-
import { convertToMarkdown } from
|
|
1
|
+
import { ChatParser } from "./base.js";
|
|
2
|
+
import { convertToMarkdown } from "../utils/html-to-markdown.js";
|
|
3
3
|
|
|
4
4
|
export class GeminiParser extends ChatParser {
|
|
5
|
-
name =
|
|
5
|
+
name = "Gemini";
|
|
6
6
|
isAvailable(url) {
|
|
7
|
-
return url.includes(
|
|
7
|
+
return url.includes("gemini.google.com");
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
async parse() {
|
|
11
|
-
console.log(
|
|
11
|
+
console.log("[Gemini Parser] ========== STARTING PARSE() ==========");
|
|
12
12
|
|
|
13
13
|
try {
|
|
14
14
|
//1. Title Extraction - Enhanced for Deep Research
|
|
15
|
-
let title =
|
|
15
|
+
let title = "";
|
|
16
16
|
|
|
17
17
|
const isInsideMessage = (el) => {
|
|
18
18
|
return !!el.closest(
|
|
19
|
-
|
|
19
|
+
"user-query, model-response, .conversation-container, message-content, .query-text, .markdown",
|
|
20
20
|
);
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
// Strategy 1: Using document.title
|
|
24
|
-
console.log(
|
|
24
|
+
console.log("[Gemini Parser] Strategy 1: Looking at document.title...");
|
|
25
25
|
if (document.title) {
|
|
26
26
|
const cleanedDocTitle = document.title
|
|
27
|
-
.replace(/Google/g,
|
|
28
|
-
.replace(/Gemini/g,
|
|
29
|
-
.replace(/Advanced/g,
|
|
30
|
-
.replace(/- /g,
|
|
31
|
-
.replace(/—/g,
|
|
27
|
+
.replace(/Google/g, "")
|
|
28
|
+
.replace(/Gemini/g, "")
|
|
29
|
+
.replace(/Advanced/g, "")
|
|
30
|
+
.replace(/- /g, "")
|
|
31
|
+
.replace(/—/g, "")
|
|
32
32
|
.trim();
|
|
33
33
|
|
|
34
34
|
const isGeneric =
|
|
35
35
|
!cleanedDocTitle ||
|
|
36
|
-
cleanedDocTitle.toLowerCase() ===
|
|
37
|
-
cleanedDocTitle.toLowerCase() ===
|
|
38
|
-
cleanedDocTitle.toLowerCase() ===
|
|
36
|
+
cleanedDocTitle.toLowerCase() === "new chat" ||
|
|
37
|
+
cleanedDocTitle.toLowerCase() === "help" ||
|
|
38
|
+
cleanedDocTitle.toLowerCase() === "settings";
|
|
39
39
|
|
|
40
40
|
if (cleanedDocTitle && !isGeneric && cleanedDocTitle.length > 2) {
|
|
41
41
|
title = cleanedDocTitle;
|
|
42
|
-
console.log(
|
|
42
|
+
console.log(
|
|
43
|
+
"[Gemini Parser] Title set from Strategy 1 (document.title):",
|
|
44
|
+
title,
|
|
45
|
+
);
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
// Strategy 2: Looking for active navigation
|
|
47
50
|
if (!title) {
|
|
48
|
-
console.log(
|
|
49
|
-
|
|
51
|
+
console.log(
|
|
52
|
+
"[Gemini Parser] Strategy 2: Looking for active navigation...",
|
|
53
|
+
);
|
|
54
|
+
const activeNav = document.querySelector(
|
|
55
|
+
'a[aria-current="page"], .selected',
|
|
56
|
+
);
|
|
50
57
|
if (activeNav) {
|
|
51
58
|
const navText = activeNav.innerText
|
|
52
|
-
.replace(/more_vert/g,
|
|
53
|
-
.replace(/\n/g,
|
|
59
|
+
.replace(/more_vert/g, "")
|
|
60
|
+
.replace(/\n/g, " ")
|
|
54
61
|
.trim();
|
|
55
|
-
if (
|
|
62
|
+
if (
|
|
63
|
+
navText &&
|
|
64
|
+
navText.length > 2 &&
|
|
65
|
+
!navText.toLowerCase().includes("new chat")
|
|
66
|
+
) {
|
|
56
67
|
title = navText;
|
|
57
|
-
console.log(
|
|
68
|
+
console.log(
|
|
69
|
+
"[Gemini Parser] Title set from Strategy 2 (active navigation):",
|
|
70
|
+
title,
|
|
71
|
+
);
|
|
58
72
|
}
|
|
59
73
|
}
|
|
60
74
|
}
|
|
61
75
|
|
|
62
76
|
// Strategy 3: Check for Deep Research title patterns
|
|
63
77
|
if (!title) {
|
|
64
|
-
console.log(
|
|
78
|
+
console.log(
|
|
79
|
+
"[Gemini Parser] Strategy 3: Looking for Deep Research title patterns...",
|
|
80
|
+
);
|
|
65
81
|
const deepResearchTitle = document.querySelector(
|
|
66
82
|
'h1, .title, .conversation-title, [data-testid="title"]',
|
|
67
83
|
);
|
|
68
84
|
if (deepResearchTitle && !isInsideMessage(deepResearchTitle)) {
|
|
69
85
|
const text = deepResearchTitle.innerText.trim();
|
|
70
|
-
console.log(
|
|
86
|
+
console.log("[Gemini Parser] Found potential title:", text);
|
|
71
87
|
if (
|
|
72
88
|
text.length > 5 &&
|
|
73
|
-
!text.includes(
|
|
74
|
-
!text.includes(
|
|
75
|
-
!text.includes(
|
|
89
|
+
!text.includes("Gemini") &&
|
|
90
|
+
!text.includes("Help") &&
|
|
91
|
+
!text.includes("Settings")
|
|
76
92
|
) {
|
|
77
93
|
title = text;
|
|
78
|
-
console.log(
|
|
94
|
+
console.log("[Gemini Parser] Title set from Strategy 3:", title);
|
|
79
95
|
}
|
|
80
96
|
}
|
|
81
97
|
}
|
|
82
98
|
|
|
83
99
|
// Strategy 4: Look for title in page content (Deep Research reports often have titles in content)
|
|
84
100
|
if (!title) {
|
|
85
|
-
console.log(
|
|
101
|
+
console.log(
|
|
102
|
+
"[Gemini Parser] Strategy 4: Looking for title in page content...",
|
|
103
|
+
);
|
|
86
104
|
const contentTitles = document.querySelectorAll(
|
|
87
|
-
|
|
105
|
+
"main h1, main h2, article h1, article h2, .content h1, .content h2",
|
|
106
|
+
);
|
|
107
|
+
console.log(
|
|
108
|
+
"[Gemini Parser] Found content titles:",
|
|
109
|
+
contentTitles.length,
|
|
88
110
|
);
|
|
89
|
-
console.log('[Gemini Parser] Found content titles:', contentTitles.length);
|
|
90
111
|
for (const el of contentTitles) {
|
|
91
112
|
if (isInsideMessage(el)) continue;
|
|
92
113
|
const text = el.innerText.trim();
|
|
93
114
|
if (
|
|
94
115
|
text.length > 5 &&
|
|
95
|
-
!text.includes(
|
|
96
|
-
!text.includes(
|
|
97
|
-
!text.includes(
|
|
98
|
-
!text.includes(
|
|
99
|
-
!text.includes(
|
|
116
|
+
!text.includes("Gemini") &&
|
|
117
|
+
!text.includes("Help") &&
|
|
118
|
+
!text.includes("Settings") &&
|
|
119
|
+
!text.includes("Prompt:") &&
|
|
120
|
+
!text.includes("Response:")
|
|
100
121
|
) {
|
|
101
122
|
title = text;
|
|
102
|
-
console.log(
|
|
123
|
+
console.log("[Gemini Parser] Title set from Strategy 4:", title);
|
|
103
124
|
break;
|
|
104
125
|
}
|
|
105
126
|
}
|
|
@@ -107,25 +128,30 @@ export class GeminiParser extends ChatParser {
|
|
|
107
128
|
|
|
108
129
|
// Strategy 5: Top Bar or Sidebar (original logic)
|
|
109
130
|
if (!title) {
|
|
110
|
-
console.log(
|
|
131
|
+
console.log(
|
|
132
|
+
"[Gemini Parser] Strategy 5: Looking for title in top bar/sidebar...",
|
|
133
|
+
);
|
|
111
134
|
const possibleHeaders = document.querySelectorAll(
|
|
112
135
|
'h1, button[aria-haspopup="true"], button[aria-expanded]',
|
|
113
136
|
);
|
|
114
|
-
console.log(
|
|
137
|
+
console.log(
|
|
138
|
+
"[Gemini Parser] Found possible headers:",
|
|
139
|
+
possibleHeaders.length,
|
|
140
|
+
);
|
|
115
141
|
|
|
116
142
|
for (const el of possibleHeaders) {
|
|
117
143
|
if (isInsideMessage(el)) continue;
|
|
118
144
|
const text = el.innerText.trim();
|
|
119
145
|
if (
|
|
120
146
|
text.length > 5 &&
|
|
121
|
-
!text.includes(
|
|
122
|
-
!text.includes(
|
|
123
|
-
!text.includes(
|
|
147
|
+
!text.includes("Gemini") &&
|
|
148
|
+
!text.includes("Help") &&
|
|
149
|
+
!text.includes("Settings")
|
|
124
150
|
) {
|
|
125
151
|
const rect = el.getBoundingClientRect();
|
|
126
152
|
if (rect.top < 100 && rect.left > 50) {
|
|
127
153
|
title = text;
|
|
128
|
-
console.log(
|
|
154
|
+
console.log("[Gemini Parser] Title set from Strategy 5:", title);
|
|
129
155
|
break;
|
|
130
156
|
}
|
|
131
157
|
}
|
|
@@ -133,80 +159,90 @@ export class GeminiParser extends ChatParser {
|
|
|
133
159
|
}
|
|
134
160
|
|
|
135
161
|
if (!title || title.length < 2) {
|
|
136
|
-
title =
|
|
162
|
+
title = "Gemini Conversation";
|
|
137
163
|
}
|
|
138
164
|
|
|
139
|
-
console.log(
|
|
165
|
+
console.log("[Gemini Parser] Final title:", title);
|
|
140
166
|
|
|
141
167
|
const messages = [];
|
|
142
168
|
const seenTexts = new Set();
|
|
143
169
|
|
|
144
|
-
console.log(
|
|
170
|
+
console.log("[Gemini Parser] Starting content extraction...");
|
|
145
171
|
let extractionAttempted = false;
|
|
146
172
|
|
|
147
173
|
// 2. Content Extraction - Enhanced for Deep Research
|
|
148
174
|
// Try multiple strategies to extract content
|
|
149
175
|
|
|
150
176
|
// Strategy 1: Original conversation containers
|
|
151
|
-
console.log(
|
|
152
|
-
|
|
153
|
-
|
|
177
|
+
console.log(
|
|
178
|
+
"[Gemini Parser] Strategy 1: Looking for conversation containers...",
|
|
179
|
+
);
|
|
180
|
+
const conversationContainers = document.querySelectorAll(
|
|
181
|
+
".conversation-container",
|
|
182
|
+
);
|
|
183
|
+
console.log(
|
|
184
|
+
"[Gemini Parser] Found conversation containers:",
|
|
185
|
+
conversationContainers.length,
|
|
186
|
+
);
|
|
154
187
|
if (conversationContainers.length > 0) {
|
|
155
|
-
console.log(
|
|
188
|
+
console.log("[Gemini Parser] Processing conversation containers...");
|
|
156
189
|
extractionAttempted = true;
|
|
157
190
|
conversationContainers.forEach((container) => {
|
|
158
|
-
console.log(
|
|
191
|
+
console.log("[Gemini Parser] Processing conversation container...");
|
|
159
192
|
|
|
160
193
|
// First, check for user query
|
|
161
|
-
const userQuery = container.querySelector(
|
|
194
|
+
const userQuery = container.querySelector("user-query");
|
|
162
195
|
if (userQuery) {
|
|
163
|
-
console.log(
|
|
164
|
-
const queryText = userQuery.querySelector(
|
|
196
|
+
console.log("[Gemini Parser] Found user query...");
|
|
197
|
+
const queryText = userQuery.querySelector(".query-text");
|
|
165
198
|
if (queryText) {
|
|
166
|
-
console.log(
|
|
199
|
+
console.log("[Gemini Parser] Found query text...");
|
|
167
200
|
const clone = queryText.cloneNode(true);
|
|
168
201
|
clone
|
|
169
|
-
.querySelectorAll(
|
|
202
|
+
.querySelectorAll(
|
|
203
|
+
'.cdk-visually-hidden, [class*="screen-reader"]',
|
|
204
|
+
)
|
|
170
205
|
.forEach((el) => el.remove());
|
|
171
206
|
const userText = clone.innerText.trim();
|
|
172
207
|
if (userText && !seenTexts.has(userText)) {
|
|
173
208
|
seenTexts.add(userText);
|
|
174
209
|
messages.push({
|
|
175
|
-
role:
|
|
210
|
+
role: "User",
|
|
176
211
|
content: userText,
|
|
177
212
|
});
|
|
178
213
|
console.log(
|
|
179
|
-
|
|
180
|
-
userText.substring(0, 50) +
|
|
214
|
+
"[Gemini Parser] Added user message:",
|
|
215
|
+
userText.substring(0, 50) + "...",
|
|
181
216
|
);
|
|
182
217
|
}
|
|
183
218
|
}
|
|
184
219
|
}
|
|
185
220
|
|
|
186
221
|
// Then, check for model response
|
|
187
|
-
const modelResponse = container.querySelector(
|
|
222
|
+
const modelResponse = container.querySelector("model-response");
|
|
188
223
|
if (modelResponse) {
|
|
189
|
-
console.log(
|
|
190
|
-
const messageContent =
|
|
224
|
+
console.log("[Gemini Parser] Found model response...");
|
|
225
|
+
const messageContent =
|
|
226
|
+
modelResponse.querySelector("message-content");
|
|
191
227
|
if (messageContent) {
|
|
192
|
-
console.log(
|
|
228
|
+
console.log("[Gemini Parser] Found message content...");
|
|
193
229
|
const markdownDiv = messageContent.querySelector(
|
|
194
|
-
|
|
230
|
+
".markdown.markdown-main-panel, .markdown",
|
|
195
231
|
);
|
|
196
232
|
if (markdownDiv) {
|
|
197
|
-
console.log(
|
|
233
|
+
console.log("[Gemini Parser] Found markdown div...");
|
|
198
234
|
// Clone to avoid modifying the original DOM
|
|
199
235
|
const clone = markdownDiv.cloneNode(true);
|
|
200
236
|
|
|
201
237
|
// Remove UI elements that shouldn't be in the export
|
|
202
238
|
clone
|
|
203
239
|
.querySelectorAll(
|
|
204
|
-
|
|
240
|
+
"button, .thoughts-container, .thoughts-wrapper, model-thoughts, .table-footer, .hide-from-message-actions",
|
|
205
241
|
)
|
|
206
242
|
.forEach((el) => el.remove());
|
|
207
243
|
|
|
208
244
|
// Remove response-element wrappers (they contain export buttons)
|
|
209
|
-
clone.querySelectorAll(
|
|
245
|
+
clone.querySelectorAll("response-element").forEach((el) => {
|
|
210
246
|
// Keep the table but remove the wrapper
|
|
211
247
|
while (el.firstChild) {
|
|
212
248
|
el.parentNode.insertBefore(el.firstChild, el);
|
|
@@ -216,25 +252,28 @@ export class GeminiParser extends ChatParser {
|
|
|
216
252
|
|
|
217
253
|
// Convert to markdown
|
|
218
254
|
const text = convertToMarkdown(clone);
|
|
219
|
-
console.log(
|
|
220
|
-
|
|
255
|
+
console.log(
|
|
256
|
+
"[Gemini Parser] Converted to markdown, length:",
|
|
257
|
+
text.length,
|
|
258
|
+
);
|
|
259
|
+
console.log("[Gemini Parser] Full markdown content:");
|
|
221
260
|
console.log(text);
|
|
222
|
-
console.log(
|
|
261
|
+
console.log("[Gemini Parser] End of markdown content");
|
|
223
262
|
|
|
224
263
|
if (text && text.trim() && !seenTexts.has(text.trim())) {
|
|
225
264
|
seenTexts.add(text.trim());
|
|
226
265
|
messages.push({
|
|
227
|
-
role:
|
|
266
|
+
role: "Model",
|
|
228
267
|
content: text.trim(),
|
|
229
268
|
});
|
|
230
269
|
console.log(
|
|
231
|
-
|
|
232
|
-
text.substring(0, 50) +
|
|
270
|
+
"[Gemini Parser] Added model message:",
|
|
271
|
+
text.substring(0, 50) + "...",
|
|
233
272
|
);
|
|
234
273
|
}
|
|
235
274
|
} else {
|
|
236
275
|
console.log(
|
|
237
|
-
|
|
276
|
+
"[Gemini Parser] No markdown div found, trying comprehensive content extraction...",
|
|
238
277
|
);
|
|
239
278
|
|
|
240
279
|
// Strategy 1: Look for content in nested elements within message-content
|
|
@@ -245,53 +284,60 @@ export class GeminiParser extends ChatParser {
|
|
|
245
284
|
'div[class*="analysis"]',
|
|
246
285
|
'div[class*="section"]',
|
|
247
286
|
'div[class*="paragraph"]',
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
287
|
+
"p",
|
|
288
|
+
"article",
|
|
289
|
+
"section",
|
|
251
290
|
];
|
|
252
291
|
|
|
253
292
|
let foundContent = false;
|
|
254
293
|
for (const selector of nestedSelectors) {
|
|
255
|
-
const nestedElements =
|
|
294
|
+
const nestedElements =
|
|
295
|
+
messageContent.querySelectorAll(selector);
|
|
256
296
|
console.log(
|
|
257
|
-
|
|
297
|
+
"[Gemini Parser] Looking for nested elements with selector:",
|
|
258
298
|
selector,
|
|
259
|
-
|
|
299
|
+
"found:",
|
|
260
300
|
nestedElements.length,
|
|
261
301
|
);
|
|
262
302
|
|
|
263
303
|
nestedElements.forEach((element) => {
|
|
264
304
|
const text = element.innerText.trim();
|
|
265
305
|
if (text.length > 100) {
|
|
266
|
-
console.log('[Gemini Parser] Found nested content, length:', text.length);
|
|
267
306
|
console.log(
|
|
268
|
-
|
|
269
|
-
text.
|
|
307
|
+
"[Gemini Parser] Found nested content, length:",
|
|
308
|
+
text.length,
|
|
309
|
+
);
|
|
310
|
+
console.log(
|
|
311
|
+
"[Gemini Parser] Nested content preview:",
|
|
312
|
+
text.substring(0, 200) + "...",
|
|
270
313
|
);
|
|
271
314
|
|
|
272
315
|
const isDeepResearch =
|
|
273
|
-
text.includes(
|
|
274
|
-
text.includes(
|
|
275
|
-
text.includes(
|
|
276
|
-
text.includes(
|
|
277
|
-
text.includes(
|
|
278
|
-
text.includes(
|
|
279
|
-
text.includes(
|
|
280
|
-
text.includes(
|
|
281
|
-
text.includes(
|
|
282
|
-
text.includes(
|
|
283
|
-
text.includes(
|
|
284
|
-
|
|
285
|
-
console.log(
|
|
316
|
+
text.includes("research") ||
|
|
317
|
+
text.includes("analysis") ||
|
|
318
|
+
text.includes("findings") ||
|
|
319
|
+
text.includes("cost") ||
|
|
320
|
+
text.includes("sweetener") ||
|
|
321
|
+
text.includes("projection") ||
|
|
322
|
+
text.includes("historical") ||
|
|
323
|
+
text.includes("economic") ||
|
|
324
|
+
text.includes("market") ||
|
|
325
|
+
text.includes("price") ||
|
|
326
|
+
text.includes("industry");
|
|
327
|
+
|
|
328
|
+
console.log(
|
|
329
|
+
"[Gemini Parser] Is Deep Research content:",
|
|
330
|
+
isDeepResearch,
|
|
331
|
+
);
|
|
286
332
|
|
|
287
333
|
if (!seenTexts.has(text)) {
|
|
288
334
|
seenTexts.add(text);
|
|
289
335
|
messages.push({
|
|
290
|
-
role:
|
|
336
|
+
role: "Model",
|
|
291
337
|
content: text,
|
|
292
338
|
});
|
|
293
339
|
console.log(
|
|
294
|
-
|
|
340
|
+
"[Gemini Parser] Added nested content, Deep Research:",
|
|
295
341
|
isDeepResearch,
|
|
296
342
|
);
|
|
297
343
|
foundContent = true;
|
|
@@ -304,32 +350,39 @@ export class GeminiParser extends ChatParser {
|
|
|
304
350
|
|
|
305
351
|
// Strategy 2: Look for content in parent/sibling elements of model-response
|
|
306
352
|
if (!foundContent) {
|
|
307
|
-
console.log(
|
|
353
|
+
console.log(
|
|
354
|
+
"[Gemini Parser] Trying parent/sibling element extraction...",
|
|
355
|
+
);
|
|
308
356
|
const parentContainer = modelResponse.parentElement;
|
|
309
357
|
if (parentContainer) {
|
|
310
358
|
const siblings = parentContainer.children;
|
|
311
|
-
console.log(
|
|
359
|
+
console.log(
|
|
360
|
+
"[Gemini Parser] Checking siblings, count:",
|
|
361
|
+
siblings.length,
|
|
362
|
+
);
|
|
312
363
|
|
|
313
364
|
Array.from(siblings).forEach((sibling) => {
|
|
314
365
|
if (sibling !== modelResponse) {
|
|
315
366
|
const text = sibling.innerText.trim();
|
|
316
367
|
if (text.length > 200) {
|
|
317
368
|
console.log(
|
|
318
|
-
|
|
369
|
+
"[Gemini Parser] Found sibling content, length:",
|
|
319
370
|
text.length,
|
|
320
371
|
);
|
|
321
372
|
console.log(
|
|
322
|
-
|
|
323
|
-
text.substring(0, 200) +
|
|
373
|
+
"[Gemini Parser] Sibling content preview:",
|
|
374
|
+
text.substring(0, 200) + "...",
|
|
324
375
|
);
|
|
325
376
|
|
|
326
377
|
if (!seenTexts.has(text)) {
|
|
327
378
|
seenTexts.add(text);
|
|
328
379
|
messages.push({
|
|
329
|
-
role:
|
|
380
|
+
role: "Model",
|
|
330
381
|
content: text,
|
|
331
382
|
});
|
|
332
|
-
console.log(
|
|
383
|
+
console.log(
|
|
384
|
+
"[Gemini Parser] Added sibling content",
|
|
385
|
+
);
|
|
333
386
|
foundContent = true;
|
|
334
387
|
}
|
|
335
388
|
}
|
|
@@ -340,23 +393,30 @@ export class GeminiParser extends ChatParser {
|
|
|
340
393
|
|
|
341
394
|
// Strategy 3: Look for content in the entire conversation container (outside model-response)
|
|
342
395
|
if (!foundContent) {
|
|
343
|
-
console.log(
|
|
396
|
+
console.log(
|
|
397
|
+
"[Gemini Parser] Trying full container content extraction...",
|
|
398
|
+
);
|
|
344
399
|
const containerText = container.innerText.trim();
|
|
345
|
-
console.log(
|
|
400
|
+
console.log(
|
|
401
|
+
"[Gemini Parser] Full container text length:",
|
|
402
|
+
containerText.length,
|
|
403
|
+
);
|
|
346
404
|
|
|
347
405
|
if (containerText.length > 500) {
|
|
348
406
|
console.log(
|
|
349
|
-
|
|
350
|
-
containerText.substring(0, 200) +
|
|
407
|
+
"[Gemini Parser] Full container content preview:",
|
|
408
|
+
containerText.substring(0, 200) + "...",
|
|
351
409
|
);
|
|
352
410
|
|
|
353
411
|
if (!seenTexts.has(containerText)) {
|
|
354
412
|
seenTexts.add(containerText);
|
|
355
413
|
messages.push({
|
|
356
|
-
role:
|
|
414
|
+
role: "Model",
|
|
357
415
|
content: containerText,
|
|
358
416
|
});
|
|
359
|
-
console.log(
|
|
417
|
+
console.log(
|
|
418
|
+
"[Gemini Parser] Added full container content",
|
|
419
|
+
);
|
|
360
420
|
foundContent = true;
|
|
361
421
|
}
|
|
362
422
|
}
|
|
@@ -365,33 +425,39 @@ export class GeminiParser extends ChatParser {
|
|
|
365
425
|
// Strategy 4: Last resort - get all text from message-content
|
|
366
426
|
if (!foundContent) {
|
|
367
427
|
const allText = messageContent.innerText.trim();
|
|
368
|
-
console.log('[Gemini Parser] Last resort text length:', allText.length);
|
|
369
428
|
console.log(
|
|
370
|
-
|
|
371
|
-
allText.
|
|
429
|
+
"[Gemini Parser] Last resort text length:",
|
|
430
|
+
allText.length,
|
|
431
|
+
);
|
|
432
|
+
console.log(
|
|
433
|
+
"[Gemini Parser] Last resort text preview:",
|
|
434
|
+
allText.substring(0, 200) + "...",
|
|
372
435
|
);
|
|
373
436
|
|
|
374
437
|
if (allText && allText.length > 50) {
|
|
375
438
|
// Check if this looks like Deep Research content
|
|
376
439
|
const isDeepResearch =
|
|
377
|
-
allText.includes(
|
|
378
|
-
allText.includes(
|
|
379
|
-
allText.includes(
|
|
380
|
-
allText.includes(
|
|
381
|
-
allText.includes(
|
|
382
|
-
allText.includes(
|
|
383
|
-
allText.includes(
|
|
440
|
+
allText.includes("research") ||
|
|
441
|
+
allText.includes("analysis") ||
|
|
442
|
+
allText.includes("findings") ||
|
|
443
|
+
allText.includes("cost") ||
|
|
444
|
+
allText.includes("sweetener") ||
|
|
445
|
+
allText.includes("projection") ||
|
|
446
|
+
allText.includes("historical");
|
|
384
447
|
|
|
385
|
-
console.log(
|
|
448
|
+
console.log(
|
|
449
|
+
"[Gemini Parser] Is Deep Research content:",
|
|
450
|
+
isDeepResearch,
|
|
451
|
+
);
|
|
386
452
|
|
|
387
453
|
if (!seenTexts.has(allText)) {
|
|
388
454
|
seenTexts.add(allText);
|
|
389
455
|
messages.push({
|
|
390
|
-
role:
|
|
456
|
+
role: "Model",
|
|
391
457
|
content: allText,
|
|
392
458
|
});
|
|
393
459
|
console.log(
|
|
394
|
-
|
|
460
|
+
"[Gemini Parser] Added last resort model message, Deep Research:",
|
|
395
461
|
isDeepResearch,
|
|
396
462
|
);
|
|
397
463
|
}
|
|
@@ -400,32 +466,38 @@ export class GeminiParser extends ChatParser {
|
|
|
400
466
|
}
|
|
401
467
|
} else {
|
|
402
468
|
console.log(
|
|
403
|
-
|
|
469
|
+
"[Gemini Parser] No message-content found, trying direct model-response text...",
|
|
404
470
|
);
|
|
405
471
|
// Fallback: get text directly from model-response
|
|
406
472
|
const directText = modelResponse.innerText.trim();
|
|
407
|
-
console.log(
|
|
473
|
+
console.log(
|
|
474
|
+
"[Gemini Parser] Direct model response text length:",
|
|
475
|
+
directText.length,
|
|
476
|
+
);
|
|
408
477
|
|
|
409
478
|
if (directText && directText.length > 50) {
|
|
410
479
|
const isDeepResearch =
|
|
411
|
-
directText.includes(
|
|
412
|
-
directText.includes(
|
|
413
|
-
directText.includes(
|
|
414
|
-
directText.includes(
|
|
415
|
-
directText.includes(
|
|
416
|
-
directText.includes(
|
|
417
|
-
directText.includes(
|
|
480
|
+
directText.includes("research") ||
|
|
481
|
+
directText.includes("analysis") ||
|
|
482
|
+
directText.includes("findings") ||
|
|
483
|
+
directText.includes("cost") ||
|
|
484
|
+
directText.includes("sweetener") ||
|
|
485
|
+
directText.includes("projection") ||
|
|
486
|
+
directText.includes("historical");
|
|
418
487
|
|
|
419
|
-
console.log(
|
|
488
|
+
console.log(
|
|
489
|
+
"[Gemini Parser] Direct text is Deep Research:",
|
|
490
|
+
isDeepResearch,
|
|
491
|
+
);
|
|
420
492
|
|
|
421
493
|
if (!seenTexts.has(directText)) {
|
|
422
494
|
seenTexts.add(directText);
|
|
423
495
|
messages.push({
|
|
424
|
-
role:
|
|
496
|
+
role: "Model",
|
|
425
497
|
content: directText,
|
|
426
498
|
});
|
|
427
499
|
console.log(
|
|
428
|
-
|
|
500
|
+
"[Gemini Parser] Added direct model message, Deep Research:",
|
|
429
501
|
isDeepResearch,
|
|
430
502
|
);
|
|
431
503
|
}
|
|
@@ -438,33 +510,48 @@ export class GeminiParser extends ChatParser {
|
|
|
438
510
|
// Strategy 2: Deep Research content extraction
|
|
439
511
|
if (!extractionAttempted) {
|
|
440
512
|
console.log(
|
|
441
|
-
|
|
513
|
+
"[Gemini Parser] Strategy 2: No conversation containers found, trying Deep Research panel...",
|
|
442
514
|
);
|
|
443
515
|
extractionAttempted = true;
|
|
444
516
|
|
|
445
517
|
// First try Deep Research immersive panel structure
|
|
446
|
-
console.log(
|
|
447
|
-
|
|
448
|
-
|
|
518
|
+
console.log(
|
|
519
|
+
"[Gemini Parser] Looking for deep-research-immersive-panel...",
|
|
520
|
+
);
|
|
521
|
+
const deepResearchPanel = document.querySelector(
|
|
522
|
+
"deep-research-immersive-panel",
|
|
523
|
+
);
|
|
524
|
+
console.log(
|
|
525
|
+
"[Gemini Parser] Deep Research panel found:",
|
|
526
|
+
!!deepResearchPanel,
|
|
527
|
+
);
|
|
449
528
|
|
|
450
529
|
if (deepResearchPanel) {
|
|
451
|
-
console.log(
|
|
530
|
+
console.log("[Gemini Parser] Processing Deep Research panel...");
|
|
452
531
|
|
|
453
532
|
// Extract title from panel
|
|
454
|
-
const panelTitle = deepResearchPanel.querySelector(
|
|
533
|
+
const panelTitle = deepResearchPanel.querySelector(
|
|
534
|
+
".title-text, h2, h1",
|
|
535
|
+
);
|
|
455
536
|
if (panelTitle && !title) {
|
|
456
537
|
const titleText = panelTitle.innerText.trim();
|
|
457
|
-
console.log(
|
|
458
|
-
if (titleText.length > 5 && !titleText.includes(
|
|
538
|
+
console.log("[Gemini Parser] Found panel title:", titleText);
|
|
539
|
+
if (titleText.length > 5 && !titleText.includes("Gemini")) {
|
|
459
540
|
title = titleText;
|
|
460
|
-
console.log(
|
|
541
|
+
console.log("[Gemini Parser] Title updated from panel:", title);
|
|
461
542
|
}
|
|
462
543
|
}
|
|
463
544
|
|
|
464
545
|
// Extract content from panel
|
|
465
|
-
console.log(
|
|
466
|
-
|
|
467
|
-
|
|
546
|
+
console.log(
|
|
547
|
+
"[Gemini Parser] Calling extractDeepResearchPanelContent...",
|
|
548
|
+
);
|
|
549
|
+
const panelContent =
|
|
550
|
+
this.extractDeepResearchPanelContent(deepResearchPanel);
|
|
551
|
+
console.log(
|
|
552
|
+
"[Gemini Parser] Panel content extracted, sections:",
|
|
553
|
+
panelContent.length,
|
|
554
|
+
);
|
|
468
555
|
|
|
469
556
|
if (panelContent.length > 0) {
|
|
470
557
|
panelContent.forEach((section) => {
|
|
@@ -475,49 +562,63 @@ export class GeminiParser extends ChatParser {
|
|
|
475
562
|
content: section.content,
|
|
476
563
|
});
|
|
477
564
|
console.log(
|
|
478
|
-
|
|
565
|
+
"[Gemini Parser] Added panel section, role:",
|
|
479
566
|
section.role,
|
|
480
|
-
|
|
567
|
+
"length:",
|
|
481
568
|
section.content.length,
|
|
482
569
|
);
|
|
483
570
|
}
|
|
484
571
|
});
|
|
485
572
|
} else {
|
|
486
|
-
console.log(
|
|
573
|
+
console.log(
|
|
574
|
+
"[Gemini Parser] No panel content found, trying fallback...",
|
|
575
|
+
);
|
|
487
576
|
}
|
|
488
577
|
} else {
|
|
489
|
-
console.log(
|
|
578
|
+
console.log("[Gemini Parser] No Deep Research panel found");
|
|
490
579
|
}
|
|
491
580
|
|
|
492
581
|
// Fallback: Look for content in main, article, or content areas
|
|
493
582
|
if (messages.length === 0) {
|
|
494
|
-
console.log(
|
|
583
|
+
console.log(
|
|
584
|
+
"[Gemini Parser] Strategy 3: Trying fallback content extraction...",
|
|
585
|
+
);
|
|
495
586
|
const contentSelectors = [
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
587
|
+
"main",
|
|
588
|
+
"article",
|
|
589
|
+
".content",
|
|
590
|
+
".main-content",
|
|
500
591
|
'[role="main"]',
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
592
|
+
".conversation-content",
|
|
593
|
+
".chat-content",
|
|
594
|
+
".message-content",
|
|
504
595
|
];
|
|
505
596
|
|
|
506
597
|
let contentFound = false;
|
|
507
598
|
|
|
508
599
|
for (const selector of contentSelectors) {
|
|
509
|
-
console.log(
|
|
600
|
+
console.log("[Gemini Parser] Trying selector:", selector);
|
|
510
601
|
const contentElement = document.querySelector(selector);
|
|
511
602
|
if (contentElement) {
|
|
512
|
-
console.log(
|
|
603
|
+
console.log(
|
|
604
|
+
"[Gemini Parser] Found content element:",
|
|
605
|
+
!!contentElement,
|
|
606
|
+
);
|
|
513
607
|
// Extract all text content from the main content area
|
|
514
608
|
const textContent = contentElement.innerText.trim();
|
|
515
|
-
console.log(
|
|
609
|
+
console.log(
|
|
610
|
+
"[Gemini Parser] Text content length:",
|
|
611
|
+
textContent.length,
|
|
612
|
+
);
|
|
516
613
|
|
|
517
614
|
if (textContent && textContent.length > 100) {
|
|
518
615
|
// Try to identify user prompts and responses
|
|
519
|
-
const sections =
|
|
520
|
-
|
|
616
|
+
const sections =
|
|
617
|
+
this.extractDeepResearchSections(contentElement);
|
|
618
|
+
console.log(
|
|
619
|
+
"[Gemini Parser] Extracted sections:",
|
|
620
|
+
sections.length,
|
|
621
|
+
);
|
|
521
622
|
|
|
522
623
|
if (sections.length > 0) {
|
|
523
624
|
sections.forEach((section) => {
|
|
@@ -527,22 +628,31 @@ export class GeminiParser extends ChatParser {
|
|
|
527
628
|
role: section.role,
|
|
528
629
|
content: section.content,
|
|
529
630
|
});
|
|
530
|
-
console.log(
|
|
631
|
+
console.log(
|
|
632
|
+
"[Gemini Parser] Added fallback section, role:",
|
|
633
|
+
section.role,
|
|
634
|
+
);
|
|
531
635
|
}
|
|
532
636
|
});
|
|
533
637
|
contentFound = true;
|
|
534
638
|
break;
|
|
535
639
|
} else {
|
|
536
640
|
// If we can't parse sections, treat the whole content as a response
|
|
537
|
-
console.log(
|
|
641
|
+
console.log(
|
|
642
|
+
"[Gemini Parser] Treating whole content as response...",
|
|
643
|
+
);
|
|
538
644
|
const markdown = convertToMarkdown(contentElement);
|
|
539
|
-
if (
|
|
645
|
+
if (
|
|
646
|
+
markdown &&
|
|
647
|
+
markdown.trim() &&
|
|
648
|
+
!seenTexts.has(markdown.trim())
|
|
649
|
+
) {
|
|
540
650
|
seenTexts.add(markdown.trim());
|
|
541
651
|
messages.push({
|
|
542
|
-
role:
|
|
652
|
+
role: "Model",
|
|
543
653
|
content: markdown.trim(),
|
|
544
654
|
});
|
|
545
|
-
console.log(
|
|
655
|
+
console.log("[Gemini Parser] Added fallback message");
|
|
546
656
|
contentFound = true;
|
|
547
657
|
break;
|
|
548
658
|
}
|
|
@@ -553,14 +663,22 @@ export class GeminiParser extends ChatParser {
|
|
|
553
663
|
|
|
554
664
|
// Strategy 3: Fallback - look for any meaningful content
|
|
555
665
|
if (!contentFound) {
|
|
556
|
-
console.log(
|
|
666
|
+
console.log(
|
|
667
|
+
"[Gemini Parser] Strategy 4: Final fallback - extracting body content...",
|
|
668
|
+
);
|
|
557
669
|
const bodyContent = document.body.innerText.trim();
|
|
558
|
-
console.log(
|
|
670
|
+
console.log(
|
|
671
|
+
"[Gemini Parser] Body content length:",
|
|
672
|
+
bodyContent.length,
|
|
673
|
+
);
|
|
559
674
|
|
|
560
675
|
if (bodyContent && bodyContent.length > 200) {
|
|
561
676
|
// Try to extract structured content from body
|
|
562
677
|
const sections = this.extractDeepResearchSections(document.body);
|
|
563
|
-
console.log(
|
|
678
|
+
console.log(
|
|
679
|
+
"[Gemini Parser] Body sections extracted:",
|
|
680
|
+
sections.length,
|
|
681
|
+
);
|
|
564
682
|
|
|
565
683
|
if (sections.length > 0) {
|
|
566
684
|
sections.forEach((section) => {
|
|
@@ -570,30 +688,37 @@ export class GeminiParser extends ChatParser {
|
|
|
570
688
|
role: section.role,
|
|
571
689
|
content: section.content,
|
|
572
690
|
});
|
|
573
|
-
console.log(
|
|
691
|
+
console.log(
|
|
692
|
+
"[Gemini Parser] Added body section, role:",
|
|
693
|
+
section.role,
|
|
694
|
+
);
|
|
574
695
|
}
|
|
575
696
|
});
|
|
576
697
|
} else {
|
|
577
698
|
// Last resort - treat as single response
|
|
578
|
-
console.log(
|
|
699
|
+
console.log(
|
|
700
|
+
"[Gemini Parser] Last resort - treating as single response...",
|
|
701
|
+
);
|
|
579
702
|
messages.push({
|
|
580
|
-
role:
|
|
703
|
+
role: "Model",
|
|
581
704
|
content: bodyContent,
|
|
582
705
|
});
|
|
583
|
-
console.log(
|
|
706
|
+
console.log("[Gemini Parser] Added last resort message");
|
|
584
707
|
}
|
|
585
708
|
}
|
|
586
709
|
}
|
|
587
710
|
}
|
|
588
711
|
}
|
|
589
712
|
|
|
590
|
-
console.log(
|
|
591
|
-
console.log(
|
|
713
|
+
console.log("[Gemini Parser] Total messages extracted:", messages.length);
|
|
714
|
+
console.log("[Gemini Parser] ========== FINISHING PARSE() ==========");
|
|
592
715
|
|
|
593
716
|
const currentUrl =
|
|
594
|
-
typeof window !==
|
|
717
|
+
typeof window !== "undefined" && window.location
|
|
718
|
+
? window.location.href || ""
|
|
719
|
+
: "";
|
|
595
720
|
const metadata = {
|
|
596
|
-
Source:
|
|
721
|
+
Source: "Gemini",
|
|
597
722
|
Date: new Date().toLocaleString(),
|
|
598
723
|
Link: currentUrl,
|
|
599
724
|
};
|
|
@@ -605,15 +730,17 @@ export class GeminiParser extends ChatParser {
|
|
|
605
730
|
metadata: metadata,
|
|
606
731
|
};
|
|
607
732
|
} catch (error) {
|
|
608
|
-
console.error(
|
|
733
|
+
console.error("[Gemini Parser] Error during parsing:", error);
|
|
609
734
|
const currentUrl =
|
|
610
|
-
typeof window !==
|
|
735
|
+
typeof window !== "undefined" && window.location
|
|
736
|
+
? window.location.href || ""
|
|
737
|
+
: "";
|
|
611
738
|
return {
|
|
612
|
-
title:
|
|
739
|
+
title: "Gemini Conversation",
|
|
613
740
|
messages: [],
|
|
614
741
|
url: currentUrl,
|
|
615
742
|
metadata: {
|
|
616
|
-
Source:
|
|
743
|
+
Source: "Gemini",
|
|
617
744
|
Date: new Date().toLocaleString(),
|
|
618
745
|
Link: currentUrl,
|
|
619
746
|
},
|
|
@@ -623,9 +750,9 @@ export class GeminiParser extends ChatParser {
|
|
|
623
750
|
|
|
624
751
|
// Helper method to extract sections from Deep Research content
|
|
625
752
|
extractDeepResearchSections(contentElement) {
|
|
626
|
-
console.log(
|
|
753
|
+
console.log("[Gemini Parser] Extracting Deep Research sections...");
|
|
627
754
|
const sections = [];
|
|
628
|
-
const text = contentElement.innerText ||
|
|
755
|
+
const text = contentElement.innerText || "";
|
|
629
756
|
|
|
630
757
|
// Look for common Deep Research patterns
|
|
631
758
|
const patterns = [
|
|
@@ -638,8 +765,10 @@ export class GeminiParser extends ChatParser {
|
|
|
638
765
|
},
|
|
639
766
|
// Pattern 2: Question/Answer format
|
|
640
767
|
{
|
|
641
|
-
promptRegex:
|
|
642
|
-
|
|
768
|
+
promptRegex:
|
|
769
|
+
/(?:Question|Q)[:\s]*\n*([\s\S]*?)(?=\n\s*(?:Answer|A|Response)|$)/i,
|
|
770
|
+
responseRegex:
|
|
771
|
+
/(?:Answer|A|Response)[:\s]*\n*([\s\S]*?)(?=\n\s*(?:Question|Q)|$)/i,
|
|
643
772
|
},
|
|
644
773
|
// Pattern 3: Look for research plan and results
|
|
645
774
|
{
|
|
@@ -652,47 +781,53 @@ export class GeminiParser extends ChatParser {
|
|
|
652
781
|
|
|
653
782
|
// Try each pattern
|
|
654
783
|
for (const pattern of patterns) {
|
|
655
|
-
console.log(
|
|
784
|
+
console.log("[Gemini Parser] Trying pattern...");
|
|
656
785
|
const promptMatches = text.match(pattern.promptRegex);
|
|
657
786
|
const responseMatches = text.match(pattern.responseRegex);
|
|
658
787
|
|
|
659
788
|
if (promptMatches && promptMatches[1]) {
|
|
660
789
|
const promptContent = promptMatches[1].trim();
|
|
661
|
-
console.log(
|
|
790
|
+
console.log(
|
|
791
|
+
"[Gemini Parser] Found prompt content, length:",
|
|
792
|
+
promptContent.length,
|
|
793
|
+
);
|
|
662
794
|
if (promptContent.length > 20) {
|
|
663
795
|
sections.push({
|
|
664
|
-
role:
|
|
796
|
+
role: "User",
|
|
665
797
|
content: promptContent,
|
|
666
798
|
});
|
|
667
|
-
console.log(
|
|
799
|
+
console.log("[Gemini Parser] Added prompt section");
|
|
668
800
|
}
|
|
669
801
|
}
|
|
670
802
|
|
|
671
803
|
if (responseMatches && responseMatches[1]) {
|
|
672
804
|
const responseContent = responseMatches[1].trim();
|
|
673
|
-
console.log(
|
|
805
|
+
console.log(
|
|
806
|
+
"[Gemini Parser] Found response content, length:",
|
|
807
|
+
responseContent.length,
|
|
808
|
+
);
|
|
674
809
|
if (responseContent.length > 50) {
|
|
675
810
|
sections.push({
|
|
676
|
-
role:
|
|
811
|
+
role: "Model",
|
|
677
812
|
content: responseContent,
|
|
678
813
|
});
|
|
679
|
-
console.log(
|
|
814
|
+
console.log("[Gemini Parser] Added response section");
|
|
680
815
|
}
|
|
681
816
|
}
|
|
682
817
|
|
|
683
818
|
// If we found meaningful sections, stop trying other patterns
|
|
684
819
|
if (sections.length > 0) {
|
|
685
|
-
console.log(
|
|
820
|
+
console.log("[Gemini Parser] Found sections using pattern matching");
|
|
686
821
|
return sections;
|
|
687
822
|
}
|
|
688
823
|
}
|
|
689
824
|
|
|
690
825
|
// If no structured sections found, try to extract based on HTML structure
|
|
691
|
-
console.log(
|
|
826
|
+
console.log("[Gemini Parser] Trying HTML structure extraction...");
|
|
692
827
|
const userElements = contentElement.querySelectorAll(
|
|
693
828
|
'.user-query, .prompt, .question, [data-role="user"]',
|
|
694
829
|
);
|
|
695
|
-
console.log(
|
|
830
|
+
console.log("[Gemini Parser] Found user elements:", userElements.length);
|
|
696
831
|
userElements.forEach((el) => {
|
|
697
832
|
const clone = el.cloneNode(true);
|
|
698
833
|
clone
|
|
@@ -701,10 +836,10 @@ export class GeminiParser extends ChatParser {
|
|
|
701
836
|
const content = clone.innerText.trim();
|
|
702
837
|
if (content.length > 20) {
|
|
703
838
|
sections.push({
|
|
704
|
-
role:
|
|
839
|
+
role: "User",
|
|
705
840
|
content: content,
|
|
706
841
|
});
|
|
707
|
-
console.log(
|
|
842
|
+
console.log("[Gemini Parser] Added user element from HTML structure");
|
|
708
843
|
}
|
|
709
844
|
});
|
|
710
845
|
|
|
@@ -712,21 +847,26 @@ export class GeminiParser extends ChatParser {
|
|
|
712
847
|
const responseElements = contentElement.querySelectorAll(
|
|
713
848
|
'.model-response, .response, .answer, [data-role="model"], .research-content',
|
|
714
849
|
);
|
|
715
|
-
console.log(
|
|
850
|
+
console.log(
|
|
851
|
+
"[Gemini Parser] Found response elements:",
|
|
852
|
+
responseElements.length,
|
|
853
|
+
);
|
|
716
854
|
responseElements.forEach((el) => {
|
|
717
855
|
const content = el.innerText.trim();
|
|
718
856
|
if (content.length > 50) {
|
|
719
857
|
sections.push({
|
|
720
|
-
role:
|
|
858
|
+
role: "Model",
|
|
721
859
|
content: content,
|
|
722
860
|
});
|
|
723
|
-
console.log(
|
|
861
|
+
console.log(
|
|
862
|
+
"[Gemini Parser] Added response element from HTML structure",
|
|
863
|
+
);
|
|
724
864
|
}
|
|
725
865
|
});
|
|
726
866
|
|
|
727
867
|
// If still no sections, try to split by common delimiters
|
|
728
868
|
if (sections.length === 0) {
|
|
729
|
-
console.log(
|
|
869
|
+
console.log("[Gemini Parser] Trying delimiter splitting...");
|
|
730
870
|
const delimiterPatterns = [
|
|
731
871
|
/\n\s*You said\s*\n/i,
|
|
732
872
|
/\n\s*Response\s*\n/i,
|
|
@@ -743,90 +883,98 @@ export class GeminiParser extends ChatParser {
|
|
|
743
883
|
const trimmedPart = part.trim();
|
|
744
884
|
if (trimmedPart.length > 50) {
|
|
745
885
|
// Alternate between User and Model roles
|
|
746
|
-
const role = index % 2 === 0 ?
|
|
886
|
+
const role = index % 2 === 0 ? "User" : "Model";
|
|
747
887
|
sections.push({
|
|
748
888
|
role: role,
|
|
749
889
|
content: trimmedPart,
|
|
750
890
|
});
|
|
751
|
-
console.log(
|
|
891
|
+
console.log("[Gemini Parser] Added delimiter section, role:", role);
|
|
752
892
|
}
|
|
753
893
|
});
|
|
754
894
|
}
|
|
755
895
|
|
|
756
|
-
console.log(
|
|
896
|
+
console.log("[Gemini Parser] Total sections extracted:", sections.length);
|
|
757
897
|
return sections;
|
|
758
898
|
}
|
|
759
899
|
|
|
760
900
|
// Helper method to extract content from Deep Research immersive panel
|
|
761
901
|
extractDeepResearchPanelContent(panelElement) {
|
|
762
|
-
console.log(
|
|
902
|
+
console.log("[Gemini Parser] Looking for Deep Research panel content...");
|
|
763
903
|
const sections = [];
|
|
764
904
|
|
|
765
|
-
console.log(
|
|
905
|
+
console.log("[Gemini Parser] Panel element found:", !!panelElement);
|
|
766
906
|
console.log(
|
|
767
|
-
|
|
907
|
+
"[Gemini Parser] Panel innerText length:",
|
|
768
908
|
panelElement.innerText ? panelElement.innerText.length : 0,
|
|
769
909
|
);
|
|
770
910
|
|
|
771
911
|
try {
|
|
772
912
|
// Look for content within panel
|
|
773
913
|
const contentSelectors = [
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
914
|
+
".markdown",
|
|
915
|
+
".content",
|
|
916
|
+
".research-content",
|
|
917
|
+
".panel-content",
|
|
778
918
|
'div[class*="content"]',
|
|
779
919
|
'div[class*="markdown"]',
|
|
780
920
|
'div[class*="research"]',
|
|
781
921
|
];
|
|
782
922
|
|
|
783
923
|
for (const selector of contentSelectors) {
|
|
784
|
-
console.log(
|
|
924
|
+
console.log("[Gemini Parser] Trying selector:", selector);
|
|
785
925
|
const contentElements = panelElement.querySelectorAll(selector);
|
|
786
|
-
console.log(
|
|
926
|
+
console.log("[Gemini Parser] Found elements:", contentElements.length);
|
|
787
927
|
contentElements.forEach((element) => {
|
|
788
928
|
const text = element.innerText.trim();
|
|
789
929
|
if (text.length > 100) {
|
|
790
930
|
sections.push({
|
|
791
|
-
role:
|
|
931
|
+
role: "Model",
|
|
792
932
|
content: text,
|
|
793
933
|
});
|
|
794
|
-
console.log(
|
|
934
|
+
console.log(
|
|
935
|
+
"[Gemini Parser] Added panel content via selector:",
|
|
936
|
+
selector,
|
|
937
|
+
);
|
|
795
938
|
}
|
|
796
939
|
});
|
|
797
940
|
}
|
|
798
941
|
|
|
799
942
|
// If no structured content found, extract all text from panel
|
|
800
943
|
if (sections.length === 0) {
|
|
801
|
-
console.log(
|
|
944
|
+
console.log(
|
|
945
|
+
"[Gemini Parser] No structured content found, extracting all panel text...",
|
|
946
|
+
);
|
|
802
947
|
const panelText = panelElement.innerText.trim();
|
|
803
|
-
console.log(
|
|
948
|
+
console.log("[Gemini Parser] Panel text length:", panelText.length);
|
|
804
949
|
if (panelText.length > 200) {
|
|
805
950
|
// Try to split into logical sections
|
|
806
951
|
const parts = this.splitIntoSections(panelText);
|
|
807
|
-
console.log(
|
|
952
|
+
console.log("[Gemini Parser] Split into parts:", parts.length);
|
|
808
953
|
parts.forEach((part) => {
|
|
809
954
|
if (part.length > 50) {
|
|
810
955
|
sections.push({
|
|
811
|
-
role:
|
|
956
|
+
role: "Model",
|
|
812
957
|
content: part,
|
|
813
958
|
});
|
|
814
|
-
console.log(
|
|
959
|
+
console.log("[Gemini Parser] Added panel text part");
|
|
815
960
|
}
|
|
816
961
|
});
|
|
817
962
|
}
|
|
818
963
|
}
|
|
819
964
|
} catch (error) {
|
|
820
|
-
console.error(
|
|
965
|
+
console.error("[Gemini Parser] Error extracting panel content:", error);
|
|
821
966
|
}
|
|
822
967
|
|
|
823
|
-
console.log(
|
|
968
|
+
console.log(
|
|
969
|
+
"[Gemini Parser] Panel content extraction complete, sections:",
|
|
970
|
+
sections.length,
|
|
971
|
+
);
|
|
824
972
|
return sections;
|
|
825
973
|
}
|
|
826
974
|
|
|
827
975
|
// Helper method to split text into logical sections
|
|
828
976
|
splitIntoSections(text) {
|
|
829
|
-
console.log(
|
|
977
|
+
console.log("[Gemini Parser] Splitting text into sections...");
|
|
830
978
|
const sections = [];
|
|
831
979
|
|
|
832
980
|
// Try to split by common delimiters
|
|
@@ -846,11 +994,17 @@ export class GeminiParser extends ChatParser {
|
|
|
846
994
|
const cleaned = part.trim();
|
|
847
995
|
if (cleaned.length > 50 && !cleaned.match(/^\d+$/)) {
|
|
848
996
|
sections.push(cleaned);
|
|
849
|
-
console.log(
|
|
997
|
+
console.log(
|
|
998
|
+
"[Gemini Parser] Added split section, length:",
|
|
999
|
+
cleaned.length,
|
|
1000
|
+
);
|
|
850
1001
|
}
|
|
851
1002
|
});
|
|
852
1003
|
|
|
853
|
-
console.log(
|
|
1004
|
+
console.log(
|
|
1005
|
+
"[Gemini Parser] Text splitting complete, sections:",
|
|
1006
|
+
sections.length,
|
|
1007
|
+
);
|
|
854
1008
|
return sections;
|
|
855
1009
|
}
|
|
856
1010
|
}
|