webpeel 0.14.2 → 0.14.4
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/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +11 -4
- package/dist/cache.js.map +1 -1
- package/dist/cli.bundle.cjs +159248 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/agent.js +12 -8
- package/dist/core/agent.js.map +1 -1
- package/dist/core/application-tracker.js +3 -2
- package/dist/core/application-tracker.js.map +1 -1
- package/dist/core/auto-extract.js +6 -4
- package/dist/core/auto-extract.js.map +1 -1
- package/dist/core/browser-fetch.d.ts +90 -0
- package/dist/core/browser-fetch.d.ts.map +1 -0
- package/dist/core/browser-fetch.js +599 -0
- package/dist/core/browser-fetch.js.map +1 -0
- package/dist/core/browser-pool.d.ts +70 -0
- package/dist/core/browser-pool.d.ts.map +1 -0
- package/dist/core/browser-pool.js +378 -0
- package/dist/core/browser-pool.js.map +1 -0
- package/dist/core/change-tracking.js +3 -2
- package/dist/core/change-tracking.js.map +1 -1
- package/dist/core/diff.js +3 -2
- package/dist/core/diff.js.map +1 -1
- package/dist/core/domain-extractors.js +3 -2
- package/dist/core/domain-extractors.js.map +1 -1
- package/dist/core/extract-inline.js +6 -4
- package/dist/core/extract-inline.js.map +1 -1
- package/dist/core/fetcher.d.ts +9 -116
- package/dist/core/fetcher.d.ts.map +1 -1
- package/dist/core/fetcher.js +10 -1484
- package/dist/core/fetcher.js.map +1 -1
- package/dist/core/http-fetch.d.ts +37 -0
- package/dist/core/http-fetch.d.ts.map +1 -0
- package/dist/core/http-fetch.js +618 -0
- package/dist/core/http-fetch.js.map +1 -0
- package/dist/core/metadata.js +18 -12
- package/dist/core/metadata.js.map +1 -1
- package/dist/core/pipeline.d.ts +104 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +623 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/profiles.js +15 -10
- package/dist/core/profiles.js.map +1 -1
- package/dist/core/quick-answer.d.ts.map +1 -1
- package/dist/core/quick-answer.js +120 -9
- package/dist/core/quick-answer.js.map +1 -1
- package/dist/core/rate-governor.js +3 -2
- package/dist/core/rate-governor.js.map +1 -1
- package/dist/core/readability.d.ts.map +1 -1
- package/dist/core/readability.js +19 -6
- package/dist/core/readability.js.map +1 -1
- package/dist/core/research.js +9 -6
- package/dist/core/research.js.map +1 -1
- package/dist/core/search-provider.js +12 -8
- package/dist/core/search-provider.js.map +1 -1
- package/dist/core/strategies.d.ts.map +1 -1
- package/dist/core/strategies.js +14 -5
- package/dist/core/strategies.js.map +1 -1
- package/dist/core/timing.d.ts +22 -0
- package/dist/core/timing.d.ts.map +1 -0
- package/dist/core/timing.js +34 -0
- package/dist/core/timing.js.map +1 -0
- package/dist/core/youtube.d.ts.map +1 -1
- package/dist/core/youtube.js +19 -6
- package/dist/core/youtube.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -444
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/server/middleware/auth.js +3 -2
- package/dist/server/middleware/auth.js.map +1 -1
- package/dist/server/routes/answer.d.ts.map +1 -1
- package/dist/server/routes/answer.js +5 -0
- package/dist/server/routes/answer.js.map +1 -1
- package/dist/server/routes/compat.js +3 -2
- package/dist/server/routes/compat.js.map +1 -1
- package/dist/server/routes/deep-fetch.d.ts.map +1 -1
- package/dist/server/routes/deep-fetch.js +5 -0
- package/dist/server/routes/deep-fetch.js.map +1 -1
- package/dist/server/routes/fetch.d.ts.map +1 -1
- package/dist/server/routes/fetch.js +44 -4
- package/dist/server/routes/fetch.js.map +1 -1
- package/dist/server/routes/health.js +3 -2
- package/dist/server/routes/health.js.map +1 -1
- package/dist/server/routes/mcp.js +1 -1
- package/dist/server/routes/mcp.js.map +1 -1
- package/dist/server/routes/quick-answer.d.ts.map +1 -1
- package/dist/server/routes/quick-answer.js +5 -0
- package/dist/server/routes/quick-answer.js.map +1 -1
- package/dist/server/routes/search.js +6 -4
- package/dist/server/routes/search.js.map +1 -1
- package/dist/server/routes/users.js +3 -2
- package/dist/server/routes/users.js.map +1 -1
- package/dist/server/routes/webhooks.d.ts +1 -0
- package/dist/server/routes/webhooks.d.ts.map +1 -1
- package/dist/server/routes/webhooks.js +1 -0
- package/dist/server/routes/webhooks.js.map +1 -1
- package/dist/server/routes/youtube.d.ts.map +1 -1
- package/dist/server/routes/youtube.js +5 -0
- package/dist/server/routes/youtube.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +5 -2
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebPeel pipeline stages
|
|
3
|
+
*
|
|
4
|
+
* Each stage is an exported async function that reads from / writes to the
|
|
5
|
+
* mutable PipelineContext. The stages are called in order by peel().
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'crypto';
|
|
8
|
+
import { smartFetch } from './strategies.js';
|
|
9
|
+
import { htmlToMarkdown, htmlToText, estimateTokens, selectContent, detectMainContent, calculateQuality, truncateToTokenBudget, filterByTags, } from './markdown.js';
|
|
10
|
+
import { pruneContent } from './content-pruner.js';
|
|
11
|
+
import { distillToBudget } from './budget.js';
|
|
12
|
+
import { extractMetadata, extractLinks, extractImages } from './metadata.js';
|
|
13
|
+
import { autoScroll as runAutoScroll } from './actions.js';
|
|
14
|
+
import { extractStructured } from './extract.js';
|
|
15
|
+
import { isPdfContentType, isDocxContentType, extractDocumentToFormat } from './documents.js';
|
|
16
|
+
import { parseYouTubeUrl, getYouTubeTranscript } from './youtube.js';
|
|
17
|
+
import { extractDomainData, getDomainExtractor } from './domain-extractors.js';
|
|
18
|
+
import { extractReadableContent } from './readability.js';
|
|
19
|
+
import { quickAnswer as runQuickAnswer } from './quick-answer.js';
|
|
20
|
+
import { Timer } from './timing.js';
|
|
21
|
+
/** Create the initial PipelineContext with defaults */
|
|
22
|
+
export function createContext(url, options) {
|
|
23
|
+
return {
|
|
24
|
+
url,
|
|
25
|
+
options,
|
|
26
|
+
timer: new Timer(),
|
|
27
|
+
startTime: Date.now(),
|
|
28
|
+
// Normalized options — filled by normalizeOptions()
|
|
29
|
+
render: false,
|
|
30
|
+
stealth: false,
|
|
31
|
+
wait: 0,
|
|
32
|
+
format: 'markdown',
|
|
33
|
+
timeout: 30000,
|
|
34
|
+
userAgent: undefined,
|
|
35
|
+
screenshot: false,
|
|
36
|
+
screenshotFullPage: false,
|
|
37
|
+
selector: undefined,
|
|
38
|
+
exclude: undefined,
|
|
39
|
+
includeTags: undefined,
|
|
40
|
+
excludeTags: undefined,
|
|
41
|
+
headers: undefined,
|
|
42
|
+
cookies: undefined,
|
|
43
|
+
raw: false,
|
|
44
|
+
actions: undefined,
|
|
45
|
+
extract: undefined,
|
|
46
|
+
maxTokens: undefined,
|
|
47
|
+
extractImagesFlag: false,
|
|
48
|
+
profileDir: undefined,
|
|
49
|
+
headed: false,
|
|
50
|
+
storageState: undefined,
|
|
51
|
+
proxy: undefined,
|
|
52
|
+
fullPage: false,
|
|
53
|
+
autoScrollOpts: undefined,
|
|
54
|
+
// Content type — filled by detectContentType()
|
|
55
|
+
contentType: 'html',
|
|
56
|
+
// Parsing results — filled by parseContent()
|
|
57
|
+
content: '',
|
|
58
|
+
title: '',
|
|
59
|
+
metadata: {},
|
|
60
|
+
links: [],
|
|
61
|
+
quality: 0,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Stage 1: normalizeOptions
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
/**
|
|
68
|
+
* Resolve all PeelOptions values into flat context fields with defaults applied.
|
|
69
|
+
* Force render=true when screenshot/stealth/actions/branding/autoScroll requested.
|
|
70
|
+
* Parse the autoScroll option.
|
|
71
|
+
*/
|
|
72
|
+
export function normalizeOptions(ctx) {
|
|
73
|
+
const opts = ctx.options;
|
|
74
|
+
// Apply agent-mode defaults (can be overridden by explicit options)
|
|
75
|
+
if (opts.agentMode) {
|
|
76
|
+
if (opts.budget === undefined)
|
|
77
|
+
opts.budget = 4000;
|
|
78
|
+
if (opts.format === undefined)
|
|
79
|
+
opts.format = 'markdown';
|
|
80
|
+
}
|
|
81
|
+
const { render = false, stealth = false, wait = 0, format = 'markdown', timeout = 30000, userAgent, screenshot = false, screenshotFullPage = false, selector, exclude, includeTags, excludeTags, headers, cookies, raw = false, actions, extract, maxTokens, images: extractImagesFlag = false, profileDir, headed = false, storageState, proxy, fullPage = false, autoScroll: autoScrollOption, } = opts;
|
|
82
|
+
// Normalize autoScroll option
|
|
83
|
+
const autoScrollOpts = autoScrollOption
|
|
84
|
+
? (typeof autoScrollOption === 'boolean' ? {} : autoScrollOption)
|
|
85
|
+
: undefined;
|
|
86
|
+
ctx.render = render;
|
|
87
|
+
ctx.stealth = stealth;
|
|
88
|
+
ctx.wait = wait;
|
|
89
|
+
ctx.format = format;
|
|
90
|
+
ctx.timeout = timeout;
|
|
91
|
+
ctx.userAgent = userAgent;
|
|
92
|
+
ctx.screenshot = screenshot;
|
|
93
|
+
ctx.screenshotFullPage = screenshotFullPage;
|
|
94
|
+
ctx.selector = selector;
|
|
95
|
+
ctx.exclude = exclude;
|
|
96
|
+
ctx.includeTags = includeTags;
|
|
97
|
+
ctx.excludeTags = excludeTags;
|
|
98
|
+
ctx.headers = headers;
|
|
99
|
+
ctx.cookies = cookies;
|
|
100
|
+
ctx.raw = raw;
|
|
101
|
+
ctx.actions = actions;
|
|
102
|
+
ctx.extract = extract;
|
|
103
|
+
ctx.maxTokens = maxTokens;
|
|
104
|
+
ctx.extractImagesFlag = extractImagesFlag;
|
|
105
|
+
ctx.profileDir = profileDir;
|
|
106
|
+
ctx.headed = headed;
|
|
107
|
+
ctx.storageState = storageState;
|
|
108
|
+
ctx.proxy = proxy;
|
|
109
|
+
ctx.fullPage = fullPage;
|
|
110
|
+
ctx.autoScrollOpts = autoScrollOpts;
|
|
111
|
+
// NOTE: PDFs/DOCX are now handled via simpleFetch + document parser.
|
|
112
|
+
// No need to force browser rendering for them.
|
|
113
|
+
// If screenshot is requested, force render mode
|
|
114
|
+
if (screenshot) {
|
|
115
|
+
ctx.render = true;
|
|
116
|
+
}
|
|
117
|
+
// If stealth is requested, force render mode
|
|
118
|
+
if (stealth) {
|
|
119
|
+
ctx.render = true;
|
|
120
|
+
}
|
|
121
|
+
// If actions are provided, force render mode
|
|
122
|
+
if (actions && actions.length > 0) {
|
|
123
|
+
ctx.render = true;
|
|
124
|
+
}
|
|
125
|
+
// If branding is requested, force render mode
|
|
126
|
+
if (opts.branding) {
|
|
127
|
+
ctx.render = true;
|
|
128
|
+
}
|
|
129
|
+
// If autoScroll is requested, force render mode
|
|
130
|
+
if (autoScrollOpts) {
|
|
131
|
+
ctx.render = true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Stage 2: handleYouTube
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
/**
|
|
138
|
+
* If the URL is a YouTube URL, attempt transcript extraction.
|
|
139
|
+
* Returns a PeelResult on success, or null to fall through to normal pipeline.
|
|
140
|
+
*/
|
|
141
|
+
export async function handleYouTube(ctx) {
|
|
142
|
+
const ytVideoId = parseYouTubeUrl(ctx.url);
|
|
143
|
+
if (!ytVideoId)
|
|
144
|
+
return null;
|
|
145
|
+
const ytStartTime = Date.now();
|
|
146
|
+
try {
|
|
147
|
+
const transcript = await getYouTubeTranscript(ctx.url, {
|
|
148
|
+
language: ctx.options.language ?? 'en',
|
|
149
|
+
});
|
|
150
|
+
// Build a clean markdown representation of the video + transcript
|
|
151
|
+
const videoInfoLines = [
|
|
152
|
+
`# ${transcript.title}`,
|
|
153
|
+
'',
|
|
154
|
+
`**Channel:** ${transcript.channel}`,
|
|
155
|
+
`**Duration:** ${transcript.duration}`,
|
|
156
|
+
`**Language:** ${transcript.language}`,
|
|
157
|
+
transcript.availableLanguages.length > 1
|
|
158
|
+
? `**Available Languages:** ${transcript.availableLanguages.join(', ')}`
|
|
159
|
+
: '',
|
|
160
|
+
'',
|
|
161
|
+
'## Transcript',
|
|
162
|
+
'',
|
|
163
|
+
transcript.fullText,
|
|
164
|
+
].filter(l => l !== undefined);
|
|
165
|
+
const videoInfoContent = videoInfoLines.join('\n');
|
|
166
|
+
const elapsed = Date.now() - ytStartTime;
|
|
167
|
+
const tokens = estimateTokens(videoInfoContent);
|
|
168
|
+
const fingerprint = createHash('sha256').update(videoInfoContent).digest('hex').slice(0, 16);
|
|
169
|
+
return {
|
|
170
|
+
url: `https://www.youtube.com/watch?v=${ytVideoId}`,
|
|
171
|
+
title: transcript.title,
|
|
172
|
+
content: videoInfoContent,
|
|
173
|
+
metadata: {
|
|
174
|
+
description: `YouTube video by ${transcript.channel}, duration ${transcript.duration}`,
|
|
175
|
+
author: transcript.channel,
|
|
176
|
+
},
|
|
177
|
+
links: [`https://www.youtube.com/watch?v=${ytVideoId}`],
|
|
178
|
+
tokens,
|
|
179
|
+
method: 'simple',
|
|
180
|
+
elapsed,
|
|
181
|
+
contentType: 'youtube',
|
|
182
|
+
quality: 1.0,
|
|
183
|
+
fingerprint,
|
|
184
|
+
extracted: undefined,
|
|
185
|
+
structured: transcript,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
catch (_ytError) {
|
|
189
|
+
// If transcript extraction fails (no captions, page changed, etc.),
|
|
190
|
+
// fall through to the normal HTML fetch pipeline below.
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
// Stage 3: fetchContent
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
/**
|
|
198
|
+
* Fetch the URL via smartFetch, handle autoScroll, and store result in ctx.fetchResult.
|
|
199
|
+
*/
|
|
200
|
+
export async function fetchContent(ctx) {
|
|
201
|
+
const needsBranding = ctx.options.branding && ctx.render;
|
|
202
|
+
const needsAutoScroll = !!ctx.autoScrollOpts && ctx.render;
|
|
203
|
+
ctx.timer.mark('fetch');
|
|
204
|
+
const fetchResult = await smartFetch(ctx.url, {
|
|
205
|
+
forceBrowser: ctx.render,
|
|
206
|
+
stealth: ctx.stealth,
|
|
207
|
+
waitMs: ctx.wait,
|
|
208
|
+
userAgent: ctx.userAgent,
|
|
209
|
+
timeoutMs: ctx.timeout,
|
|
210
|
+
screenshot: ctx.screenshot,
|
|
211
|
+
screenshotFullPage: ctx.screenshotFullPage,
|
|
212
|
+
headers: ctx.headers,
|
|
213
|
+
cookies: ctx.cookies,
|
|
214
|
+
actions: ctx.actions,
|
|
215
|
+
keepPageOpen: needsBranding || needsAutoScroll,
|
|
216
|
+
profileDir: ctx.profileDir,
|
|
217
|
+
headed: ctx.headed,
|
|
218
|
+
storageState: ctx.storageState,
|
|
219
|
+
proxy: ctx.proxy,
|
|
220
|
+
});
|
|
221
|
+
ctx.timer.end('fetch');
|
|
222
|
+
// Auto-scroll to load lazy content, then grab fresh HTML
|
|
223
|
+
if (needsAutoScroll && fetchResult.page) {
|
|
224
|
+
try {
|
|
225
|
+
await runAutoScroll(fetchResult.page, ctx.autoScrollOpts);
|
|
226
|
+
// Capture refreshed HTML after scrolling
|
|
227
|
+
fetchResult.html = await fetchResult.page.content();
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
// Non-fatal: auto-scroll failed, continuing with whatever HTML we have
|
|
231
|
+
if (process.env.DEBUG)
|
|
232
|
+
console.debug('[webpeel]', 'auto-scroll failed:', e instanceof Error ? e.message : e);
|
|
233
|
+
}
|
|
234
|
+
finally {
|
|
235
|
+
// Close page unless branding also needs it
|
|
236
|
+
if (!needsBranding) {
|
|
237
|
+
try {
|
|
238
|
+
await fetchResult.page.close().catch(() => { });
|
|
239
|
+
if (fetchResult.browser && !needsBranding) {
|
|
240
|
+
await fetchResult.browser.close().catch(() => { });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
// Non-fatal: page/browser cleanup after auto-scroll
|
|
245
|
+
if (process.env.DEBUG)
|
|
246
|
+
console.debug('[webpeel]', 'page/browser cleanup after auto-scroll:', e instanceof Error ? e.message : e);
|
|
247
|
+
}
|
|
248
|
+
fetchResult.page = undefined;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
ctx.fetchResult = fetchResult;
|
|
253
|
+
}
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
// Stage 4: detectContentType
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
/**
|
|
258
|
+
* Detect and set ctx.contentType based on response headers and content.
|
|
259
|
+
*/
|
|
260
|
+
export function detectContentType(ctx) {
|
|
261
|
+
const fetchResult = ctx.fetchResult;
|
|
262
|
+
const ct = (fetchResult.contentType || '').toLowerCase();
|
|
263
|
+
const urlLower = fetchResult.url.toLowerCase();
|
|
264
|
+
// Check for binary document types (PDF/DOCX)
|
|
265
|
+
const isDocument = isPdfContentType(ct) || isDocxContentType(ct) ||
|
|
266
|
+
urlLower.endsWith('.pdf') || urlLower.endsWith('.docx');
|
|
267
|
+
const isHTML = !isDocument && (ct.includes('html') || ct.includes('xhtml') || (!ct && fetchResult.html.trimStart().startsWith('<')));
|
|
268
|
+
const isJSON = !isDocument && ct.includes('json');
|
|
269
|
+
const isXML = !isDocument && (ct.includes('xml') || ct.includes('rss') || ct.includes('atom'));
|
|
270
|
+
const isPlainText = !isDocument && (ct.includes('text/plain') || ct.includes('text/markdown') || ct.includes('text/csv') || ct.includes('text/css') || ct.includes('javascript'));
|
|
271
|
+
ctx.contentType = isDocument ? 'document' : isHTML ? 'html' : isJSON ? 'json' : isXML ? 'xml' : isPlainText ? 'text' : 'html';
|
|
272
|
+
}
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
// Stage 5: parseContent
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
/**
|
|
277
|
+
* Parse content from fetchResult based on the detected contentType.
|
|
278
|
+
* Sets ctx.content, ctx.title, ctx.metadata, ctx.links, ctx.quality, ctx.prunedPercent.
|
|
279
|
+
*/
|
|
280
|
+
export async function parseContent(ctx) {
|
|
281
|
+
const fetchResult = ctx.fetchResult;
|
|
282
|
+
const { contentType, format, fullPage, raw, selector, exclude, includeTags, excludeTags } = ctx;
|
|
283
|
+
const hasBuffer = !!fetchResult.buffer;
|
|
284
|
+
if (contentType === 'document' && hasBuffer) {
|
|
285
|
+
// Document parsing pipeline (PDF/DOCX)
|
|
286
|
+
const docResult = await extractDocumentToFormat(fetchResult.buffer, {
|
|
287
|
+
url: fetchResult.url,
|
|
288
|
+
contentType: fetchResult.contentType,
|
|
289
|
+
format,
|
|
290
|
+
});
|
|
291
|
+
ctx.content = docResult.content;
|
|
292
|
+
ctx.title = docResult.metadata.title;
|
|
293
|
+
ctx.metadata = docResult.metadata;
|
|
294
|
+
ctx.quality = 1.0; // Documents are inherently structured content
|
|
295
|
+
}
|
|
296
|
+
else if (contentType === 'html') {
|
|
297
|
+
// Standard HTML pipeline
|
|
298
|
+
let html = fetchResult.html;
|
|
299
|
+
// Apply include/exclude tags filtering first (before selector)
|
|
300
|
+
if (includeTags || excludeTags) {
|
|
301
|
+
html = filterByTags(html, includeTags, excludeTags);
|
|
302
|
+
}
|
|
303
|
+
if (selector) {
|
|
304
|
+
html = selectContent(html, selector, exclude);
|
|
305
|
+
}
|
|
306
|
+
else if (exclude?.length) {
|
|
307
|
+
// Apply exclude selectors even without a specific selector
|
|
308
|
+
const cheerio = await import('cheerio');
|
|
309
|
+
const $doc = cheerio.load(html);
|
|
310
|
+
exclude.forEach(sel => $doc(sel).remove());
|
|
311
|
+
html = $doc.html() || html;
|
|
312
|
+
}
|
|
313
|
+
// Smart main content detection (unless raw or selector specified)
|
|
314
|
+
let contentHtml = html;
|
|
315
|
+
if (!raw && !selector) {
|
|
316
|
+
const detected = detectMainContent(html);
|
|
317
|
+
if (detected.detected) {
|
|
318
|
+
contentHtml = detected.html;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const metadataTask = Promise.resolve().then(() => {
|
|
322
|
+
ctx.timer.mark('metadata');
|
|
323
|
+
const meta = extractMetadata(html, fetchResult.url);
|
|
324
|
+
const result = {
|
|
325
|
+
title: meta.title,
|
|
326
|
+
metadata: meta.metadata,
|
|
327
|
+
links: extractLinks(html, fetchResult.url),
|
|
328
|
+
};
|
|
329
|
+
ctx.timer.end('metadata');
|
|
330
|
+
return result;
|
|
331
|
+
});
|
|
332
|
+
// Content density pruning — runs on HTML before markdown conversion.
|
|
333
|
+
// Removes low-value blocks (sidebars, footers, ads) CSS selectors miss.
|
|
334
|
+
// OFF when fullPage=true or format !== markdown.
|
|
335
|
+
if (format === 'markdown' && !fullPage) {
|
|
336
|
+
ctx.timer.mark('prune');
|
|
337
|
+
const pruned = pruneContent(contentHtml, { dynamic: true });
|
|
338
|
+
ctx.timer.end('prune');
|
|
339
|
+
contentHtml = pruned.html;
|
|
340
|
+
if (pruned.nodesRemoved > 0) {
|
|
341
|
+
ctx.prunedPercent = pruned.reductionPercent;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const contentTask = Promise.resolve().then(() => {
|
|
345
|
+
ctx.timer.mark('convert');
|
|
346
|
+
let converted;
|
|
347
|
+
switch (format) {
|
|
348
|
+
case 'html':
|
|
349
|
+
converted = contentHtml;
|
|
350
|
+
break;
|
|
351
|
+
case 'text':
|
|
352
|
+
converted = htmlToText(contentHtml);
|
|
353
|
+
break;
|
|
354
|
+
case 'markdown':
|
|
355
|
+
default:
|
|
356
|
+
// prune:false — already pruned above; avoid double-pruning in htmlToMarkdown
|
|
357
|
+
converted = htmlToMarkdown(contentHtml, { raw, prune: false });
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
ctx.timer.end('convert');
|
|
361
|
+
return converted;
|
|
362
|
+
});
|
|
363
|
+
const [metaResult, convertedContent] = await Promise.all([metadataTask, contentTask]);
|
|
364
|
+
ctx.title = metaResult.title;
|
|
365
|
+
ctx.metadata = metaResult.metadata;
|
|
366
|
+
ctx.links = metaResult.links;
|
|
367
|
+
ctx.content = convertedContent;
|
|
368
|
+
ctx.quality = calculateQuality(convertedContent, fetchResult.html);
|
|
369
|
+
}
|
|
370
|
+
else if (contentType === 'json') {
|
|
371
|
+
// JSON content — format nicely
|
|
372
|
+
try {
|
|
373
|
+
const parsed = JSON.parse(fetchResult.html);
|
|
374
|
+
ctx.content = JSON.stringify(parsed, null, 2);
|
|
375
|
+
ctx.title = 'JSON Response';
|
|
376
|
+
// Extract any URLs from JSON for links
|
|
377
|
+
const urlRegex = /https?:\/\/[^\s"'`,\]})]+/g;
|
|
378
|
+
const found = ctx.content.match(urlRegex) || [];
|
|
379
|
+
ctx.links = [...new Set(found)];
|
|
380
|
+
}
|
|
381
|
+
catch (e) {
|
|
382
|
+
// Non-fatal: JSON parse failed, treating as malformed
|
|
383
|
+
if (process.env.DEBUG)
|
|
384
|
+
console.debug('[webpeel]', 'JSON parse failed:', e instanceof Error ? e.message : e);
|
|
385
|
+
ctx.content = fetchResult.html;
|
|
386
|
+
ctx.title = 'JSON Response (malformed)';
|
|
387
|
+
}
|
|
388
|
+
ctx.quality = 1.0; // JSON is structured, always "clean"
|
|
389
|
+
}
|
|
390
|
+
else if (contentType === 'xml') {
|
|
391
|
+
// XML/RSS/Atom — convert to readable format
|
|
392
|
+
try {
|
|
393
|
+
const $ = (await import('cheerio')).load(fetchResult.html, { xml: true });
|
|
394
|
+
// Check if RSS/Atom feed
|
|
395
|
+
const items = $('item, entry');
|
|
396
|
+
if (items.length > 0) {
|
|
397
|
+
ctx.title = $('channel > title, feed > title').first().text() || 'RSS/Atom Feed';
|
|
398
|
+
const feedItems = [];
|
|
399
|
+
items.each((_, el) => {
|
|
400
|
+
const itemTitle = $(el).find('title').first().text();
|
|
401
|
+
const itemLink = $(el).find('link').first().text() || $(el).find('link').first().attr('href') || '';
|
|
402
|
+
const itemDesc = $(el).find('description, summary, content').first().text().slice(0, 200);
|
|
403
|
+
feedItems.push(`## ${itemTitle}\n${itemLink}\n${itemDesc}`);
|
|
404
|
+
if (itemLink)
|
|
405
|
+
ctx.links.push(itemLink);
|
|
406
|
+
});
|
|
407
|
+
ctx.content = `# ${ctx.title}\n\n${feedItems.join('\n\n---\n\n')}`;
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
ctx.content = fetchResult.html;
|
|
411
|
+
ctx.title = $('title').first().text() || 'XML Document';
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
catch (e) {
|
|
415
|
+
// Non-fatal: XML/RSS parse failed, using raw content
|
|
416
|
+
if (process.env.DEBUG)
|
|
417
|
+
console.debug('[webpeel]', 'XML/RSS parse failed:', e instanceof Error ? e.message : e);
|
|
418
|
+
ctx.content = fetchResult.html;
|
|
419
|
+
ctx.title = 'XML Document';
|
|
420
|
+
}
|
|
421
|
+
ctx.quality = 0.9;
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
// Plain text, CSS, JS, etc — return as-is
|
|
425
|
+
ctx.content = fetchResult.html;
|
|
426
|
+
ctx.title = fetchResult.url.split('/').pop() || 'Text Document';
|
|
427
|
+
// Extract URLs from plain text
|
|
428
|
+
const urlRegex = /https?:\/\/[^\s"'`,\]})]+/g;
|
|
429
|
+
const found = ctx.content.match(urlRegex) || [];
|
|
430
|
+
ctx.links = [...new Set(found)];
|
|
431
|
+
ctx.quality = 1.0;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// ---------------------------------------------------------------------------
|
|
435
|
+
// Stage 6: postProcess
|
|
436
|
+
// ---------------------------------------------------------------------------
|
|
437
|
+
/**
|
|
438
|
+
* Run all post-processing in sequence:
|
|
439
|
+
* readability, image extraction, structured extraction,
|
|
440
|
+
* maxTokens truncation, budget distillation, domain extractors, quick answer.
|
|
441
|
+
*/
|
|
442
|
+
export async function postProcess(ctx) {
|
|
443
|
+
const fetchResult = ctx.fetchResult;
|
|
444
|
+
const { contentType, options } = ctx;
|
|
445
|
+
const isHTML = contentType === 'html';
|
|
446
|
+
// Readability mode
|
|
447
|
+
if (options.readable && isHTML && fetchResult.html) {
|
|
448
|
+
ctx.timer.mark('readability');
|
|
449
|
+
const readResult = extractReadableContent(fetchResult.html, fetchResult.url);
|
|
450
|
+
ctx.timer.end('readability');
|
|
451
|
+
ctx.readabilityResult = readResult;
|
|
452
|
+
ctx.content = readResult.content;
|
|
453
|
+
ctx.metadata = {
|
|
454
|
+
...ctx.metadata,
|
|
455
|
+
title: readResult.title || ctx.metadata?.title,
|
|
456
|
+
author: readResult.author || undefined,
|
|
457
|
+
publishedDate: readResult.date || undefined,
|
|
458
|
+
};
|
|
459
|
+
ctx.title = readResult.title || ctx.title;
|
|
460
|
+
}
|
|
461
|
+
// Extract images if requested
|
|
462
|
+
if (ctx.extractImagesFlag && isHTML) {
|
|
463
|
+
ctx.imagesList = extractImages(fetchResult.html, fetchResult.url);
|
|
464
|
+
}
|
|
465
|
+
// Extract structured data if requested
|
|
466
|
+
if (ctx.extract && isHTML) {
|
|
467
|
+
if (ctx.extract.llmApiKey && (ctx.extract.prompt || ctx.extract.schema)) {
|
|
468
|
+
// LLM-powered extraction
|
|
469
|
+
const { extractWithLLM } = await import('./extract.js');
|
|
470
|
+
ctx.extracted = await extractWithLLM(ctx.content, ctx.extract);
|
|
471
|
+
}
|
|
472
|
+
else if (ctx.extract.selectors || ctx.extract.schema) {
|
|
473
|
+
// CSS-based extraction (existing)
|
|
474
|
+
ctx.extracted = extractStructured(fetchResult.html, ctx.extract);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
// Quick answer (LLM-free) — runs BEFORE budget distillation so it sees full
|
|
478
|
+
// content including infobox data (which budget stripping may remove).
|
|
479
|
+
if (options.question && ctx.content) {
|
|
480
|
+
ctx.timer.mark('quickAnswer');
|
|
481
|
+
const qa = runQuickAnswer({
|
|
482
|
+
question: options.question,
|
|
483
|
+
content: ctx.content,
|
|
484
|
+
url: fetchResult.url,
|
|
485
|
+
});
|
|
486
|
+
ctx.timer.end('quickAnswer');
|
|
487
|
+
ctx.quickAnswerResult = qa;
|
|
488
|
+
}
|
|
489
|
+
// Truncate to token budget if requested (simple truncation)
|
|
490
|
+
if (ctx.maxTokens && ctx.maxTokens > 0) {
|
|
491
|
+
ctx.content = truncateToTokenBudget(ctx.content, ctx.maxTokens);
|
|
492
|
+
}
|
|
493
|
+
// Smart budget distillation — applied AFTER maxTokens truncation
|
|
494
|
+
// This intelligently compresses content (strips boilerplate, compresses
|
|
495
|
+
// tables, removes weak paragraphs) rather than blindly cutting.
|
|
496
|
+
if (options.budget && options.budget > 0) {
|
|
497
|
+
const budgetFormat = ctx.contentType === 'json' ? 'json' :
|
|
498
|
+
ctx.format === 'text' ? 'text' : 'markdown';
|
|
499
|
+
ctx.timer.mark('budget');
|
|
500
|
+
ctx.content = distillToBudget(ctx.content, options.budget, budgetFormat);
|
|
501
|
+
ctx.timer.end('budget');
|
|
502
|
+
}
|
|
503
|
+
// Domain-aware structured extraction (Twitter, Reddit, GitHub, HN)
|
|
504
|
+
// Fires when URL matches a known domain. Replaces content with clean markdown.
|
|
505
|
+
if (getDomainExtractor(fetchResult.url)) {
|
|
506
|
+
try {
|
|
507
|
+
ctx.timer.mark('domainExtract');
|
|
508
|
+
const ddResult = await extractDomainData(fetchResult.html, fetchResult.url);
|
|
509
|
+
ctx.timer.end('domainExtract');
|
|
510
|
+
if (ddResult) {
|
|
511
|
+
ctx.domainData = ddResult;
|
|
512
|
+
ctx.content = ddResult.cleanContent;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
catch (e) {
|
|
516
|
+
// Domain extraction failure is non-fatal; continue with normal content
|
|
517
|
+
if (process.env.DEBUG)
|
|
518
|
+
console.debug('[webpeel]', 'domain extraction failed:', e instanceof Error ? e.message : e);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
// ---------------------------------------------------------------------------
|
|
523
|
+
// Stage 7: finalize
|
|
524
|
+
// ---------------------------------------------------------------------------
|
|
525
|
+
/**
|
|
526
|
+
* Screenshot base64 conversion, branding extraction (needs page), change tracking, AI summary.
|
|
527
|
+
*/
|
|
528
|
+
export async function finalize(ctx) {
|
|
529
|
+
const fetchResult = ctx.fetchResult;
|
|
530
|
+
const { options } = ctx;
|
|
531
|
+
// Convert screenshot buffer to base64 if present
|
|
532
|
+
ctx.screenshotBase64 = fetchResult.screenshot?.toString('base64');
|
|
533
|
+
// Extract branding if requested (reuses existing browser page when available)
|
|
534
|
+
if (options.branding && ctx.render && fetchResult.page) {
|
|
535
|
+
try {
|
|
536
|
+
const { extractBranding } = await import('./branding.js');
|
|
537
|
+
ctx.brandingProfile = await extractBranding(fetchResult.page);
|
|
538
|
+
}
|
|
539
|
+
catch (error) {
|
|
540
|
+
console.error('Branding extraction failed:', error);
|
|
541
|
+
}
|
|
542
|
+
finally {
|
|
543
|
+
// Clean up the kept-open page and browser
|
|
544
|
+
try {
|
|
545
|
+
await fetchResult.page.close().catch(() => { });
|
|
546
|
+
if (fetchResult.browser) {
|
|
547
|
+
await fetchResult.browser.close().catch(() => { });
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
catch (e) {
|
|
551
|
+
// Non-fatal: page/browser cleanup after branding extraction
|
|
552
|
+
if (process.env.DEBUG)
|
|
553
|
+
console.debug('[webpeel]', 'page/browser cleanup after branding:', e instanceof Error ? e.message : e);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
// Track content changes if requested
|
|
558
|
+
if (options.changeTracking) {
|
|
559
|
+
try {
|
|
560
|
+
const fingerprint = createHash('sha256').update(ctx.content).digest('hex').slice(0, 16);
|
|
561
|
+
const { trackChange } = await import('./change-tracking.js');
|
|
562
|
+
ctx.changeResult = await trackChange(fetchResult.url, ctx.content, fingerprint);
|
|
563
|
+
}
|
|
564
|
+
catch (error) {
|
|
565
|
+
console.error('Change tracking failed:', error);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
// Generate AI summary if requested
|
|
569
|
+
if (options.summary && options.llm) {
|
|
570
|
+
try {
|
|
571
|
+
const { summarizeContent } = await import('./summarize.js');
|
|
572
|
+
const maxLength = typeof options.summary === 'object' && options.summary.maxLength
|
|
573
|
+
? options.summary.maxLength
|
|
574
|
+
: 150;
|
|
575
|
+
ctx.summaryText = await summarizeContent(ctx.content, {
|
|
576
|
+
apiKey: options.llm.apiKey,
|
|
577
|
+
model: options.llm.model,
|
|
578
|
+
apiBase: options.llm.baseUrl,
|
|
579
|
+
maxWords: maxLength,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
catch (error) {
|
|
583
|
+
console.error('Summary generation failed:', error);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
// ---------------------------------------------------------------------------
|
|
588
|
+
// Stage 8: buildResult
|
|
589
|
+
// ---------------------------------------------------------------------------
|
|
590
|
+
/**
|
|
591
|
+
* Assemble the final PeelResult from the pipeline context.
|
|
592
|
+
*/
|
|
593
|
+
export function buildResult(ctx) {
|
|
594
|
+
const fetchResult = ctx.fetchResult;
|
|
595
|
+
const elapsed = Date.now() - ctx.startTime;
|
|
596
|
+
const tokens = estimateTokens(ctx.content);
|
|
597
|
+
const fingerprint = createHash('sha256').update(ctx.content).digest('hex').slice(0, 16);
|
|
598
|
+
return {
|
|
599
|
+
url: fetchResult.url,
|
|
600
|
+
title: ctx.title,
|
|
601
|
+
content: ctx.content,
|
|
602
|
+
metadata: ctx.metadata,
|
|
603
|
+
links: ctx.links,
|
|
604
|
+
tokens,
|
|
605
|
+
method: fetchResult.method === 'cached' ? 'simple' : fetchResult.method,
|
|
606
|
+
elapsed,
|
|
607
|
+
screenshot: ctx.screenshotBase64,
|
|
608
|
+
contentType: ctx.contentType,
|
|
609
|
+
quality: ctx.quality,
|
|
610
|
+
fingerprint,
|
|
611
|
+
extracted: ctx.extracted,
|
|
612
|
+
branding: ctx.brandingProfile,
|
|
613
|
+
changeTracking: ctx.changeResult,
|
|
614
|
+
summary: ctx.summaryText,
|
|
615
|
+
images: ctx.imagesList,
|
|
616
|
+
...(ctx.prunedPercent !== undefined ? { prunedPercent: ctx.prunedPercent } : {}),
|
|
617
|
+
...(ctx.domainData !== undefined ? { domainData: ctx.domainData } : {}),
|
|
618
|
+
...(ctx.readabilityResult !== undefined ? { readability: ctx.readabilityResult } : {}),
|
|
619
|
+
...(ctx.quickAnswerResult !== undefined ? { quickAnswer: ctx.quickAnswerResult } : {}),
|
|
620
|
+
timing: ctx.timer.toTiming(),
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"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"}
|