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.
Files changed (107) hide show
  1. package/dist/cache.d.ts.map +1 -1
  2. package/dist/cache.js +11 -4
  3. package/dist/cache.js.map +1 -1
  4. package/dist/cli.bundle.cjs +159248 -0
  5. package/dist/cli.js +1 -1
  6. package/dist/cli.js.map +1 -1
  7. package/dist/core/agent.js +12 -8
  8. package/dist/core/agent.js.map +1 -1
  9. package/dist/core/application-tracker.js +3 -2
  10. package/dist/core/application-tracker.js.map +1 -1
  11. package/dist/core/auto-extract.js +6 -4
  12. package/dist/core/auto-extract.js.map +1 -1
  13. package/dist/core/browser-fetch.d.ts +90 -0
  14. package/dist/core/browser-fetch.d.ts.map +1 -0
  15. package/dist/core/browser-fetch.js +599 -0
  16. package/dist/core/browser-fetch.js.map +1 -0
  17. package/dist/core/browser-pool.d.ts +70 -0
  18. package/dist/core/browser-pool.d.ts.map +1 -0
  19. package/dist/core/browser-pool.js +378 -0
  20. package/dist/core/browser-pool.js.map +1 -0
  21. package/dist/core/change-tracking.js +3 -2
  22. package/dist/core/change-tracking.js.map +1 -1
  23. package/dist/core/diff.js +3 -2
  24. package/dist/core/diff.js.map +1 -1
  25. package/dist/core/domain-extractors.js +3 -2
  26. package/dist/core/domain-extractors.js.map +1 -1
  27. package/dist/core/extract-inline.js +6 -4
  28. package/dist/core/extract-inline.js.map +1 -1
  29. package/dist/core/fetcher.d.ts +9 -116
  30. package/dist/core/fetcher.d.ts.map +1 -1
  31. package/dist/core/fetcher.js +10 -1484
  32. package/dist/core/fetcher.js.map +1 -1
  33. package/dist/core/http-fetch.d.ts +37 -0
  34. package/dist/core/http-fetch.d.ts.map +1 -0
  35. package/dist/core/http-fetch.js +618 -0
  36. package/dist/core/http-fetch.js.map +1 -0
  37. package/dist/core/metadata.js +18 -12
  38. package/dist/core/metadata.js.map +1 -1
  39. package/dist/core/pipeline.d.ts +104 -0
  40. package/dist/core/pipeline.d.ts.map +1 -0
  41. package/dist/core/pipeline.js +623 -0
  42. package/dist/core/pipeline.js.map +1 -0
  43. package/dist/core/profiles.js +15 -10
  44. package/dist/core/profiles.js.map +1 -1
  45. package/dist/core/quick-answer.d.ts.map +1 -1
  46. package/dist/core/quick-answer.js +120 -9
  47. package/dist/core/quick-answer.js.map +1 -1
  48. package/dist/core/rate-governor.js +3 -2
  49. package/dist/core/rate-governor.js.map +1 -1
  50. package/dist/core/readability.d.ts.map +1 -1
  51. package/dist/core/readability.js +19 -6
  52. package/dist/core/readability.js.map +1 -1
  53. package/dist/core/research.js +9 -6
  54. package/dist/core/research.js.map +1 -1
  55. package/dist/core/search-provider.js +12 -8
  56. package/dist/core/search-provider.js.map +1 -1
  57. package/dist/core/strategies.d.ts.map +1 -1
  58. package/dist/core/strategies.js +14 -5
  59. package/dist/core/strategies.js.map +1 -1
  60. package/dist/core/timing.d.ts +22 -0
  61. package/dist/core/timing.d.ts.map +1 -0
  62. package/dist/core/timing.js +34 -0
  63. package/dist/core/timing.js.map +1 -0
  64. package/dist/core/youtube.d.ts.map +1 -1
  65. package/dist/core/youtube.js +19 -6
  66. package/dist/core/youtube.js.map +1 -1
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +13 -444
  70. package/dist/index.js.map +1 -1
  71. package/dist/mcp/server.js +1 -1
  72. package/dist/mcp/server.js.map +1 -1
  73. package/dist/server/middleware/auth.js +3 -2
  74. package/dist/server/middleware/auth.js.map +1 -1
  75. package/dist/server/routes/answer.d.ts.map +1 -1
  76. package/dist/server/routes/answer.js +5 -0
  77. package/dist/server/routes/answer.js.map +1 -1
  78. package/dist/server/routes/compat.js +3 -2
  79. package/dist/server/routes/compat.js.map +1 -1
  80. package/dist/server/routes/deep-fetch.d.ts.map +1 -1
  81. package/dist/server/routes/deep-fetch.js +5 -0
  82. package/dist/server/routes/deep-fetch.js.map +1 -1
  83. package/dist/server/routes/fetch.d.ts.map +1 -1
  84. package/dist/server/routes/fetch.js +44 -4
  85. package/dist/server/routes/fetch.js.map +1 -1
  86. package/dist/server/routes/health.js +3 -2
  87. package/dist/server/routes/health.js.map +1 -1
  88. package/dist/server/routes/mcp.js +1 -1
  89. package/dist/server/routes/mcp.js.map +1 -1
  90. package/dist/server/routes/quick-answer.d.ts.map +1 -1
  91. package/dist/server/routes/quick-answer.js +5 -0
  92. package/dist/server/routes/quick-answer.js.map +1 -1
  93. package/dist/server/routes/search.js +6 -4
  94. package/dist/server/routes/search.js.map +1 -1
  95. package/dist/server/routes/users.js +3 -2
  96. package/dist/server/routes/users.js.map +1 -1
  97. package/dist/server/routes/webhooks.d.ts +1 -0
  98. package/dist/server/routes/webhooks.d.ts.map +1 -1
  99. package/dist/server/routes/webhooks.js +1 -0
  100. package/dist/server/routes/webhooks.js.map +1 -1
  101. package/dist/server/routes/youtube.d.ts.map +1 -1
  102. package/dist/server/routes/youtube.js +5 -0
  103. package/dist/server/routes/youtube.js.map +1 -1
  104. package/dist/types.d.ts +2 -0
  105. package/dist/types.d.ts.map +1 -1
  106. package/dist/types.js.map +1 -1
  107. 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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"}