@lobu/connector-sdk 6.0.1

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 (93) hide show
  1. package/dist/api-paginated.d.ts +79 -0
  2. package/dist/api-paginated.d.ts.map +1 -0
  3. package/dist/api-paginated.js +120 -0
  4. package/dist/api-paginated.js.map +1 -0
  5. package/dist/base.d.ts +66 -0
  6. package/dist/base.d.ts.map +1 -0
  7. package/dist/base.js +122 -0
  8. package/dist/base.js.map +1 -0
  9. package/dist/browser/acquire.d.ts +66 -0
  10. package/dist/browser/acquire.d.ts.map +1 -0
  11. package/dist/browser/acquire.js +109 -0
  12. package/dist/browser/acquire.js.map +1 -0
  13. package/dist/browser/cdp-page.d.ts +48 -0
  14. package/dist/browser/cdp-page.d.ts.map +1 -0
  15. package/dist/browser/cdp-page.js +165 -0
  16. package/dist/browser/cdp-page.js.map +1 -0
  17. package/dist/browser/cdp.d.ts +44 -0
  18. package/dist/browser/cdp.d.ts.map +1 -0
  19. package/dist/browser/cdp.js +252 -0
  20. package/dist/browser/cdp.js.map +1 -0
  21. package/dist/browser/launcher.d.ts +29 -0
  22. package/dist/browser/launcher.d.ts.map +1 -0
  23. package/dist/browser/launcher.js +157 -0
  24. package/dist/browser/launcher.js.map +1 -0
  25. package/dist/browser/stealth.d.ts +55 -0
  26. package/dist/browser/stealth.d.ts.map +1 -0
  27. package/dist/browser/stealth.js +170 -0
  28. package/dist/browser/stealth.js.map +1 -0
  29. package/dist/browser-network.d.ts +51 -0
  30. package/dist/browser-network.d.ts.map +1 -0
  31. package/dist/browser-network.js +175 -0
  32. package/dist/browser-network.js.map +1 -0
  33. package/dist/browser-paginated.d.ts +141 -0
  34. package/dist/browser-paginated.d.ts.map +1 -0
  35. package/dist/browser-paginated.js +269 -0
  36. package/dist/browser-paginated.js.map +1 -0
  37. package/dist/connector-runtime.d.ts +70 -0
  38. package/dist/connector-runtime.d.ts.map +1 -0
  39. package/dist/connector-runtime.js +48 -0
  40. package/dist/connector-runtime.js.map +1 -0
  41. package/dist/connector-types.d.ts +613 -0
  42. package/dist/connector-types.d.ts.map +1 -0
  43. package/dist/connector-types.js +27 -0
  44. package/dist/connector-types.js.map +1 -0
  45. package/dist/event-taxonomy.d.ts +3 -0
  46. package/dist/event-taxonomy.d.ts.map +1 -0
  47. package/dist/event-taxonomy.js +30 -0
  48. package/dist/event-taxonomy.js.map +1 -0
  49. package/dist/http.d.ts +18 -0
  50. package/dist/http.d.ts.map +1 -0
  51. package/dist/http.js +74 -0
  52. package/dist/http.js.map +1 -0
  53. package/dist/identity-normalize.d.ts +53 -0
  54. package/dist/identity-normalize.d.ts.map +1 -0
  55. package/dist/identity-normalize.js +146 -0
  56. package/dist/identity-normalize.js.map +1 -0
  57. package/dist/identity-types.d.ts +214 -0
  58. package/dist/identity-types.d.ts.map +1 -0
  59. package/dist/identity-types.js +217 -0
  60. package/dist/identity-types.js.map +1 -0
  61. package/dist/index.d.ts +37 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +33 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/logger.d.ts +7 -0
  66. package/dist/logger.d.ts.map +1 -0
  67. package/dist/logger.js +10 -0
  68. package/dist/logger.js.map +1 -0
  69. package/dist/paginated.d.ts +93 -0
  70. package/dist/paginated.d.ts.map +1 -0
  71. package/dist/paginated.js +167 -0
  72. package/dist/paginated.js.map +1 -0
  73. package/dist/reaction-sdk.d.ts +43 -0
  74. package/dist/reaction-sdk.d.ts.map +1 -0
  75. package/dist/reaction-sdk.js +9 -0
  76. package/dist/reaction-sdk.js.map +1 -0
  77. package/dist/retry.d.ts +19 -0
  78. package/dist/retry.d.ts.map +1 -0
  79. package/dist/retry.js +131 -0
  80. package/dist/retry.js.map +1 -0
  81. package/dist/scoring.d.ts +17 -0
  82. package/dist/scoring.d.ts.map +1 -0
  83. package/dist/scoring.js +28 -0
  84. package/dist/scoring.js.map +1 -0
  85. package/dist/types.d.ts +280 -0
  86. package/dist/types.d.ts.map +1 -0
  87. package/dist/types.js +2 -0
  88. package/dist/types.js.map +1 -0
  89. package/dist/watcher-time.d.ts +14 -0
  90. package/dist/watcher-time.d.ts.map +1 -0
  91. package/dist/watcher-time.js +112 -0
  92. package/dist/watcher-time.js.map +1 -0
  93. package/package.json +59 -0
@@ -0,0 +1,157 @@
1
+ /// <reference lib="dom" />
2
+ /**
3
+ * Browser Launcher Utility
4
+ * Provides Playwright-based browser automation
5
+ */
6
+ import { mkdir, writeFile } from 'node:fs/promises';
7
+ import { join } from 'node:path';
8
+ import { sdkLogger } from '../logger.js';
9
+ import { launchStealthBrowser } from './stealth.js';
10
+ /**
11
+ * Add Puppeteer-compatible methods to Playwright Page
12
+ */
13
+ function addCompatibilityMethods(page) {
14
+ if (!page.setUserAgent) {
15
+ page.setUserAgent = async (userAgent) => {
16
+ await page.setExtraHTTPHeaders({
17
+ 'User-Agent': userAgent,
18
+ });
19
+ };
20
+ }
21
+ return page;
22
+ }
23
+ /**
24
+ * Launch browser with Playwright
25
+ */
26
+ export async function launchBrowser(_env, options = {}) {
27
+ const isDebug = options.debug ?? process.env.BROWSER_DEBUG === '1';
28
+ const enableTrace = options.trace ?? process.env.BROWSER_TRACE === '1';
29
+ const screenshotDir = options.screenshotDir ?? process.env.BROWSER_SCREENSHOT_DIR ?? '/tmp/feed-screenshots';
30
+ const useStealth = options.stealth ?? process.env.BROWSER_STEALTH === '1';
31
+ sdkLogger.info(`[BrowserLauncher] Using Playwright (local) - headless: ${!isDebug}, stealth: ${useStealth}`);
32
+ try {
33
+ if (useStealth) {
34
+ const stealthBrowser = await launchStealthBrowser({
35
+ headless: !isDebug,
36
+ debug: isDebug,
37
+ });
38
+ const browser = stealthBrowser.browser;
39
+ const originalNewPage = browser.newPage.bind(browser);
40
+ browser.newPage = async () => {
41
+ const page = await originalNewPage();
42
+ return addCompatibilityMethods(page);
43
+ };
44
+ sdkLogger.info('[BrowserLauncher] Stealth mode enabled - using anti-detection measures');
45
+ return {
46
+ browser,
47
+ isPlaywright: true,
48
+ screenshotDir,
49
+ };
50
+ }
51
+ const playwrightModule = 'playwright';
52
+ const { chromium } = await import(/* @vite-ignore */ playwrightModule);
53
+ const browser = await chromium.launch({
54
+ headless: !isDebug,
55
+ slowMo: isDebug ? 100 : 0,
56
+ args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
57
+ devtools: isDebug,
58
+ });
59
+ const originalNewPage = browser.newPage.bind(browser);
60
+ browser.newPage = async () => {
61
+ const page = await originalNewPage();
62
+ return addCompatibilityMethods(page);
63
+ };
64
+ if (isDebug) {
65
+ sdkLogger.info('[BrowserLauncher] Debug mode enabled - browser visible, slow motion active');
66
+ }
67
+ if (enableTrace) {
68
+ sdkLogger.info('[BrowserLauncher] Trace recording enabled - artifacts will be saved on error');
69
+ }
70
+ return {
71
+ browser,
72
+ isPlaywright: true,
73
+ screenshotDir,
74
+ };
75
+ }
76
+ catch (error) {
77
+ if (error.message?.includes("Executable doesn't exist") || error.code === 'MODULE_NOT_FOUND') {
78
+ throw new Error('Playwright not installed or Chromium browser missing.\n' +
79
+ 'Install with: npm install -D playwright && npx playwright install chromium');
80
+ }
81
+ sdkLogger.error({ error }, '[BrowserLauncher] Failed to launch Playwright browser:');
82
+ throw new Error(`Playwright launch failed: ${error.message}`);
83
+ }
84
+ }
85
+ /**
86
+ * Capture error artifacts (screenshot, HTML, trace) when feed fails
87
+ */
88
+ export async function captureErrorArtifacts(page, error, feedType, screenshotDir) {
89
+ try {
90
+ await mkdir(screenshotDir, { recursive: true });
91
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
92
+ const baseFilename = `${feedType}-${timestamp}`;
93
+ const screenshotPath = join(screenshotDir, `${baseFilename}.png`);
94
+ try {
95
+ await page.screenshot({
96
+ path: screenshotPath,
97
+ fullPage: true,
98
+ timeout: 5000,
99
+ });
100
+ sdkLogger.error({ path: screenshotPath }, '[BrowserLauncher] Screenshot saved');
101
+ }
102
+ catch (screenshotError) {
103
+ sdkLogger.warn({ error: screenshotError }, '[BrowserLauncher] Failed to capture screenshot');
104
+ }
105
+ const htmlPath = join(screenshotDir, `${baseFilename}.html`);
106
+ try {
107
+ const html = await page.content();
108
+ await writeFile(htmlPath, html, 'utf-8');
109
+ sdkLogger.error({ path: htmlPath }, '[BrowserLauncher] HTML saved');
110
+ }
111
+ catch (htmlError) {
112
+ sdkLogger.warn({ error: htmlError }, '[BrowserLauncher] Failed to save HTML');
113
+ }
114
+ const logsPath = join(screenshotDir, `${baseFilename}.log`);
115
+ try {
116
+ const logs = await page
117
+ .evaluate(() => {
118
+ return window.console?.history || [];
119
+ })
120
+ .catch(() => []);
121
+ if (logs.length > 0) {
122
+ await writeFile(logsPath, logs.join('\n'), 'utf-8');
123
+ sdkLogger.error(`[BrowserLauncher] Console logs saved: ${logsPath}`);
124
+ }
125
+ }
126
+ catch (_logError) {
127
+ // Console logs are optional
128
+ }
129
+ sdkLogger.error({
130
+ feed_type: feedType,
131
+ error: error.message,
132
+ stack: error.stack,
133
+ artifacts: {
134
+ directory: screenshotDir,
135
+ screenshot: screenshotPath,
136
+ html: htmlPath,
137
+ },
138
+ debug_hint: `To debug: BROWSER_DEBUG=1 pnpm sync ${feedType} [options]`,
139
+ }, '[BrowserLauncher] Feed failed');
140
+ }
141
+ catch (captureError) {
142
+ sdkLogger.error({ error: captureError }, '[BrowserLauncher] Failed to capture error artifacts');
143
+ }
144
+ }
145
+ /**
146
+ * Wrap feed execution with error artifact capture
147
+ */
148
+ export async function withErrorCapture(fn, page, feedType, screenshotDir) {
149
+ try {
150
+ return await fn();
151
+ }
152
+ catch (error) {
153
+ await captureErrorArtifacts(page, error, feedType, screenshotDir);
154
+ throw error;
155
+ }
156
+ }
157
+ //# sourceMappingURL=launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher.js","sourceRoot":"","sources":["../../src/browser/launcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Stealth Browser Helper
3
+ * Provides browser instances that mimic real browsers to avoid CAPTCHA and bot detection
4
+ */
5
+ type Browser = any;
6
+ type BrowserContext = any;
7
+ type Page = any;
8
+ export interface StealthBrowserOptions {
9
+ headless?: boolean;
10
+ debug?: boolean;
11
+ userAgent?: string;
12
+ viewport?: {
13
+ width: number;
14
+ height: number;
15
+ };
16
+ timezoneId?: string;
17
+ locale?: string;
18
+ proxy?: {
19
+ server: string;
20
+ username?: string;
21
+ password?: string;
22
+ };
23
+ }
24
+ export interface StealthBrowser {
25
+ browser: Browser;
26
+ context: BrowserContext;
27
+ page: Page;
28
+ close: () => Promise<void>;
29
+ }
30
+ /**
31
+ * Launch a stealth browser instance
32
+ */
33
+ export declare function launchStealthBrowser(options?: StealthBrowserOptions): Promise<StealthBrowser>;
34
+ /**
35
+ * Human-like delay (50-200ms random)
36
+ */
37
+ export declare function getRandomDelay(): number;
38
+ /**
39
+ * Random scroll behavior to mimic human browsing
40
+ */
41
+ export declare function randomScroll(page: Page, direction?: 'down' | 'up'): Promise<void>;
42
+ /**
43
+ * Wait with random duration to mimic human reading time
44
+ */
45
+ export declare function humanWait(page: Page, minMs?: number, maxMs?: number): Promise<void>;
46
+ /**
47
+ * Test bot detection on common detection sites
48
+ */
49
+ export declare function testBotDetection(page: Page): Promise<{
50
+ site: string;
51
+ detected: boolean;
52
+ details?: string;
53
+ }[]>;
54
+ export {};
55
+ //# sourceMappingURL=stealth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stealth.d.ts","sourceRoot":"","sources":["../../src/browser/stealth.ts"],"names":[],"mappings":"AACA;;;GAGG;AAEH,KAAK,OAAO,GAAG,GAAG,CAAC;AACnB,KAAK,cAAc,GAAG,GAAG,CAAC;AAC1B,KAAK,IAAI,GAAG,GAAG,CAAC;AAIhB,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAgBD;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,cAAc,CAAC,CAgDzB;AA8CD;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,GAAE,MAAM,GAAG,IAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/F;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,IAAI,EACV,KAAK,GAAE,MAAa,EACpB,KAAK,GAAE,MAAa,GACnB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CACzD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,EAAE,CACJ,CA+CA"}
@@ -0,0 +1,170 @@
1
+ /// <reference lib="dom" />
2
+ /**
3
+ * Stealth Browser Helper
4
+ * Provides browser instances that mimic real browsers to avoid CAPTCHA and bot detection
5
+ */
6
+ import { sdkLogger } from '../logger.js';
7
+ /**
8
+ * Default user agents (rotate through these for better stealth)
9
+ */
10
+ const DEFAULT_USER_AGENTS = [
11
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
12
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
13
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
14
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0',
15
+ ];
16
+ function getRandomUserAgent() {
17
+ return DEFAULT_USER_AGENTS[Math.floor(Math.random() * DEFAULT_USER_AGENTS.length)];
18
+ }
19
+ /**
20
+ * Launch a stealth browser instance
21
+ */
22
+ export async function launchStealthBrowser(options = {}) {
23
+ const { headless = true, debug = false, userAgent = getRandomUserAgent(), viewport = { width: 1920, height: 1080 }, timezoneId = 'America/New_York', locale = 'en-US', proxy, } = options;
24
+ // patchright (drop-in playwright replacement) handles navigator.webdriver natively
25
+ const playwrightModule = 'playwright';
26
+ const { chromium } = await import(/* @vite-ignore */ playwrightModule);
27
+ const browser = await chromium.launch({
28
+ headless: headless && !debug,
29
+ slowMo: debug ? 100 : 0,
30
+ devtools: debug,
31
+ args: getStealthArgs(),
32
+ proxy,
33
+ });
34
+ sdkLogger.info('[StealthBrowser] Using patchright with stealth flags');
35
+ const context = await browser.newContext({
36
+ userAgent,
37
+ viewport,
38
+ locale,
39
+ timezoneId,
40
+ deviceScaleFactor: 1,
41
+ hasTouch: false,
42
+ colorScheme: 'light',
43
+ permissions: ['geolocation', 'notifications'],
44
+ extraHTTPHeaders: getRealisticHeaders(),
45
+ });
46
+ const page = await context.newPage();
47
+ return {
48
+ browser,
49
+ context,
50
+ page,
51
+ close: async () => {
52
+ await context.close();
53
+ await browser.close();
54
+ },
55
+ };
56
+ }
57
+ function getStealthArgs() {
58
+ return [
59
+ '--disable-blink-features=AutomationControlled',
60
+ '--exclude-switches=enable-automation',
61
+ '--disable-features=IsolateOrigins,site-per-process',
62
+ '--disable-extensions',
63
+ '--disable-infobars',
64
+ '--no-sandbox',
65
+ '--disable-setuid-sandbox',
66
+ '--disable-dev-shm-usage',
67
+ '--enable-webgl',
68
+ '--use-gl=swiftshader',
69
+ '--enable-accelerated-2d-canvas',
70
+ '--no-first-run',
71
+ '--no-zygote',
72
+ '--disable-background-networking',
73
+ '--disable-background-timer-throttling',
74
+ '--disable-backgrounding-occluded-windows',
75
+ '--disable-breakpad',
76
+ '--disable-component-extensions-with-background-pages',
77
+ '--disable-features=TranslateUI',
78
+ '--disable-ipc-flooding-protection',
79
+ '--disable-renderer-backgrounding',
80
+ '--metrics-recording-only',
81
+ '--mute-audio',
82
+ ];
83
+ }
84
+ function getRealisticHeaders() {
85
+ return {
86
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
87
+ 'Accept-Language': 'en-US,en;q=0.9',
88
+ 'Accept-Encoding': 'gzip, deflate, br',
89
+ Connection: 'keep-alive',
90
+ 'Upgrade-Insecure-Requests': '1',
91
+ 'Sec-Fetch-Dest': 'document',
92
+ 'Sec-Fetch-Mode': 'navigate',
93
+ 'Sec-Fetch-Site': 'none',
94
+ 'Sec-Fetch-User': '?1',
95
+ 'Cache-Control': 'max-age=0',
96
+ };
97
+ }
98
+ /**
99
+ * Human-like delay (50-200ms random)
100
+ */
101
+ export function getRandomDelay() {
102
+ return Math.random() * (200 - 50) + 50;
103
+ }
104
+ /**
105
+ * Random scroll behavior to mimic human browsing
106
+ */
107
+ export async function randomScroll(page, direction = 'down') {
108
+ const scrollY = (Math.floor(Math.random() * 500) + 200) * (direction === 'down' ? 1 : -1);
109
+ await page.evaluate((y) => {
110
+ window.scrollBy({
111
+ top: y,
112
+ behavior: 'smooth',
113
+ });
114
+ }, scrollY);
115
+ await page.waitForTimeout(1000 + Math.random() * 1000);
116
+ }
117
+ /**
118
+ * Wait with random duration to mimic human reading time
119
+ */
120
+ export async function humanWait(page, minMs = 1000, maxMs = 3000) {
121
+ const delay = Math.random() * (maxMs - minMs) + minMs;
122
+ await page.waitForTimeout(delay);
123
+ }
124
+ /**
125
+ * Test bot detection on common detection sites
126
+ */
127
+ export async function testBotDetection(page) {
128
+ const results = [];
129
+ try {
130
+ await page.goto('https://bot.sannysoft.com', { waitUntil: 'networkidle' });
131
+ await page.waitForTimeout(2000);
132
+ const webdriverDetected = await page.evaluate(() => {
133
+ return navigator.webdriver === true;
134
+ });
135
+ results.push({
136
+ site: 'bot.sannysoft.com',
137
+ detected: webdriverDetected,
138
+ details: `navigator.webdriver: ${webdriverDetected}`,
139
+ });
140
+ }
141
+ catch (error) {
142
+ results.push({
143
+ site: 'bot.sannysoft.com',
144
+ detected: true,
145
+ details: `Error: ${error.message}`,
146
+ });
147
+ }
148
+ try {
149
+ await page.goto('https://arh.antoinevastel.com/bots/areyouheadless', {
150
+ waitUntil: 'networkidle',
151
+ });
152
+ await page.waitForTimeout(2000);
153
+ const headlessDetected = await page.textContent('body');
154
+ const isHeadless = headlessDetected?.includes('You are headless');
155
+ results.push({
156
+ site: 'arh.antoinevastel.com',
157
+ detected: isHeadless || false,
158
+ details: isHeadless ? 'Headless detected' : 'Not detected as headless',
159
+ });
160
+ }
161
+ catch (error) {
162
+ results.push({
163
+ site: 'arh.antoinevastel.com',
164
+ detected: true,
165
+ details: `Error: ${error.message}`,
166
+ });
167
+ }
168
+ return results;
169
+ }
170
+ //# sourceMappingURL=stealth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stealth.js","sourceRoot":"","sources":["../../src/browser/stealth.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B;;;GAGG;AAMH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAuBzC;;GAEG;AACH,MAAM,mBAAmB,GAAG;IAC1B,iHAAiH;IACjH,iHAAiH;IACjH,uHAAuH;IACvH,kFAAkF;CACnF,CAAC;AAEF,SAAS,kBAAkB;IACzB,OAAO,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAAiC,EAAE;IAEnC,MAAM,EACJ,QAAQ,GAAG,IAAI,EACf,KAAK,GAAG,KAAK,EACb,SAAS,GAAG,kBAAkB,EAAE,EAChC,QAAQ,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EACxC,UAAU,GAAG,kBAAkB,EAC/B,MAAM,GAAG,OAAO,EAChB,KAAK,GACN,GAAG,OAAO,CAAC;IAEZ,mFAAmF;IACnF,MAAM,gBAAgB,GAAG,YAAY,CAAC;IACtC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAY,MAAM,QAAQ,CAAC,MAAM,CAAC;QAC7C,QAAQ,EAAE,QAAQ,IAAI,CAAC,KAAK;QAC5B,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,cAAc,EAAE;QACtB,KAAK;KACN,CAAC,CAAC;IAEH,SAAS,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;QACvC,SAAS;QACT,QAAQ;QACR,MAAM;QACN,UAAU;QACV,iBAAiB,EAAE,CAAC;QACpB,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,OAAO;QACpB,WAAW,EAAE,CAAC,aAAa,EAAE,eAAe,CAAC;QAC7C,gBAAgB,EAAE,mBAAmB,EAAE;KACxC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAErC,OAAO;QACL,OAAO;QACP,OAAO;QACP,IAAI;QACJ,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc;IACrB,OAAO;QACL,+CAA+C;QAC/C,sCAAsC;QACtC,oDAAoD;QACpD,sBAAsB;QACtB,oBAAoB;QACpB,cAAc;QACd,0BAA0B;QAC1B,yBAAyB;QACzB,gBAAgB;QAChB,sBAAsB;QACtB,gCAAgC;QAChC,gBAAgB;QAChB,aAAa;QACb,iCAAiC;QACjC,uCAAuC;QACvC,0CAA0C;QAC1C,oBAAoB;QACpB,sDAAsD;QACtD,gCAAgC;QAChC,mCAAmC;QACnC,kCAAkC;QAClC,0BAA0B;QAC1B,cAAc;KACf,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO;QACL,MAAM,EACJ,kGAAkG;QACpG,iBAAiB,EAAE,gBAAgB;QACnC,iBAAiB,EAAE,mBAAmB;QACtC,UAAU,EAAE,YAAY;QACxB,2BAA2B,EAAE,GAAG;QAChC,gBAAgB,EAAE,UAAU;QAC5B,gBAAgB,EAAE,UAAU;QAC5B,gBAAgB,EAAE,MAAM;QACxB,gBAAgB,EAAE,IAAI;QACtB,eAAe,EAAE,WAAW;KAC7B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAU,EAAE,YAA2B,MAAM;IAC9E,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE1F,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAS,EAAE,EAAE;QAChC,MAAM,CAAC,QAAQ,CAAC;YACd,GAAG,EAAE,CAAC;YACN,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;IACL,CAAC,EAAE,OAAO,CAAC,CAAC;IAEZ,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAU,EACV,QAAgB,IAAI,EACpB,QAAgB,IAAI;IAEpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;IACtD,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAU;IAO/C,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;QAC3E,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAEhC,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;YACjD,OAAO,SAAS,CAAC,SAAS,KAAK,IAAI,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE,iBAAiB;YAC3B,OAAO,EAAE,wBAAwB,iBAAiB,EAAE;SACrD,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,UAAU,KAAK,CAAC,OAAO,EAAE;SACnC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,IAAI,CAAC,mDAAmD,EAAE;YACnE,SAAS,EAAE,aAAa;SACzB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAEhC,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,gBAAgB,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;QAElE,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,uBAAuB;YAC7B,QAAQ,EAAE,UAAU,IAAI,KAAK;YAC7B,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,0BAA0B;SACvE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,uBAAuB;YAC7B,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,UAAU,KAAK,CAAC,OAAO,EAAE;SACnC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Browser Network Feed
3
+ *
4
+ * Helper for connectors that use browser network interception instead of DOM scraping.
5
+ * Two-layer cascade:
6
+ * 1. CDP — Playwright's connectOverCDP to user's real Chrome (default context).
7
+ * Works for network interception because we just open a tab and listen.
8
+ * 2. Playwright — launch headless browser with stored cookies (fallback).
9
+ *
10
+ * Both paths share the same intercept → scroll → parse pipeline.
11
+ * Fresh cookies are always captured and returned for persistence.
12
+ */
13
+ import type { Cookie, Page } from 'playwright';
14
+ export interface BrowserNetworkConfig {
15
+ /** URL patterns to intercept (glob or regex). Matched against response URLs. */
16
+ interceptPatterns: (string | RegExp)[];
17
+ /** Cookie domains required for auth (e.g., ['x.com', '.x.com']) */
18
+ authDomains: string[];
19
+ /** Maximum number of scroll iterations for pagination (default: 10) */
20
+ maxScrolls?: number;
21
+ /** Delay between scrolls in ms (default: 2000) */
22
+ scrollDelayMs?: number;
23
+ /** Time to wait for API response after scroll in ms (default: 5000) */
24
+ responseTimeoutMs?: number;
25
+ /** Navigation timeout in ms (default: 15000) */
26
+ navigationTimeoutMs?: number;
27
+ /** Use stealth browser to evade bot detection (default: false) */
28
+ stealth?: boolean;
29
+ }
30
+ export interface BrowserNetworkResult<TItem> {
31
+ items: TItem[];
32
+ cookies: Cookie[];
33
+ apiCallCount: number;
34
+ /** Which browser backend was used */
35
+ backend: 'cdp' | 'playwright';
36
+ }
37
+ export declare function browserNetworkSync<TItem>(opts: {
38
+ config: BrowserNetworkConfig;
39
+ url: string;
40
+ /** Stored cookies for Playwright fallback. Can be empty if CDP is expected. */
41
+ cookies: Cookie[];
42
+ parseResponse: (url: string, json: unknown) => TItem[];
43
+ triggerNextPage?: (page: Page) => Promise<void>;
44
+ checkAuth?: (page: Page) => Promise<boolean>;
45
+ /**
46
+ * CDP endpoint URL, 'auto' to auto-discover, or null/undefined to skip CDP.
47
+ * When set, CDP is tried first; if unavailable, falls back to Playwright + cookies.
48
+ */
49
+ cdpUrl?: string | 'auto' | null;
50
+ }): Promise<BrowserNetworkResult<TItem>>;
51
+ //# sourceMappingURL=browser-network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-network.d.ts","sourceRoot":"","sources":["../src/browser-network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAA2B,MAAM,EAAE,IAAI,EAAY,MAAM,YAAY,CAAC;AAKlF,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,iBAAiB,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IACvC,mEAAmE;IACnE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gDAAgD;IAChD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB,CAAC,KAAK;IACzC,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,OAAO,EAAE,KAAK,GAAG,YAAY,CAAC;CAC/B;AA6FD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE;IACpD,MAAM,EAAE,oBAAoB,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,KAAK,EAAE,CAAC;IACvD,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACjC,GAAG,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAmHvC"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Browser Network Feed
3
+ *
4
+ * Helper for connectors that use browser network interception instead of DOM scraping.
5
+ * Two-layer cascade:
6
+ * 1. CDP — Playwright's connectOverCDP to user's real Chrome (default context).
7
+ * Works for network interception because we just open a tab and listen.
8
+ * 2. Playwright — launch headless browser with stored cookies (fallback).
9
+ *
10
+ * Both paths share the same intercept → scroll → parse pipeline.
11
+ * Fresh cookies are always captured and returned for persistence.
12
+ */
13
+ import { resolveCdpUrl } from './browser/cdp.js';
14
+ import { captureErrorArtifacts, launchBrowser } from './browser/launcher.js';
15
+ import { sdkLogger } from './logger.js';
16
+ const DEFAULT_CONFIG = {
17
+ maxScrolls: 10,
18
+ scrollDelayMs: 2000,
19
+ responseTimeoutMs: 5000,
20
+ navigationTimeoutMs: 15000,
21
+ };
22
+ async function acquireForNetworkSync(cdpUrl, cookies, stealth) {
23
+ // --- Layer 1: CDP via Playwright connectOverCDP ---
24
+ if (cdpUrl !== null && cdpUrl !== undefined) {
25
+ try {
26
+ const wsUrl = await resolveCdpUrl(cdpUrl === 'auto' ? 'auto' : cdpUrl, {
27
+ loggerLabel: 'BrowserNetwork',
28
+ preferRealBrowser: true,
29
+ });
30
+ const playwrightModule = 'playwright';
31
+ const { chromium } = await import(/* @vite-ignore */ playwrightModule);
32
+ const browser = await chromium.connectOverCDP(wsUrl);
33
+ // Use the default context (user's session) — don't create a new context
34
+ // which crashes on browsers with many tabs
35
+ const context = browser.contexts()[0];
36
+ if (!context)
37
+ throw new Error('Chrome has no browser context');
38
+ const page = await context.newPage();
39
+ sdkLogger.info({ wsUrl }, '[BrowserNetwork] Connected via CDP');
40
+ return {
41
+ browser,
42
+ context,
43
+ page,
44
+ backend: 'cdp',
45
+ ownsBrowser: false,
46
+ screenshotDir: '/tmp/feed-screenshots',
47
+ };
48
+ }
49
+ catch (err) {
50
+ sdkLogger.info({ error: err.message }, '[BrowserNetwork] CDP not available, falling back to Playwright');
51
+ }
52
+ }
53
+ // --- Layer 2: Playwright with stored cookies ---
54
+ const { browser, screenshotDir } = await launchBrowser({}, { stealth });
55
+ const context = (await browser.newContext());
56
+ if (cookies.length > 0) {
57
+ await context.addCookies(cookies);
58
+ sdkLogger.info({ count: cookies.length }, '[BrowserNetwork] Loaded persisted cookies');
59
+ }
60
+ const page = await context.newPage();
61
+ return {
62
+ browser: browser,
63
+ context,
64
+ page,
65
+ backend: 'playwright',
66
+ ownsBrowser: true,
67
+ screenshotDir,
68
+ };
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Main entry point
72
+ // ---------------------------------------------------------------------------
73
+ export async function browserNetworkSync(opts) {
74
+ const cfg = { ...DEFAULT_CONFIG, ...opts.config };
75
+ const items = [];
76
+ let apiCallCount = 0;
77
+ // Pre-compile string glob patterns into RegExp for hot-path matching
78
+ const matchers = cfg.interceptPatterns.map((p) => typeof p === 'string' ? compileGlob(p) : p);
79
+ const matchesUrl = (url) => matchers.some((re) => re.test(url));
80
+ const acquired = await acquireForNetworkSync(opts.cdpUrl ?? null, opts.cookies, cfg.stealth ?? false);
81
+ const { context, page, backend, ownsBrowser, browser, screenshotDir } = acquired;
82
+ try {
83
+ // Accumulates promises from async response handlers between drain points
84
+ const responsePromises = [];
85
+ page.on('response', (response) => {
86
+ if (!matchesUrl(response.url()))
87
+ return;
88
+ const p = response
89
+ .json()
90
+ .then((json) => {
91
+ apiCallCount++;
92
+ const parsed = opts.parseResponse(response.url(), json);
93
+ items.push(...parsed);
94
+ sdkLogger.info({ apiCall: apiCallCount, itemsInBatch: parsed.length, totalItems: items.length }, '[BrowserNetwork] Intercepted API response');
95
+ })
96
+ .catch(() => { });
97
+ responsePromises.push(p);
98
+ });
99
+ sdkLogger.info({ url: opts.url, backend }, '[BrowserNetwork] Navigating');
100
+ await page.goto(opts.url, {
101
+ waitUntil: 'domcontentloaded',
102
+ timeout: cfg.navigationTimeoutMs,
103
+ });
104
+ await page.waitForTimeout(cfg.responseTimeoutMs);
105
+ await drainPromises(responsePromises);
106
+ if (opts.checkAuth) {
107
+ const authed = await opts.checkAuth(page);
108
+ if (!authed) {
109
+ const msg = backend === 'cdp'
110
+ ? 'Authentication check failed via CDP — you may not be logged in to this site in Chrome'
111
+ : 'Authentication failed — cookies may be expired. Re-run: lobu memory browser-auth';
112
+ throw new Error(msg);
113
+ }
114
+ }
115
+ const triggerNext = opts.triggerNextPage ??
116
+ (async (p) => {
117
+ await p.evaluate(() => window.scrollTo(0, document.documentElement.scrollHeight));
118
+ });
119
+ let prevCount = items.length;
120
+ for (let scroll = 0; scroll < cfg.maxScrolls; scroll++) {
121
+ await triggerNext(page);
122
+ try {
123
+ await page.waitForResponse((resp) => matchesUrl(resp.url()), {
124
+ timeout: cfg.responseTimeoutMs,
125
+ });
126
+ }
127
+ catch {
128
+ sdkLogger.info({ scroll: scroll + 1 }, '[BrowserNetwork] No new API response, stopping');
129
+ break;
130
+ }
131
+ await page.waitForTimeout(cfg.scrollDelayMs);
132
+ await drainPromises(responsePromises);
133
+ if (items.length === prevCount) {
134
+ sdkLogger.info({ scroll: scroll + 1 }, '[BrowserNetwork] No new items, stopping');
135
+ break;
136
+ }
137
+ sdkLogger.info({ scroll: scroll + 1, newItems: items.length - prevCount, total: items.length }, '[BrowserNetwork] Scroll pagination');
138
+ prevCount = items.length;
139
+ }
140
+ // Always capture cookies — regardless of backend, these get persisted
141
+ const cookies = await context.cookies(cfg.authDomains.map((d) => (d.startsWith('http') ? d : `https://${d}`)));
142
+ return { items, cookies, apiCallCount, backend };
143
+ }
144
+ catch (error) {
145
+ if (page) {
146
+ await captureErrorArtifacts(page, error, 'browser-network', screenshotDir);
147
+ }
148
+ throw error;
149
+ }
150
+ finally {
151
+ // CDP: only close our tab, not the user's context or browser.
152
+ // Playwright: close context and browser (we own them).
153
+ if (ownsBrowser) {
154
+ await context.close().catch(() => { });
155
+ await browser.close().catch(() => { });
156
+ }
157
+ else {
158
+ await page.close().catch(() => { });
159
+ }
160
+ }
161
+ }
162
+ /** Snapshot-then-clear to avoid losing promises pushed between Promise.all and clear. */
163
+ async function drainPromises(arr) {
164
+ const batch = [...arr];
165
+ arr.length = 0;
166
+ await Promise.all(batch);
167
+ }
168
+ function compileGlob(pattern) {
169
+ const escaped = pattern
170
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
171
+ .replace(/\*\*/g, '.*')
172
+ .replace(/\*/g, '[^/]*');
173
+ return new RegExp(escaped);
174
+ }
175
+ //# sourceMappingURL=browser-network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-network.js","sourceRoot":"","sources":["../src/browser-network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA2BxC,MAAM,cAAc,GAKhB;IACF,UAAU,EAAE,EAAE;IACd,aAAa,EAAE,IAAI;IACnB,iBAAiB,EAAE,IAAI;IACvB,mBAAmB,EAAE,KAAK;CAC3B,CAAC;AAgBF,KAAK,UAAU,qBAAqB,CAClC,MAA0C,EAC1C,OAAiB,EACjB,OAAgB;IAEhB,qDAAqD;IACrD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE;gBACrE,WAAW,EAAE,gBAAgB;gBAC7B,iBAAiB,EAAE,IAAI;aACxB,CAAC,CAAC;YAEH,MAAM,gBAAgB,GAAG,YAAY,CAAC;YACtC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;YACvE,MAAM,OAAO,GAAY,MAAM,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAE9D,wEAAwE;YACxE,2CAA2C;YAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAmB,CAAC;YACxD,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAE/D,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YAErC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,oCAAoC,CAAC,CAAC;YAEhE,OAAO;gBACL,OAAO;gBACP,OAAO;gBACP,IAAI;gBACJ,OAAO,EAAE,KAAK;gBACd,WAAW,EAAE,KAAK;gBAClB,aAAa,EAAE,uBAAuB;aACvC,CAAC;QACJ,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,SAAS,CAAC,IAAI,CACZ,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,EACtB,gEAAgE,CACjE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,aAAa,CAAC,EAAW,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,CAAC,MAAO,OAAmB,CAAC,UAAU,EAAE,CAAmB,CAAC;IAC5E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,2CAA2C,CAAC,CAAC;IACzF,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAErC,OAAO;QACL,OAAO,EAAE,OAAkB;QAC3B,OAAO;QACP,IAAI;QACJ,OAAO,EAAE,YAAY;QACrB,WAAW,EAAE,IAAI;QACjB,aAAa;KACd,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAQ,IAa/C;IACC,MAAM,GAAG,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAClD,MAAM,KAAK,GAAY,EAAE,CAAC;IAC1B,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,qEAAqE;IACrE,MAAM,QAAQ,GAAa,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACzD,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC3C,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAExE,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAC1C,IAAI,CAAC,MAAM,IAAI,IAAI,EACnB,IAAI,CAAC,OAAO,EACZ,GAAG,CAAC,OAAO,IAAI,KAAK,CACrB,CAAC;IAEF,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,QAAQ,CAAC;IAEjF,IAAI,CAAC;QACH,yEAAyE;QACzE,MAAM,gBAAgB,GAAoB,EAAE,CAAC;QAE7C,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,QAAkB,EAAE,EAAE;YACzC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBAAE,OAAO;YACxC,MAAM,CAAC,GAAG,QAAQ;iBACf,IAAI,EAAE;iBACN,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACb,YAAY,EAAE,CAAC;gBACf,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;gBACxD,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;gBACtB,SAAS,CAAC,IAAI,CACZ,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,EAAE,EAChF,2CAA2C,CAC5C,CAAC;YACJ,CAAC,CAAC;iBACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACnB,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,6BAA6B,CAAC,CAAC;QAC1E,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACxB,SAAS,EAAE,kBAAkB;YAC7B,OAAO,EAAE,GAAG,CAAC,mBAAmB;SACjC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACjD,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAEtC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,GAAG,GACP,OAAO,KAAK,KAAK;oBACf,CAAC,CAAC,uFAAuF;oBACzF,CAAC,CAAC,kFAAkF,CAAC;gBACzF,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GACf,IAAI,CAAC,eAAe;YACpB,CAAC,KAAK,EAAE,CAAO,EAAE,EAAE;gBACjB,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;YACpF,CAAC,CAAC,CAAC;QAEL,IAAI,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;QAC7B,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC;YACvD,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;YAExB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,eAAe,CAAC,CAAC,IAAc,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE;oBACrE,OAAO,EAAE,GAAG,CAAC,iBAAiB;iBAC/B,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,gDAAgD,CAAC,CAAC;gBACzF,MAAM;YACR,CAAC;YAED,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC7C,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;YAEtC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC/B,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,yCAAyC,CAAC,CAAC;gBAClF,MAAM;YACR,CAAC;YAED,SAAS,CAAC,IAAI,CACZ,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,EAC/E,oCAAoC,CACrC,CAAC;YACF,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3B,CAAC;QAED,sEAAsE;QACtE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CACnC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CACxE,CAAC;QAEF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IACnD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,aAAa,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,8DAA8D;QAC9D,uDAAuD;QACvD,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,KAAK,UAAU,aAAa,CAAC,GAAoB;IAC/C,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IACvB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,MAAM,OAAO,GAAG,OAAO;SACpB,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC;SACpC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;SACtB,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3B,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC"}