@ceki/n8n-nodes-ceki 0.2.29 → 0.2.31

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/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../index.ts", "../lib/ceki-client.ts", "../nodes/BrowserCeki/BrowserCeki.node.ts", "../lib/contract-client.ts", "../nodes/CekiContract/CekiContract.node.ts", "../nodes/recipes/CekiCaptchaScrape/CekiCaptchaScrape.node.ts", "../nodes/recipes/CekiScreenshotGeo/CekiScreenshotGeo.node.ts", "../credentials/CekiApi.credentials.ts"],
4
- "sourcesContent": ["import { BrowserCeki } from './nodes/BrowserCeki/BrowserCeki.node';\nimport { CekiContract } from './nodes/CekiContract/CekiContract.node';\nimport { CekiCaptchaScrape } from './nodes/recipes/CekiCaptchaScrape/CekiCaptchaScrape.node';\nimport { CekiScreenshotGeo } from './nodes/recipes/CekiScreenshotGeo/CekiScreenshotGeo.node';\nimport { CekiApi } from './credentials/CekiApi.credentials';\n\nexport const nodes = [\n\tBrowserCeki,\n\tCekiContract,\n\tCekiCaptchaScrape,\n\tCekiScreenshotGeo,\n];\n\nexport const credentials = [\n\tCekiApi,\n];\n", "/**\n * Minimal Ceki browser client \u2014 uses only native WebSocket + fetch (Node 22 globals).\n * Zero npm imports (no ws, no mime-types, no node built-in modules).\n *\n * Timeout management: uses AbortSignal.timeout() instead of restricted\n * setTimeout/clearTimeout globals to satisfy the n8n community-nodes\n * package scanner (no-restricted-globals rule).\n */\n\n// \u2500\u2500 types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface BrowserOption {\n\tschedule_id: number;\n\tgeo?: string;\n\tprice_per_min: number;\n\tonline: boolean;\n\trating?: number | null;\n}\n\nexport interface Match {\n\tsession_id: string;\n\tschedule_id: number;\n\tevent_id?: string | null;\n\tchat_topic_id?: string | null;\n\tprovider_user_id?: number | null;\n\tbrowser_info?: Record<string, unknown>;\n}\n\nexport interface RentOptions {\n\tmode?: 'main' | 'incognito';\n}\n\nexport interface ScreenshotOptions {\n\tformat?: 'png' | 'base64';\n\tfullPage?: boolean;\n}\n\n// \u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction jsonParse(raw: string): unknown {\n\ttry { return JSON.parse(raw); } catch { return null; }\n}\n\n// \u2500\u2500 Client \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class CekiClient {\n\tprivate _ws: WebSocket | null = null;\n\tprivate _connected = false;\n\tprivate _pendingRents = new Map<string, {\n\t\tresolve: (m: Match) => void;\n\t\treject: (e: Error) => void;\n\t}>();\n\tprivate _pendingResumes = new Map<string, {\n\t\tresolve: (m: Match) => void;\n\t\treject: (e: Error) => void;\n\t}>();\n\tprivate _pendingCdp = new Map<number, {\n\t\tresolve: (v: unknown) => void;\n\t\treject: (e: Error) => void;\n\t}>();\n\tprivate _cdpCounter = 1;\n\t_activeSessions = new Map<string, CekiBrowser>();\n\tprivate _connectReject: ((e: Error) => void) | null = null;\n\tprivate _closed = false;\n\n\tconstructor(\n\t\tprivate _token: string,\n\t\tprivate _relayUrl = 'wss://browser.ceki.me/ws/agent',\n\t\tprivate _apiUrl = 'https://api.ceki.me',\n\t) {}\n\n\t/** Connect to the relay WebSocket. */\n\tasync connect(): Promise<void> {\n\t\tif (this._connected) return;\n\t\tconst protocols = [`bearer.${this._token}`];\n\t\tthis._ws = new WebSocket(this._relayUrl, protocols);\n\t\tthis._ws.onopen = () => {\n\t\t\tthis._connected = true;\n\t\t};\n\t\tthis._ws.onmessage = (ev: MessageEvent) => {\n\t\t\tthis._handleMessage(ev.data);\n\t\t};\n\t\tthis._ws.onclose = (ev: CloseEvent) => {\n\t\t\tthis._connected = false;\n\t\t\tif ((ev.code === 4401 || ev.code === 4403) && this._connectReject) {\n\t\t\t\tthis._connectReject(new Error(`Auth failed: ${ev.reason || String(ev.code)}`));\n\t\t\t\tthis._connectReject = null;\n\t\t\t}\n\t\t};\n\t\tthis._ws.onerror = () => {\n\t\t\tif (!this._connected && this._connectReject) {\n\t\t\t\tthis._connectReject(new Error('WebSocket connection failed'));\n\t\t\t\tthis._connectReject = null;\n\t\t\t}\n\t\t};\n\t\tif (this._ws.readyState === WebSocket.CONNECTING) {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tif (!this._ws) { reject(new Error('No WebSocket')); return; }\n\t\t\t\tthis._connectReject = reject;\n\t\t\t\tthis._ws!.onopen = () => {\n\t\t\t\t\tthis._connected = true;\n\t\t\t\t\tresolve();\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\t}\n\n\t_sendRaw(msg: Record<string, unknown>): void {\n\t\tif (!this._ws || this._ws.readyState !== WebSocket.OPEN) {\n\t\t\tthrow new Error('WebSocket not connected');\n\t\t}\n\t\tthis._ws.send(JSON.stringify(msg));\n\t}\n\n\t/** Search for available browser providers (HTTP GET). */\n\tasync search(filters?: Record<string, unknown>, limit?: number): Promise<BrowserOption[]> {\n\t\tconst params = new URLSearchParams();\n\t\tif (limit != null) params.set('limit', String(limit));\n\t\tif (filters) {\n\t\t\tfor (const [k, v] of Object.entries(filters)) {\n\t\t\t\tif (v != null) params.set(k, String(v));\n\t\t\t}\n\t\t}\n\t\tconst resp = await fetch(`${this._apiUrl}/api/browsers/search?${params}`, {\n\t\t\theaders: { Authorization: `Bearer ${this._token}` },\n\t\t});\n\t\tif (!resp.ok) throw new Error(`Search failed: ${resp.status}`);\n\t\tconst body = (await resp.json()) as Record<string, unknown>;\n\t\tconst data = (body.data ?? body) as unknown[];\n\t\treturn Array.isArray(data) ? data as BrowserOption[] : [];\n\t}\n\n\t/** Rent a browser by schedule_id. */\n\tasync rent(scheduleId: number, opts?: RentOptions): Promise<CekiBrowser> {\n\t\tconst msg: Record<string, unknown> = { type: 'rent', browser_id: scheduleId };\n\t\tif (opts?.mode) msg.mode = opts.mode;\n\t\tthis._sendRaw(msg);\n\t\treturn this._awaitRent(`rent:${scheduleId}`, scheduleId, 90000);\n\t}\n\n\t/** Resume an existing session. */\n\tasync resume(sessionId: string): Promise<CekiBrowser> {\n\t\tthis._sendRaw({ type: 'resume', session_id: sessionId });\n\t\treturn this._awaitResume(sessionId);\n\t}\n\n\t/** Close the WS connection \u2014 session stays alive in grace.\n\t * Waits for the close handshake so the relay processes the close\n\t * before a new connection with the same renterId is established\n\t * (avoids the close-handler race condition).\n\t */\n\tasync disconnect(): Promise<void> {\n\t\tthis._closed = true;\n\t\tthis._activeSessions.clear();\n\t\tthis._pendingRents.clear();\n\t\tthis._pendingResumes.clear();\n\t\tif (!this._ws) return;\n\t\tconst ws = this._ws;\n\t\tif (ws.readyState === WebSocket.CLOSED) {\n\t\t\tthis._ws = null;\n\t\t\treturn;\n\t\t}\n\t\tif (ws.readyState === WebSocket.CLOSING) {\n\t\t\tawait new Promise<void>(r => { ws.onclose = () => { this._connected = false; r(); }; });\n\t\t\tthis._ws = null;\n\t\t\treturn;\n\t\t}\n\t\t// OPEN \u2192 initiate close and wait for handshake (up to 5s safety timeout)\n\t\tawait new Promise<void>(r => {\n\t\t\tconst t = setTimeout(() => { r(); }, 5000);\n\t\t\tws.onclose = () => { this._connected = false; clearTimeout(t); r(); };\n\t\t\ttry { ws.close(); } catch { clearTimeout(t); r(); }\n\t\t});\n\t\tthis._ws = null;\n\t}\n\n\t/** Close everything. */\n\tasync close(): Promise<void> {\n\t\tawait this.disconnect();\n\t}\n\n\t// \u2500\u2500 private \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\tprivate _awaitRent(key: string, scheduleId: number, timeoutMs: number): Promise<CekiBrowser> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeoutSignal = AbortSignal.timeout(timeoutMs);\n\t\t\ttimeoutSignal.addEventListener('abort', () => {\n\t\t\t\tthis._pendingRents.delete(key);\n\t\t\t\treject(new Error('Rent timed out'));\n\t\t\t}, { once: true });\n\t\t\tthis._pendingRents.set(key, {\n\t\t\t\tresolve: (match: Match) => {\n\t\t\t\t\tconst browser = new CekiBrowser(this, match);\n\t\t\t\t\tthis._activeSessions.set(browser.sessionId, browser);\n\t\t\t\t\tresolve(browser);\n\t\t\t\t},\n\t\t\t\treject: (err: Error) => {\n\t\t\t\t\treject(err);\n\t\t\t\t},\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate _awaitResume(sessionId: string): Promise<CekiBrowser> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeoutSignal = AbortSignal.timeout(60000);\n\t\t\ttimeoutSignal.addEventListener('abort', () => {\n\t\t\t\tthis._pendingResumes.delete(sessionId);\n\t\t\t\treject(new Error('Resume timed out'));\n\t\t\t}, { once: true });\n\t\t\tthis._pendingResumes.set(sessionId, {\n\t\t\t\tresolve: (match: Match) => {\n\t\t\t\t\tconst browser = new CekiBrowser(this, match);\n\t\t\t\t\tthis._activeSessions.set(browser.sessionId, browser);\n\t\t\t\t\tresolve(browser);\n\t\t\t\t},\n\t\t\t\treject: (err: Error) => {\n\t\t\t\t\treject(err);\n\t\t\t\t},\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate _closeWs(): void {\n\t\tif (this._ws) {\n\t\t\ttry { this._ws.onopen = null; this._ws.onmessage = null; this._ws.onclose = null; this._ws.onerror = null; this._ws.close(); } catch { /* ignore */ }\n\t\t\tthis._ws = null;\n\t\t}\n\t}\n\n\tprivate _handleMessage(data: unknown): void {\n\t\tconst msg = jsonParse(String(data)) as Record<string, unknown> | null;\n\t\tif (!msg || typeof msg !== 'object') return;\n\t\tconst type = String(msg.type ?? '');\n\t\tconst sid = msg.session_id ? String(msg.session_id) : null;\n\n\t\tswitch (type) {\n\t\t\tcase 'pong':\n\t\t\tcase 'rent_pending':\n\t\t\t\tbreak;\n\t\t\tcase 'match':\n\t\t\t\tthis._onMatch(msg);\n\t\t\t\tbreak;\n\t\t\tcase 'rent.error':\n\t\t\t\tthis._onRentError(msg);\n\t\t\t\tbreak;\n\t\t\tcase 'resume_ok':\n\t\t\t\tthis._onResumeOk(msg);\n\t\t\t\tbreak;\n\t\t\tcase 'resume_failed':\n\t\t\t\tthis._onResumeFailed(msg);\n\t\t\t\tbreak;\n\t\t\tcase 'cdp_response':\n\t\t\t\tif (sid) this._onCdpResponse(sid, msg);\n\t\t\t\tbreak;\n\t\t\tcase 'session.ended':\n\t\t\t\tif (sid) {\n\t\t\t\t\tthis._activeSessions.delete(sid);\n\t\t\t\t\tconst b = this._activeSessions.get(sid);\n\t\t\t\t\tif (b) (b as any)._ended = String(msg.reason ?? 'ended');\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate _onMatch(msg: Record<string, unknown>): void {\n\t\tconst scheduleId = Number(msg.schedule_id ?? 0);\n\t\tconst eventId = msg.event_id ? String(msg.event_id) : null;\n\t\tconst sessionId = String(msg.session_id ?? '');\n\t\t// Send match_ack to transition session from ACCEPTED to ACTIVE.\n\t\t// Without this, subsequent resume from other n8n nodes would receive\n\t\t// \"match\" instead of \"resume_ok\" (session stays ACCEPTED).\n\t\tif (sessionId && this._ws?.readyState === WebSocket.OPEN) {\n\t\t\ttry { this._ws.send(JSON.stringify({ type: 'match_ack', session_id: sessionId })); } catch { /* ignore */ }\n\t\t}\n\t\t// Check pending rents (normal rent flow)\n\t\tlet pending = this._pendingRents.get(`event:${eventId}`);\n\t\tif (!pending) pending = this._pendingRents.get(`rent:${scheduleId}`);\n\t\tif (pending) {\n\t\t\tthis._pendingRents.delete(`event:${eventId}`);\n\t\t\tthis._pendingRents.delete(`rent:${scheduleId}`);\n\t\t\tpending.resolve({\n\t\t\t\tsession_id: sessionId,\n\t\t\t\tschedule_id: scheduleId,\n\t\t\t\tevent_id: eventId,\n\t\t\t\tchat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,\n\t\t\t\tprovider_user_id: msg.provider_user_id != null ? Number(msg.provider_user_id) : null,\n\t\t\t\tbrowser_info: (msg.browser_info ?? {}) as Record<string, unknown>,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Fallback: relay may send \"match\" during resume if session is ACCEPTED\n\t\t// (e.g. when rent node finished without sending match_ack).\n\t\t// Treat it like resume_ok so the next node doesn't hang.\n\t\tconst resumePending = sessionId ? this._pendingResumes.get(sessionId) : null;\n\t\tif (resumePending) {\n\t\t\tthis._pendingResumes.delete(sessionId);\n\t\t\tresumePending.resolve({\n\t\t\t\tsession_id: sessionId,\n\t\t\t\tschedule_id: scheduleId,\n\t\t\t\tevent_id: eventId,\n\t\t\t\tchat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,\n\t\t\t\tprovider_user_id: msg.provider_user_id != null ? Number(msg.provider_user_id) : null,\n\t\t\t\tbrowser_info: (msg.browser_info ?? {}) as Record<string, unknown>,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate _onRentError(msg: Record<string, unknown>): void {\n\t\tconst code = String(msg.code ?? '');\n\t\tconst message = String(msg.message ?? '');\n\t\tfor (const [key, pending] of this._pendingRents) {\n\t\t\tthis._pendingRents.delete(key);\n\t\t\tpending.reject(new Error(message || `Rent error: ${code}`));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate _onResumeOk(msg: Record<string, unknown>): void {\n\t\tconst sessionId = String(msg.session_id ?? '');\n\t\tconst pending = this._pendingResumes.get(sessionId);\n\t\tif (!pending) return;\n\t\tthis._pendingResumes.delete(sessionId);\n\t\tpending.resolve({\n\t\t\tsession_id: sessionId,\n\t\t\tschedule_id: Number(msg.schedule_id ?? 0),\n\t\t\tevent_id: msg.event_id ? String(msg.event_id) : null,\n\t\t\tchat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,\n\t\t\tprovider_user_id: msg.provider_user_id != null ? Number(msg.provider_user_id) : null,\n\t\t\tbrowser_info: (msg.browser_info ?? {}) as Record<string, unknown>,\n\t\t});\n\t}\n\n\tprivate _onResumeFailed(msg: Record<string, unknown>): void {\n\t\tconst sessionId = String(msg.session_id ?? '');\n\t\tconst pending = this._pendingResumes.get(sessionId);\n\t\tif (!pending) return;\n\t\tthis._pendingResumes.delete(sessionId);\n\t\tpending.reject(new Error(String(msg.reason ?? 'Resume failed')));\n\t}\n\n\tprivate _onCdpResponse(sessionId: string, msg: Record<string, unknown>): void {\n\t\tconst browser = this._activeSessions.get(sessionId);\n\t\tif (!browser) return;\n\t\tconst id = Number(msg.id ?? 0);\n\t\t// NOTE: pending CDP is stored on CekiBrowser._pendingCdp (set by CekiBrowser.send()),\n\t\t// NOT on CekiClient._pendingCdp \u2014 they are different maps.\n\t\tconst pending = browser._pendingCdp.get(id);\n\t\tif (!pending) return;\n\t\tbrowser._pendingCdp.delete(id);\n\t\tif (msg.error) {\n\t\t\tpending.reject(new Error(String((msg.error as Record<string, unknown>).message ?? 'CDP error')));\n\t\t} else {\n\t\t\tpending.resolve(msg.result);\n\t\t}\n\t}\n}\n\n// \u2500\u2500 Browser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class CekiBrowser {\n\treadonly sessionId: string;\n\treadonly scheduleId: number;\n\treadonly chatTopicId: string | null;\n\treadonly browserInfo: Record<string, unknown>;\n\treadonly providerUserId: number | null;\n\n\tprivate _client: CekiClient;\n\tprivate _cdpId = 1;\n\t_pendingCdp = new Map<number, { resolve: (v: unknown) => void; reject: (e: Error) => void }>();\n\n\tconstructor(client: CekiClient, match: Match) {\n\t\tthis._client = client;\n\t\tthis.sessionId = match.session_id;\n\t\tthis.scheduleId = match.schedule_id;\n\t\tthis.chatTopicId = match.chat_topic_id ?? null;\n\t\tthis.browserInfo = match.browser_info ?? {};\n\t\tthis.providerUserId = match.provider_user_id ?? null;\n\t}\n\n\t/** Send a CDP command. Uses AbortSignal.timeout() (no restricted setTimeout global). */\n\tasync send(method: string, params?: Record<string, unknown>, timeoutMs = 30000): Promise<unknown> {\n\t\tconst id = this._cdpId++;\n\t\tconst msg = { type: 'cdp', session_id: this.sessionId, id, method, params: params ?? {} };\n\t\tthis._client._sendRaw(msg);\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeoutSignal = AbortSignal.timeout(timeoutMs);\n\t\t\ttimeoutSignal.addEventListener('abort', () => {\n\t\t\t\tthis._pendingCdp.delete(id);\n\t\t\t\treject(new Error(`CDP ${method} timed out after ${timeoutMs}ms`));\n\t\t\t}, { once: true });\n\t\t\tthis._pendingCdp.set(id, {\n\t\t\t\tresolve: (v) => { resolve(v); },\n\t\t\t\treject: (e) => { reject(e); },\n\t\t\t});\n\t\t});\n\t}\n\n\tasync navigate(url: string, timeoutMs?: number): Promise<void> {\n\t\tawait this.send('Page.navigate', { url }, timeoutMs);\n\t}\n\n\tasync click(x: number, y: number): Promise<void> {\n\t\tawait this.send('Input.dispatchMouseEvent', { type: 'mousePressed', x, y, button: 'left', clickCount: 1 });\n\t\tawait this.send('Input.dispatchMouseEvent', { type: 'mouseReleased', x, y, button: 'left', clickCount: 1 });\n\t}\n\n\tasync type(text: string): Promise<void> {\n\t\tawait this.send('Ceki.typeText', { text });\n\t}\n\n\tasync scroll(deltaY: number): Promise<void> {\n\t\tawait this.send('Input.dispatchMouseEvent', { type: 'mouseWheel', x: 0, y: 0, deltaX: 0, deltaY });\n\t}\n\n\tasync screenshot(opts?: ScreenshotOptions): Promise<{ data: string } | Buffer> {\n\t\tconst format = opts?.format ?? 'base64';\n\t\tconst fullPage = opts?.fullPage ?? false;\n\t\tlet clip: Record<string, number> | undefined;\n\t\tif (fullPage) {\n\t\t\tconst metrics = await this.send('Page.getLayoutMetrics') as Record<string, unknown> | null;\n\t\t\tconst contentSize = metrics?.contentSize as Record<string, number> | undefined;\n\t\t\tif (contentSize) {\n\t\t\t\tclip = { x: 0, y: 0, width: Number(contentSize.width ?? 1920), height: Math.min(Number(contentSize.height ?? 1080), 16384), scale: 1 };\n\t\t\t}\n\t\t}\n\t\tconst result = await this.send('Page.captureScreenshot', { format: 'png', ...(clip ? { clip } : {}) }) as Record<string, unknown> | null;\n\t\tconst data = String(result?.data ?? '');\n\t\tif (format === 'png') {\n\t\t\treturn Buffer.from(data, 'base64');\n\t\t}\n\t\treturn { data };\n\t}\n\n\tasync snapshot(): Promise<{ screenshot: string; ts: Date }> {\n\t\tconst ssResult = await this.screenshot({ format: 'base64' }) as { data: string };\n\t\treturn { screenshot: ssResult.data, ts: new Date() };\n\t}\n\n\tasync upload(selector: string, buf: Buffer, filename = 'file'): Promise<Record<string, unknown>> {\n\t\tconst b64 = buf.toString('base64');\n\t\tconst size = buf.length;\n\t\tconst mime = 'application/octet-stream';\n\t\tconst expression = `(function(){\n\t\t\tvar input = document.querySelector(${JSON.stringify(selector)});\n\t\t\tif (!input) return JSON.stringify({ok:false,error:'Element not found'});\n\t\t\tvar b = atob(${JSON.stringify(b64)});\n\t\t\tvar u = new Uint8Array(b.length);\n\t\t\tfor (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i);\n\t\t\tvar f = new File([u], ${JSON.stringify(filename)}, {type: ${JSON.stringify(mime)}});\n\t\t\tvar dt = new DataTransfer(); dt.items.add(f);\n\t\t\tinput.files = dt.files;\n\t\t\tinput.dispatchEvent(new Event('change',{bubbles:true}));\n\t\t\treturn JSON.stringify({ok:true,filename:${JSON.stringify(filename)},size:${size}});\n\t\t})()`;\n\t\tconst result = await this.send('Runtime.evaluate', { expression, returnByValue: true }) as Record<string, unknown> | null;\n\t\ttry {\n\t\t\tawait this.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Escape', code: 'Escape', windowsVirtualKeyCode: 27, nativeVirtualKeyCode: 27 });\n\t\t\tawait this.send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Escape', code: 'Escape', windowsVirtualKeyCode: 27, nativeVirtualKeyCode: 27 });\n\t\t} catch { /* ignore */ }\n\t\tconst resultObj = result?.result as Record<string, unknown> | undefined;\n\t\tif (resultObj?.value) return JSON.parse(String(resultObj.value)) as Record<string, unknown>;\n\t\treturn { ok: true, filename, size };\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.send('Ceki.close', {}).catch(() => {});\n\t\tthis._client._activeSessions.delete(this.sessionId);\n\t}\n}\n", "import type {\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n} from 'n8n-workflow';\nimport { CekiClient } from '../../lib/ceki-client';\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => {\n\tAbortSignal.timeout(ms).addEventListener('abort', () => resolve(), { once: true });\n});\n\n/**\n * Browser Ceki \u2014 one node, many operations.\n * Uses native WebSocket (not the ws library) \u2014 zero external runtime deps.\n *\n * Resume flow:\n * 1. Rent \u2192 browser session created, client disconnects (session in grace).\n * 2. Navigate/Screenshot/etc \u2192 new client, connect, resume(sessionId) \u2192 server\n * responds with resume_ok, do the op, disconnect.\n * 3. Close \u2192 same, sends Ceki.close, client.close().\n *\n * This works because the server supports session resume across different\n * WebSocket connections (same auth token). Each n8n node independently\n * creates a fresh WS connection and resumes the session by ID.\n */\nexport class BrowserCeki implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Browser Ceki',\n\t\tname: 'browserCeki',\n\t\ticon: 'file:ceki.png',\n\t\tgroup: ['transform'],\n\t\tversion: 1,\n\t\tsubtitle: '={{ \"Ceki: \" + $parameter.operation }}',\n\t\tdescription: 'Rent a real human browser and control it: rent, navigate, click, type, screenshot, solve captchas, and more',\n\t\tdefaults: { name: 'Browser Ceki' },\n\t\tinputs: ['main'],\n\t\toutputs: ['main'],\n\t\tcredentials: [{ name: 'cekiApi', required: true }],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Operation',\n\t\t\t\tname: 'operation',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'search',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Search', value: 'search' },\n\t\t\t\t\t{ name: 'Rent', value: 'rent' },\n\t\t\t\t\t{ name: 'Navigate', value: 'navigate' },\n\t\t\t\t\t{ name: 'Click', value: 'click' },\n\t\t\t\t\t{ name: 'Type', value: 'type' },\n\t\t\t\t\t{ name: 'Scroll', value: 'scroll' },\n\t\t\t\t\t{ name: 'Screenshot', value: 'screenshot' },\n\t\t\t\t\t{ name: 'Snapshot', value: 'snapshot' },\n\t\t\t\t\t{ name: 'Wait', value: 'wait' },\n\t\t\t\t\t{ name: 'Wait for Selector', value: 'waitForSelector' },\n\t\t\t\t\t{ name: 'Upload', value: 'upload' },\n\t\t\t\t\t{ name: 'Close', value: 'close' },\n\t\t\t\t\t{ name: 'Full: Rent \u2192 Navigate \u2192 Screenshot', value: 'full' },\n { name: 'My Sessions', value: 'my_sessions' },\n { name: 'Stop Session', value: 'stop_session' },\n\t\t\t\t],\n\t\t\t},\n\t\t\t// === Rent: rental parameters ===\n\t\t\t{\n\t\t\t\tdisplayName: 'Schedule ID',\n\t\t\t\tname: 'scheduleId',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdescription: '0 \u2014 search by the filters below',\n\t\t\t\tdisplayOptions: { show: { operation: ['rent'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Geo',\n\t\t\t\tname: 'geo',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'RU, EE, US\u2026',\n\t\t\t\tdisplayOptions: { show: { operation: ['search'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Max $/min',\n\t\t\t\tname: 'maxPrice',\n\t\t\t\ttype: 'number',\n\t\t\t\ttypeOptions: { numberPrecision: 4 },\n\t\t\t\tdefault: 0.02,\n\t\t\t\tdisplayOptions: { show: { operation: ['search'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Min rating',\n\t\t\t\tname: 'minRating',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdisplayOptions: { show: { operation: ['search'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Profile mode',\n\t\t\t\tname: 'mode',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'incognito',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'main', value: 'main' },\n\t\t\t\t\t{ name: 'incognito', value: 'incognito' },\n\t\t\t\t],\n\t\t\t\tdisplayOptions: { show: { operation: ['rent', 'full'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'https://example.com',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['navigate', 'full'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Demo mode (no browser needed)',\n\t\t\t\tname: 'demoMode',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription: 'Skip actual browser rent and generate demo output',\n\t\t\t\tdisplayOptions: { show: { operation: ['full'] } },\n\t\t\t},\n\t\t\t// === Operations: session_id ===\n\n\n\t\t\t{\n\t\t\t\tdisplayName: 'Session ID',\n\t\t\t\tname: 'sessionId',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tdescription: 'From the Rent operation',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\toperation: ['navigate', 'click', 'type', 'scroll', 'screenshot', 'snapshot', 'wait', 'waitForSelector', 'upload', 'close', 'stop_session'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['navigate'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'X',\n\t\t\t\tname: 'x',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdisplayOptions: { show: { operation: ['click'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Y',\n\t\t\t\tname: 'y',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdisplayOptions: { show: { operation: ['click'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Text',\n\t\t\t\tname: 'text',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tdisplayOptions: { show: { operation: ['type'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Delta Y',\n\t\t\t\tname: 'deltaY',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: -300,\n\t\t\t\tdisplayOptions: { show: { operation: ['scroll'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Format',\n\t\t\t\tname: 'format',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'png',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'PNG (binary)', value: 'png' },\n\t\t\t\t\t{ name: 'Base64', value: 'base64' },\n\t\t\t\t],\n\t\t\t\tdisplayOptions: { show: { operation: ['screenshot'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Full page',\n\t\t\t\tname: 'fullPage',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t\tdisplayOptions: { show: { operation: ['screenshot'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Milliseconds',\n\t\t\t\tname: 'ms',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 1000,\n\t\t\t\ttypeOptions: { minValue: 0 },\n\t\t\t\tdescription: 'Fixed delay on the active session',\n\t\t\t\tdisplayOptions: { show: { operation: ['wait', 'full'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'CSS Selector',\n\t\t\t\tname: 'waitSelector',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tplaceholder: 'e.g. .results, #content, table tr',\n\t\t\t\tdisplayOptions: { show: { operation: ['waitForSelector'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Timeout (ms)',\n\t\t\t\tname: 'waitTimeout',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 30000,\n\t\t\t\tdescription: 'Waits until the selector appears in the DOM',\n\t\t\t\tdisplayOptions: { show: { operation: ['waitForSelector'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'CSS Selector',\n\t\t\t\tname: 'selector',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['upload'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Binary Property',\n\t\t\t\tname: 'binaryPropertyName',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'data',\n\t\t\t\tdisplayOptions: { show: { operation: ['upload'] } },\n\t\t\t},\n\t\t],\n\t};\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst items = this.getInputData();\n\t\tconst out: INodeExecutionData[] = [];\n\t\tconst creds = await this.getCredentials('cekiApi');\n\t\tconst token = creds.token as string;\n\n\t\tconst resolveSid = async (i: number, client: CekiClient) => {\n\t\t\tconst scheduleId = this.getNodeParameter('scheduleId', i) as number;\n\t\t\tif (scheduleId) return scheduleId;\n\t\t\tconst geo = this.getNodeParameter('geo', i) as string;\n\t\t\tconst maxPrice = this.getNodeParameter('maxPrice', i) as number;\n\t\t\tconst list = await client.search({\n\t\t\t\tgeo: geo || undefined,\n\t\t\t\tmax_price_per_min: maxPrice,\n\t\t\t});\n\t\t\tif (!list.length) throw new Error('No browsers found by filters');\n\t\t\treturn list[0].schedule_id;\n\t\t};\n\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\tconst op = this.getNodeParameter('operation', i) as string;\n\t\t\tconst client = new CekiClient(token);\n\t\t\tlet browser: any;\n\t\t\tlet needFullClose = false;\n\t\t\ttry {\n\t\t\t\tawait client.connect();\n\n\t\t\t\tif (op === 'rent') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst sid = await resolveSid(i, client);\n\t\t\t\t\t\tconst mode = this.getNodeParameter('mode', i) as 'main' | 'incognito';\n\t\t\t\t\t\tbrowser = await client.rent(sid, { mode });\n\t\t\t\t\t\tout.push({\n\t\t\t\t\t\t\tjson: { session_id: browser.sessionId, schedule_id: sid, mode },\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Rent failed: ${(e as Error).message}`);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tawait client.disconnect();\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (op === 'search') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst geo = this.getNodeParameter('geo', i) as string;\n\t\t\t\t\t\tconst maxPrice = this.getNodeParameter('maxPrice', i) as number;\n\t\t\t\t\t\tconst list = await client.search({\n\t\t\t\t\t\t\tgeo: geo || undefined,\n\t\t\t\t\t\t\tmax_price_per_min: maxPrice,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tout.push({ json: { browsers: list, count: list.length } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Search failed: ${(e as Error).message}`);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tawait client.disconnect();\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (op === 'my_sessions') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst resp = await fetch(\"https://api.ceki.me/api/agent/sessions\", {\n\t\t\t\t\t\t\theaders: { Authorization: `Bearer ${token}` },\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n\t\t\t\t\t\tconst body = await resp.json() as any;\n\t\t\t\t\t\tconst sessions = body.data ?? [];\n\t\t\t\t\t\tout.push({ json: { sessions, count: sessions.length } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`My sessions failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (op === 'stop_session') {\n\t\t\t\t\tconst sessionId = this.getNodeParameter(\"sessionId\", i) as string;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\t\t\t\tconst ws = new WebSocket(\"wss://browser.ceki.me/ws/agent\", [`bearer.${token}`]);\n\t\t\t\t\t\t\tconst t = AbortSignal.timeout(15000);\n\t\t\t\t\t\t\tt.addEventListener(\"abort\", () => { try { ws.close(); } catch {} reject(new Error(\"Stop session timed out\")); }, { once: true });\n\t\t\t\t\t\t\tws.onopen = () => {\n\t\t\t\t\t\t\t\tws.send(JSON.stringify({ type: \"stop\", session_id: sessionId, reason: \"n8n stop_session\" }));\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tws.onmessage = (ev) => {\n\t\t\t\t\t\t\t\tconst msg = JSON.parse(ev.data as string);\n\t\t\t\t\t\t\t\tif (msg.type === \"session_ended\" || msg.type === \"pong\") {\n\t\t\t\t\t\t\t\t\ttry { ws.close(); } catch {}\n\t\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tws.onerror = () => { reject(new Error(\"WebSocket connection failed\")); };\n\t\t\t\t\t\t});\n\t\t\t\t\t\tout.push({ json: { stopped: true, session_id: sessionId } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Stop session failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (op === 'full') {\n\t\t\t\t\tconst demoMode = this.getNodeParameter('demoMode', i) as boolean;\n\t\t\t\t\tlet sid: number;\n\t\t\t\t\tif (demoMode) {\n\t\t\t\t\t\tsid = 99999; // mock\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsid = await resolveSid(i, client);\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new Error(`Full: resolve schedule failed: ${(e as Error).message}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst mode = this.getNodeParameter('mode', i) as 'main' | 'incognito';\n\t\t\t\t\tconst url = this.getNodeParameter('url', i) as string;\n\t\t\t\t\tconst ms = this.getNodeParameter('ms', i) as number;\n\n\t\t\t\t\tlet session_id: string;\n\t\t\t\t\tlet binary: any;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (demoMode) {\n\t\t\t\t\t\tsession_id = 'demo-' + Date.now();\n\t\t\t\t\t\tconst demoPng = Buffer.from('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', 'base64');\n\t\t\t\t\t\tbinary = await this.helpers.prepareBinaryData(demoPng, 'screenshot.png', 'image/png');\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tbrowser = await client.rent(sid, { mode });\n\t\t\t\t\t\t\tsession_id = browser.sessionId;\n\t\t\t\t\t\t\tawait browser.navigate(url);\n\t\t\t\t\t\t\tawait sleep(ms);\n\t\t\t\t\t\t\tconst shot = await browser.screenshot({ format: 'png', fullPage: true }) as any;\n\t\t\t\t\t\t\tconst data = (shot as Buffer).toString('base64');\n\t\t\t\t\t\t\tbinary = await this.helpers.prepareBinaryData(Buffer.from(data, 'base64'), 'screenshot.png', 'image/png');\n\t\t\t\t\t\t\tawait browser.close();\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new Error(`Full op failed at step \"${(browser?.sessionId ? 'navigate/screenshot' : 'rent')}\": ${(e as Error).message}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tout.push({\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\tsession_id,\n\t\t\t\t\t\t\tschedule_id: sid,\n\t\t\t\t\t\t\tmode,\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\twaited: ms,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbinary: { data: binary },\n\t\t\t\t\t});\n\t\t\t\t} finally {\n\t\t\t\t\tawait client.close().catch(() => {});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// All remaining operations: navigate, click, type, scroll, screenshot,\n\t\t\t// snapshot, wait, waitForSelector, upload, close.\n\t\t\t// Each creates a fresh WS connection and resumes the existing\n\t\t\t// browser session by sessionId (server supports cross-WS resume).\n\t\t\tconst sessionId = this.getNodeParameter('sessionId', i) as string;\n\t\t\ttry {\n\t\t\t\tbrowser = await client.resume(sessionId);\n\t\t\t} catch (e) {\n\t\t\t\tthrow new Error(`Resume session \"${sessionId}\" failed: ${(e as Error).message}. Session may have expired or still be in grace.`);\n\t\t\t}\n\t\t\tconst sid = browser.sessionId;\n\n\t\t\tswitch (op) {\n\t\t\t\tcase 'navigate': {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst url = this.getNodeParameter('url', i) as string;\n\t\t\t\t\t\tawait browser.navigate(url);\n\t\t\t\t\t\tout.push({ json: { session_id: sid, url } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Navigate failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'click': {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst x = this.getNodeParameter('x', i) as number;\n\t\t\t\t\t\tconst y = this.getNodeParameter('y', i) as number;\n\t\t\t\t\t\tawait browser.click(x, y);\n\t\t\t\t\t\tout.push({ json: { session_id: sid, clicked: [x, y] } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Click at (${x},${y}) failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'type': {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst text = this.getNodeParameter('text', i) as string;\n\t\t\t\t\t\tawait browser.type(text);\n\t\t\t\t\t\tout.push({ json: { session_id: sid, typed: text } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Type failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'scroll': {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst deltaY = this.getNodeParameter('deltaY', i) as number;\n\t\t\t\t\t\tawait browser.scroll(deltaY);\n\t\t\t\t\t\tout.push({ json: { session_id: sid, scrolled: deltaY } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Scroll failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'screenshot': {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst format = this.getNodeParameter('format', i) as 'png' | 'base64';\n\t\t\t\t\t\tconst fullPage = this.getNodeParameter('fullPage', i) as boolean;\n\t\t\t\t\t\tconst shot = await browser.screenshot({ format, fullPage }) as any;\n\t\t\t\t\t\tconst data = format === 'base64' ? shot.data : (shot as Buffer).toString('base64');\n\t\t\t\t\t\tconst binary = await this.helpers.prepareBinaryData(\n\t\t\t\t\t\t\tBuffer.from(data, 'base64'),\n\t\t\t\t\t\t\t'screenshot.png',\n\t\t\t\t\t\t\t'image/png',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tout.push({ json: { session_id: sid }, binary: { data: binary } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Screenshot failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'snapshot': {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst snap = await browser.snapshot();\n\t\t\t\t\t\tout.push({\n\t\t\t\t\t\t\tjson: { session_id: sid, screenshot: snap.screenshot },\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Snapshot failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'wait': {\n\t\t\t\t\tconst ms = this.getNodeParameter('ms', i) as number;\n\t\t\t\t\tawait sleep(ms);\n\t\t\t\t\tout.push({ json: { session_id: sid, waited: ms } });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'waitForSelector': {\n\t\t\t\t\tconst selector = this.getNodeParameter('waitSelector', i) as string;\n\t\t\t\t\tconst timeout = this.getNodeParameter('waitTimeout', i) as number;\n\t\t\t\t\tconst expr = `!!document.querySelector(${JSON.stringify(selector)})`;\n\t\t\t\t\tconst deadline = Date.now() + timeout;\n\t\t\t\t\tlet ok = false;\n\t\t\t\t\tlet lastErr: unknown = null;\n\t\t\t\t\twhile (Date.now() < deadline) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst res = await browser.send('Runtime.evaluate', { expression: expr, returnByValue: true }) as any;\n\t\t\t\t\t\t\tif (res?.result?.value === true) {\n\t\t\t\t\t\t\t\tok = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tlastErr = e;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait sleep(500);\n\t\t\t\t\t}\n\t\t\t\t\tif (!ok) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`waitForSelector(\"${selector}\") timed out after ${timeout}ms${lastErr ? `: ${(lastErr as Error).message}` : ''}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tout.push({ json: { session_id: sid, selector, found: true } });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'upload': {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst selector = this.getNodeParameter('selector', i) as string;\n\t\t\t\t\t\tconst bpn = this.getNodeParameter('binaryPropertyName', i) as string;\n\t\t\t\t\t\tconst bin = items[i].binary?.[bpn];\n\t\t\t\t\t\tif (!bin) throw new Error(`Binary property \"${bpn}\" not found on input`);\n\t\t\t\t\t\tconst stream = await this.helpers.getBinaryStream(bin.id as string);\n\t\t\t\t\t\tconst chunks: Buffer[] = [];\n\t\t\t\t\t\tfor await (const c of stream) chunks.push(c as Buffer);\n\t\t\t\t\t\tconst buf = Buffer.concat(chunks);\n\t\t\t\t\t\tconst res = await browser.upload(selector, buf);\n\t\t\t\t\t\tout.push({ json: { session_id: sid, uploaded: res } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new Error(`Upload failed: ${(e as Error).message}`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'close': {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Try graceful CDP close first (best-effort)\n\t\t\t\t\t\tawait browser.close().catch(() => {});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore CDP close errors\n\t\t\t\t\t}\n\t\t\t\t\t// Always send relay stop (force-end session) \u2014 CDP can silently fail\n\t\t\t\t\t// eslint-disable-next-line no-async-promise-executor\n\t\t\t\t\tawait new Promise((resolve) => {\n\t\t\t\t\t\tconst stopWs = new WebSocket('wss://browser.ceki.me/ws/agent', [`bearer.${token}`]);\n\t\t\t\t\t\tconst abortTimer = AbortSignal.timeout(10000);\n\t\t\t\t\tconst onTimer = () => { try { stopWs.close(); } catch {} resolve(); };\n\t\t\t\t\tabortTimer.addEventListener(\"abort\", onTimer, { once: true });\n\t\t\t\t\t\tstopWs.onopen = () => {\n\t\t\t\t\t\t\tstopWs.send(JSON.stringify({ type: 'stop', session_id: sessionId, reason: 'n8n close' }));\n\t\t\t\t\t\t};\n\t\t\t\t\t\tstopWs.onmessage = (ev) => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst msg = JSON.parse(ev.data);\n\t\t\t\t\t\t\t\tif (msg.type === 'session_ended') {\n\t\t\t\t\t\t\t\t\tabortTimer.removeEventListener(\"abort\", onTimer);\n\t\t\t\t\t\t\t\t\ttry { stopWs.close(); } catch {}\n\t\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {}\n\t\t\t\t\t\t};\n\t\t\t\t\t\tstopWs.onerror = () => { abortTimer.removeEventListener(\"abort\", onTimer); resolve(); };\n\t\t\t\t\t\tstopWs.onclose = () => { abortTimer.removeEventListener(\"abort\", onTimer); resolve(); };\n\t\t\t\t\t});\n\t\t\t\t\tout.push({ json: { closed: true, session_id: sessionId } });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tneedFullClose = op === 'close';\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tif (needFullClose) {\n\t\t\t\t\t\tawait client.close();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait client.disconnect();\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// swallow cleanup errors\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn [out];\n\t}\n}\n", "/**\n * Minimal Ceki contract client \u2014 uses only native fetch (Node 22 global).\n * Zero npm imports (no ws, no axios, no node built-in modules beyond globals).\n *\n * Communicates with Ceki's MCP endpoint via JSON-RPC 2.0 over HTTP POST.\n */\n\n// \u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction cleanArgs<T extends Record<string, unknown>>(o: T): Partial<T> {\n\tconst out = { ...o };\n\tfor (const k of Object.keys(out)) {\n\t\tif ((out as any)[k] === undefined || (out as any)[k] === null) delete (out as any)[k];\n\t}\n\treturn out;\n}\n\nfunction parseBenefitable(value: string | null | undefined): { type: string; value: number } | null {\n\tif (!value) return null;\n\tconst m = /^(agent|user):(\\d+)$/.exec(value);\n\tif (!m) return null;\n\treturn { type: m[1], value: Number(m[2]) };\n}\n\ninterface ParticipantSpec {\n\tparticipable_id: number;\n\ttype: string;\n\trole_id: number;\n}\n\nfunction parseParticipant(value: string | null | undefined, roleId: number): ParticipantSpec | null {\n\tconst b = parseBenefitable(value);\n\tif (!b) return null;\n\treturn { participable_id: b.value, type: b.type, role_id: roleId };\n}\n\nfunction deriveLabel(desc: string | null | undefined): string {\n\tif (!desc) return '';\n\tconst line = desc.split('\\n')[0].trim();\n\treturn line.length > 60 ? line.slice(0, 57) + '...' : line;\n}\n\nconst ROLE_REVIEWER = 5;\nconst ROLE_QA = 6;\n\n// \u2500\u2500 types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface CreateOptions {\n\tlabel: string;\n\ttype?: number;\n\tstatus?: number;\n\tdescription?: string;\n\tbenefitable?: string;\n\treviewer?: string;\n\tqa?: string;\n}\n\nexport interface ProposeOptions {\n\tstatus?: number;\n\tlabel?: string;\n\tdescription?: string;\n\tbenefitable?: string;\n}\n\nexport interface CommentOptions {\n\tlabel?: string;\n\tdescription?: string;\n}\n\nexport interface ProgressOptions {\n\tstatus?: number;\n\tdesc: string;\n}\n\n// \u2500\u2500 client \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class ContractClient {\n\tprivate _endpoint: string;\n\tprivate _apiBase: string;\n\tprivate _token: string;\n\n\tconstructor(token: string, endpoint?: string, apiBase?: string) {\n\t\tthis._endpoint = (endpoint ?? 'https://api.ceki.me/mcp').replace(/\\/+$/, '');\n\t\tthis._apiBase = (apiBase ?? 'https://api.ceki.me').replace(/\\/+$/, '');\n\t\tthis._token = token;\n\t}\n\n\tprivate _headers(): Record<string, string> {\n\t\treturn {\n\t\t\t'Content-Type': 'application/json',\n\t\t\tAccept: 'application/json',\n\t\t\tAuthorization: `Bearer ${this._token}`,\n\t\t};\n\t}\n\n\tprivate async _rpc(method: string, params: Record<string, unknown>): Promise<any> {\n\t\tconst body = JSON.stringify({ jsonrpc: '2.0', id: Date.now(), method, params });\n\t\tconst resp = await fetch(this._endpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: this._headers(),\n\t\t\tbody,\n\t\t});\n\t\tif (!resp.ok) {\n\t\t\tconst text = await resp.text().catch(() => '');\n\t\t\tthrow new Error(`HTTP ${resp.status}: ${text.slice(0, 400)}`);\n\t\t}\n\t\treturn resp.json();\n\t}\n\n\tprivate async _call(tool: string, args?: Record<string, unknown>): Promise<any> {\n\t\tconst body = await this._rpc('tools/call', { name: tool, arguments: args ?? {} });\n\t\tif (body.error) throw new Error(`${tool} \u2192 ${JSON.stringify(body.error).slice(0, 400)}`);\n\t\tconst result = body.result ?? {};\n\t\tconst content = result.content;\n\t\tif (Array.isArray(content)) {\n\t\t\tconst texts = content.filter((c: any) => c.type === 'text').map((c: any) => String(c.text ?? ''));\n\t\t\tconst joined = texts.join('\\n');\n\t\t\ttry { return JSON.parse(joined); } catch { return joined; }\n\t\t}\n\t\tif (result.structuredContent !== undefined) return result.structuredContent;\n\t\treturn result;\n\t}\n\n\t// \u2500\u2500 domain methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\tasync listContracts(): Promise<any> {\n\t\treturn this._call('list-contracts');\n\t}\n\n\tasync members(contractId: number): Promise<any> {\n\t\treturn this._call('contract-members', { contract_id: contractId });\n\t}\n\n\tasync tasks(contractId: number): Promise<any> {\n\t\treturn this._call('contract-tasks', { contract_id: contractId });\n\t}\n\n\tasync myEvents(): Promise<any> {\n\t\treturn this._call('get-my-events');\n\t}\n\n\tasync task(eventId: number): Promise<any> {\n\t\treturn this._call('get-event', { event_id: eventId });\n\t}\n\n\tasync create(contractId: number, opts: CreateOptions): Promise<any> {\n\t\tconst args = cleanArgs({\n\t\t\tcontract_id: contractId,\n\t\t\tlabel: opts.label,\n\t\t\ttype_id: opts.type,\n\t\t\tstatus_id: opts.status,\n\t\t\tdescription: opts.description,\n\t\t\tbenefitable: opts.benefitable ? parseBenefitable(opts.benefitable) : undefined,\n\t\t});\n\t\tconst users: ParticipantSpec[] = [];\n\t\tconst rev = parseParticipant(opts.reviewer, ROLE_REVIEWER);\n\t\tif (rev) users.push(rev);\n\t\tconst qa = parseParticipant(opts.qa, ROLE_QA);\n\t\tif (qa) users.push(qa);\n\t\tif (users.length) (args as any).users = users;\n\t\treturn this._call('create-contract-event', args);\n\t}\n\n\tasync propose(eventId: number, opts: ProposeOptions): Promise<any> {\n\t\treturn this._call('propose-correction', cleanArgs({\n\t\t\tevent_id: eventId,\n\t\t\tstatus_id: opts.status,\n\t\t\tlabel: opts.label,\n\t\t\tdescription: opts.description,\n\t\t\tbenefitable: opts.benefitable ? parseBenefitable(opts.benefitable) : undefined,\n\t\t}));\n\t}\n\n\tasync comment(eventId: number, opts?: CommentOptions): Promise<any> {\n\t\treturn this._call('comment', cleanArgs({\n\t\t\tevent_id: eventId,\n\t\t\tlabel: opts?.label,\n\t\t\tdescription: opts?.description,\n\t\t}));\n\t}\n\n\tasync progress(eventId: number, opts: ProgressOptions): Promise<any> {\n\t\tlet statusResult: any = null;\n\t\tif (opts.status != null) {\n\t\t\tstatusResult = await this.propose(eventId, { status: opts.status });\n\t\t}\n\t\tconst commentResult = await this.comment(eventId, { label: deriveLabel(opts.desc), description: opts.desc });\n\t\treturn { status_correction: statusResult, comment: commentResult };\n\t}\n\n\tasync callHuman(eventId: number, kind: 'input' | 'review' | 'stuck', desc: string): Promise<any> {\n\t\tif (!['input', 'review', 'stuck'].includes(kind)) throw new Error(`kind must be input|review|stuck, got ${kind}`);\n\t\treturn this._call('call-human', { event_id: eventId, kind, desc });\n\t}\n\n\t/** GET /agent/polling. Returns [] on 429. */\n\tasync poll(): Promise<any[]> {\n\t\tconst resp = await fetch(`${this._apiBase}/agent/polling`, {\n\t\t\theaders: { Accept: 'application/json', Authorization: `Bearer ${this._token}` },\n\t\t});\n\t\tif (resp.status === 429) return [];\n\t\tif (!resp.ok) {\n\t\t\tconst text = await resp.text().catch(() => '');\n\t\t\tthrow new Error(`poll HTTP ${resp.status}: ${text.slice(0, 300)}`);\n\t\t}\n\t\tconst body = (await resp.json()) as Record<string, unknown>;\n\t\tif (Array.isArray(body)) return body;\n\t\tif (body && typeof body === 'object') {\n\t\t\tfor (const k of ['notifications', 'data', 'items']) {\n\t\t\t\tif (Array.isArray(body[k])) return body[k] as any[];\n\t\t\t}\n\t\t}\n\t\treturn [];\n\t}\n}\n", "import type {\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n} from 'n8n-workflow';\nimport { ContractClient } from '../../lib/contract-client';\n\nconst STATUS_OPTIONS = [\n\t{ name: '100 \u00B7 Backlog', value: 100 },\n\t{ name: '200 \u00B7 Hand (assigned)', value: 200 },\n\t{ name: '222 \u00B7 Hand done', value: 222 },\n\t{ name: '300 \u00B7 QA', value: 300 },\n\t{ name: '350 \u00B7 QA done', value: 350 },\n\t{ name: '499 \u00B7 Reviewer', value: 499 },\n];\n\n/**\n * Ceki Contract \u2014 operation node for the Ceki contract system (tasks/events).\n * Uses native fetch() \u2014 zero external runtime deps.\n */\nexport class CekiContract implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Ceki Contract',\n\t\tname: 'cekiContract',\n\t\ticon: 'file:ceki.png',\n\t\tgroup: ['transform'],\n\t\tversion: 1,\n\t\tsubtitle: '={{ \"Contract: \" + $operation }}',\n\t\tdescription: 'Work with Ceki contract tasks: list, create, assign, update status, comment, report progress, escalate to a human, and poll',\n\t\tdefaults: { name: 'Ceki Contract' },\n\t\tinputs: ['main'],\n\t\toutputs: ['main'],\n\t\tcredentials: [{ name: 'cekiApi', required: true }],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Operation',\n\t\t\t\tname: 'operation',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'myEvents',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'List My Contracts', value: 'listContracts' },\n\t\t\t\t\t{ name: 'List Tasks in Contract', value: 'listTasks' },\n\t\t\t\t\t{ name: 'Get Task', value: 'getTask' },\n\t\t\t\t\t{ name: 'My Assigned Events', value: 'myEvents' },\n\t\t\t\t\t{ name: 'Create Task', value: 'createTask' },\n\t\t\t\t\t{ name: 'Assign Executor', value: 'assign' },\n\t\t\t\t\t{ name: 'Update Status', value: 'setStatus' },\n\t\t\t\t\t{ name: 'Comment', value: 'comment' },\n\t\t\t\t\t{ name: 'Progress Report', value: 'progress' },\n\t\t\t\t\t{ name: 'Call Human', value: 'callHuman' },\n\t\t\t\t\t{ name: 'Poll Notifications', value: 'poll' },\n\t\t\t\t],\n\t\t\t},\n\t\t\t// --- contractId / eventId ---\n\t\t\t{\n\t\t\t\tdisplayName: 'Contract ID',\n\t\t\t\tname: 'contractId',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdescription: 'ceki contract id',\n\t\t\t\tdisplayOptions: { show: { operation: ['listTasks', 'createTask'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Event ID',\n\t\t\t\tname: 'eventId',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdescription: 'Task / event id (KalEvent)',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: { operation: ['getTask', 'assign', 'setStatus', 'comment', 'progress', 'callHuman'] },\n\t\t\t\t},\n\t\t\t},\n\t\t\t// --- createTask fields ---\n\t\t\t{\n\t\t\t\tdisplayName: 'Label',\n\t\t\t\tname: 'label',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['createTask'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Description',\n\t\t\t\tname: 'description',\n\t\t\t\ttype: 'string',\n\t\t\t\ttypeOptions: { rows: 4 },\n\t\t\t\tdefault: '',\n\t\t\t\tdisplayOptions: { show: { operation: ['createTask', 'comment'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Executor (benefitable)',\n\t\t\t\tname: 'benefitableType',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'agent',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Agent', value: 'agent' },\n\t\t\t\t\t{ name: 'User (human)', value: 'user' },\n\t\t\t\t],\n\t\t\t\tdisplayOptions: { show: { operation: ['createTask', 'assign'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Executor ID',\n\t\t\t\tname: 'benefitableValue',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdescription: 'Agent ID or user ID of the executor',\n\t\t\t\tdisplayOptions: { show: { operation: ['createTask', 'assign'] } },\n\t\t\t},\n\t\t\t// --- status ---\n\t\t\t{\n\t\t\t\tdisplayName: 'Status',\n\t\t\t\tname: 'status',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: STATUS_OPTIONS,\n\t\t\t\tdefault: 200,\n\t\t\t\tdisplayOptions: { show: { operation: ['createTask', 'setStatus', 'progress'] } },\n\t\t\t},\n\t\t\t// --- progress desc ---\n\t\t\t{\n\t\t\t\tdisplayName: 'Progress Description',\n\t\t\t\tname: 'progressDesc',\n\t\t\t\ttype: 'string',\n\t\t\t\ttypeOptions: { rows: 4 },\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'Body of the progress comment (does not overwrite the task spec)',\n\t\t\t\tdisplayOptions: { show: { operation: ['progress'] } },\n\t\t\t},\n\t\t\t// --- call human (escalate) ---\n\t\t\t{\n\t\t\t\tdisplayName: 'Call Kind',\n\t\t\t\tname: 'callKind',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'review',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Input (need clarification)', value: 'input' },\n\t\t\t\t\t{ name: 'Review (done, take a look)', value: 'review' },\n\t\t\t\t\t{ name: 'Stuck (blocked)', value: 'stuck' },\n\t\t\t\t],\n\t\t\t\tdescription: 'Type of escalation to a human (the call-human action)',\n\t\t\t\tdisplayOptions: { show: { operation: ['callHuman'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Message',\n\t\t\t\tname: 'callDesc',\n\t\t\t\ttype: 'string',\n\t\t\t\ttypeOptions: { rows: 4 },\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'What to tell the human \u2014 context, question, or what was done',\n\t\t\t\tdisplayOptions: { show: { operation: ['callHuman'] } },\n\t\t\t},\n\t\t],\n\t};\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst items = this.getInputData();\n\t\tconst out: INodeExecutionData[] = [];\n\t\tconst creds = await this.getCredentials('cekiApi');\n\t\tconst token = creds.token as string;\n\t\tconst client = new ContractClient(token);\n\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\tconst op = this.getNodeParameter('operation', i) as string;\n\t\t\tlet result: unknown;\n\n\t\t\tswitch (op) {\n\t\t\t\tcase 'listContracts':\n\t\t\t\t\tresult = await client.listContracts();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'listTasks': {\n\t\t\t\t\tconst contractId = this.getNodeParameter('contractId', i) as number;\n\t\t\t\t\tresult = await client.tasks(contractId);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'getTask': {\n\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\tresult = await client.task(eventId);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'myEvents':\n\t\t\t\t\tresult = await client.myEvents();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'createTask': {\n\t\t\t\t\tconst contractId = this.getNodeParameter('contractId', i) as number;\n\t\t\t\t\tconst label = this.getNodeParameter('label', i) as string;\n\t\t\t\t\tconst description = (this.getNodeParameter('description', i) as string) || '';\n\t\t\t\t\tconst status = this.getNodeParameter('status', i) as number;\n\t\t\t\t\tconst bType = this.getNodeParameter('benefitableType', i) as string;\n\t\t\t\t\tconst bValue = this.getNodeParameter('benefitableValue', i) as number;\n\t\t\t\t\tresult = await client.create(contractId, {\n\t\t\t\t\t\tlabel,\n\t\t\t\t\t\tdescription: description || undefined,\n\t\t\t\t\t\tstatus,\n\t\t\t\t\t\tbenefitable: bValue ? `${bType}:${bValue}` : undefined,\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'assign': {\n\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\tconst bType = this.getNodeParameter('benefitableType', i) as string;\n\t\t\t\t\tconst bValue = this.getNodeParameter('benefitableValue', i) as number;\n\t\t\t\t\tif (!bValue) throw new Error('Executor ID is required for Assign');\n\t\t\t\t\tresult = await client.propose(eventId, { benefitable: `${bType}:${bValue}` });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'setStatus': {\n\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\tconst status = this.getNodeParameter('status', i) as number;\n\t\t\t\t\tresult = await client.propose(eventId, { status });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'comment': {\n\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\tconst description = (this.getNodeParameter('description', i) as string) || '';\n\t\t\t\t\tif (!description) throw new Error('Comment text is required');\n\t\t\t\t\tresult = await client.comment(eventId, { description });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'progress': {\n\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\tconst status = this.getNodeParameter('status', i) as number;\n\t\t\t\t\tconst desc = this.getNodeParameter('progressDesc', i) as string;\n\t\t\t\t\tresult = await client.progress(eventId, { status, desc });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'callHuman': {\n\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\tconst kind = this.getNodeParameter('callKind', i) as 'input' | 'review' | 'stuck';\n\t\t\t\t\tconst desc = this.getNodeParameter('callDesc', i) as string;\n\t\t\t\t\tif (!desc) throw new Error('Message is required for Call Human');\n\t\t\t\t\tresult = await client.callHuman(eventId, kind, desc);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'poll':\n\t\t\t\t\tresult = await client.poll();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Unknown operation: ${op}`);\n\t\t\t}\n\n\t\t\tout.push({ json: { op, result: result as any } });\n\t\t}\n\t\treturn [out];\n\t}\n}\n", "import type { IExecuteFunctions, INodeType, INodeTypeDescription, INodeExecutionData } from 'n8n-workflow';\nimport { CekiClient } from '../../../lib/ceki-client';\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => {\n\tAbortSignal.timeout(ms).addEventListener('abort', () => resolve(), { once: true });\n});\n\nasync function waitForSelector(browser: any, selector: string, timeoutMs: number, intervalMs = 500) {\n\tconst expr = `!!document.querySelector(${JSON.stringify(selector)})`;\n\tconst deadline = Date.now() + timeoutMs;\n\tlet lastErr: unknown = null;\n\twhile (Date.now() < deadline) {\n\t\ttry {\n\t\t\tconst res = await browser.send('Runtime.evaluate', { expression: expr, returnByValue: true }) as any;\n\t\t\tif (res?.result?.value === true) return true;\n\t\t} catch (e) {\n\t\t\tlastErr = e;\n\t\t}\n\t\tawait sleep(intervalMs);\n\t}\n\tthrow new Error(\n\t\t`waitForSelector(\"${selector}\") timed out after ${timeoutMs}ms${lastErr ? `: ${(lastErr as Error).message}` : ''}`,\n\t);\n}\n\nasync function extractHtml(browser: any, selector: string): Promise<string> {\n\tconst expr =\n\t\tselector.trim() === '' || selector === 'body'\n\t\t\t? `document.body ? document.body.outerHTML : ''`\n\t\t\t: `(function(){ var el = document.querySelector(${JSON.stringify(selector)}); return el ? el.outerHTML : ''; })()`;\n\tconst res = await browser.send('Runtime.evaluate', { expression: expr, returnByValue: true }) as any;\n\treturn (res?.result?.value as string) ?? '';\n}\n\n/**\n * Recipe: Captcha-protected Scrape.\n * Rent a human browser \u2192 open a URL \u2192 (optional) wait for a selector \u2192\n * snapshot/HTML \u2192 release.\n *\n * The real human fingerprint bypasses anti-bot protection.\n */\nexport class CekiCaptchaScrape implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Browser Ceki: Captcha-protected Scrape',\n\t\tname: 'cekiCaptchaScrape',\n\t\tdescription: 'Rent a human browser, wait, screenshot/HTML, release',\n\t\ticon: 'file:ceki.png',\n\t\tgroup: ['transform'],\n\t\tversion: 1,\n\t\tsubtitle: '=rent in {{ $geo }} \u2192 snapshot',\n\t\tdefaults: { name: 'Browser Ceki: Captcha-protected Scrape' },\n\t\tinputs: ['main'],\n\t\toutputs: ['main'],\n\t\tcredentials: [{ name: 'cekiApi', required: true }],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'https://example.com',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'Page protected by anti-bot / captcha',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Geo',\n\t\t\t\tname: 'geo',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'RU',\n\t\t\t\tplaceholder: 'RU, EE, US\u2026',\n\t\t\t},\n\t\t\t{ displayName: 'Max $/min', name: 'maxPrice', type: 'number', typeOptions: { numberPrecision: 4 }, default: 0.02 },\n\t\t\t{\n\t\t\t\tdisplayName: 'Wait for Selector',\n\t\t\t\tname: 'waitSelector',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'CSS selector (optional)',\n\t\t\t\tdescription: 'Wait until this selector appears in the DOM',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Wait Timeout (ms)',\n\t\t\t\tname: 'waitTimeout',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 30000,\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Extract HTML',\n\t\t\t\tname: 'extractHtml',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'HTML Selector',\n\t\t\t\tname: 'htmlSelector',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'body',\n\t\t\t\tplaceholder: 'CSS selector or \"body\"',\n\t\t\t\tdescription: 'outerHTML of this selector is returned as `html`',\n\t\t\t\tdisplayOptions: { show: { extractHtml: [true] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Full Page Screenshot',\n\t\t\t\tname: 'fullPage',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t],\n\t};\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst items = this.getInputData();\n\t\tconst out: INodeExecutionData[] = [];\n\t\tconst creds = await this.getCredentials('cekiApi');\n\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\tconst url = this.getNodeParameter('url', i) as string;\n\t\t\tconst geo = this.getNodeParameter('geo', i) as string;\n\t\t\tconst maxPrice = this.getNodeParameter('maxPrice', i) as number;\n\t\t\tconst waitSelector = (this.getNodeParameter('waitSelector', i) as string) || '';\n\t\t\tconst waitTimeout = this.getNodeParameter('waitTimeout', i) as number;\n\t\t\tconst extractHtmlFlag = this.getNodeParameter('extractHtml', i) as boolean;\n\t\t\tconst htmlSelector = (this.getNodeParameter('htmlSelector', i) as string) || 'body';\n\t\t\tconst fullPage = this.getNodeParameter('fullPage', i) as boolean;\n\n\t\t\tconst client = new CekiClient(creds.token as string);\n\t\t\tawait client.connect();\n\t\t\tlet browser: any;\n\t\t\tlet scheduleId = 0;\n\t\t\ttry {\n\t\t\t\tconst list = await client.search({ geo: geo || undefined, max_price_per_min: maxPrice });\n\t\t\t\tif (!list.length) throw new Error(`No browsers in geo ${geo || '*'}`);\n\t\t\t\tscheduleId = list[0].schedule_id;\n\t\t\t\tbrowser = await client.rent(scheduleId);\n\n\t\t\t\tawait browser.navigate(url);\n\n\t\t\t\tif (waitSelector) {\n\t\t\t\t\tawait waitForSelector(browser, waitSelector, waitTimeout);\n\t\t\t\t}\n\n\t\t\t\tconst shot = await browser.screenshot({ format: 'base64', fullPage }) as any;\n\t\t\t\tconst data = shot.data ?? (shot instanceof Buffer ? shot.toString('base64') : '');\n\t\t\t\tconst binary = await this.helpers.prepareBinaryData(\n\t\t\t\t\tBuffer.from(data, 'base64'),\n\t\t\t\t\t'captcha-scrape.png',\n\t\t\t\t\t'image/png',\n\t\t\t\t);\n\n\t\t\t\tconst json: Record<string, unknown> = {\n\t\t\t\t\turl,\n\t\t\t\t\tgeo,\n\t\t\t\t\tschedule_id: scheduleId,\n\t\t\t\t};\n\t\t\t\tif (extractHtmlFlag) {\n\t\t\t\t\tjson.html = await extractHtml(browser, htmlSelector);\n\t\t\t\t}\n\n\t\t\t\tout.push({ json: json as any, binary: { data: binary } });\n\t\t\t} finally {\n\t\t\t\tif (browser) {\n\t\t\t\t\ttry { await browser.close(); } catch { /* ignore */ }\n\t\t\t\t}\n\t\t\t\ttry { await client.close(); } catch { /* ignore */ }\n\t\t\t}\n\t\t}\n\t\treturn [out];\n\t}\n}\n", "import type { IExecuteFunctions, INodeType, INodeTypeDescription, INodeExecutionData } from 'n8n-workflow';\nimport { CekiClient } from '../../../lib/ceki-client';\n\n/**\n * Recipe: Screenshot in Geo.\n * One call \u2014 rent a browser in the requested geo, open a URL, take a screenshot, release.\n */\nexport class CekiScreenshotGeo implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Browser Ceki: Screenshot in Geo',\n\t\tname: 'cekiScreenshotGeo',\n\t\tdescription: 'Rent a browser in a given geo, screenshot a page, release',\n\t\ticon: 'file:ceki.png',\n\t\tgroup: ['transform'],\n\t\tversion: 1,\n\t\tsubtitle: '=rent in {{ $geo }} \u2192 screenshot \u2192 release',\n\t\tdefaults: { name: 'Browser Ceki: Screenshot in Geo' },\n\t\tinputs: ['main'],\n\t\toutputs: ['main'],\n\t\tcredentials: [{ name: 'cekiApi', required: true }],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'https://ifconfig.me',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{ displayName: 'Geo', name: 'geo', type: 'string', default: 'RU', placeholder: 'RU, EE, US\u2026' },\n\t\t\t{ displayName: 'Full page', name: 'fullPage', type: 'boolean', default: false },\n\t\t\t{ displayName: 'Max $/min', name: 'maxPrice', type: 'number', default: 0.02 },\n\t\t],\n\t};\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst items = this.getInputData();\n\t\tconst out: INodeExecutionData[] = [];\n\t\tconst creds = await this.getCredentials('cekiApi');\n\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\tconst url = this.getNodeParameter('url', i) as string;\n\t\t\tconst geo = this.getNodeParameter('geo', i) as string;\n\t\t\tconst fullPage = this.getNodeParameter('fullPage', i) as boolean;\n\t\t\tconst maxPrice = this.getNodeParameter('maxPrice', i) as number;\n\n\t\t\tconst client = new CekiClient(creds.token as string);\n\t\t\tawait client.connect();\n\t\t\tlet browser: any;\n\t\t\ttry {\n\t\t\t\tconst list = await client.search({ geo, max_price_per_min: maxPrice });\n\t\t\t\tif (!list.length) throw new Error(`No browsers in geo ${geo}`);\n\t\t\t\tbrowser = await client.rent(list[0].schedule_id);\n\t\t\t\tawait browser.navigate(url);\n\t\t\t\tconst shot = await browser.screenshot({ format: 'base64', fullPage }) as any;\n\t\t\t\tconst binary = await this.helpers.prepareBinaryData(\n\t\t\t\t\tBuffer.from(shot.data, 'base64'),\n\t\t\t\t\t'screenshot.png',\n\t\t\t\t\t'image/png',\n\t\t\t\t);\n\t\t\t\tout.push({\n\t\t\t\t\tjson: { url, geo, schedule_id: list[0].schedule_id },\n\t\t\t\t\tbinary: { data: binary },\n\t\t\t\t});\n\t\t\t} finally {\n\t\t\t\tif (browser) { try { await browser.close(); } catch {} }\n\t\t\t\ttry { await client.close(); } catch {}\n\t\t\t}\n\t\t}\n\t\treturn [out];\n\t}\n}\n", "import type {\n\tIAuthenticateGeneric,\n\tICredentialTestRequest,\n\tICredentialType,\n\tINodeProperties,\n} from 'n8n-workflow';\n\n/**\n * Ceki agent token (ag_...). Authorizes every Ceki node.\n * Get it from the Ceki panel \u2192 agent profile \u2192 API key.\n */\nexport class CekiApi implements ICredentialType {\n\tname = 'cekiApi';\n\tdisplayName = 'Ceki API';\n\tdocumentationUrl = 'https://browser.ceki.me/docs#api-key';\n\tproperties: INodeProperties[] = [\n\t\t{\n\t\t\tdisplayName: 'API Key',\n\t\t\tname: 'token',\n\t\t\ttype: 'string',\n\t\t\ttypeOptions: { password: true },\n\t\t\tdefault: '',\n\t\t\tdescription:\n\t\t\t\t'Agent token (ag_...). [Get your API key \u2192](https://browser.ceki.me/docs#api-key)',\n\t\t\trequired: true,\n\t\t},\n\t];\n\n\tauthenticate: IAuthenticateGeneric = {\n\t\ttype: 'generic',\n\t\tproperties: {\n\t\t\theaders: {\n\t\t\t\tAuthorization: '=Bearer {{$credentials?.token}}',\n\t\t\t},\n\t\t},\n\t};\n\n\ttest: ICredentialTestRequest = {\n\t\trequest: {\n\t\t\tbaseURL: 'https://api.ceki.me',\n\t\t\turl: '/api/browsers/search',\n\t\t\tmethod: 'GET',\n\t\t},\n\t};\n}\n"],
5
- "mappings": "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",
6
- "names": ["x", "y", "sid", "sessionId", "x", "y", "sleep"]
3
+ "sources": ["../index.ts", "../nodes/BrowserCeki/BrowserCeki.node.ts", "../lib/ceki-client.ts", "../lib/contract-client.ts", "../credentials/CekiApi.credentials.ts"],
4
+ "sourcesContent": ["import { BrowserCeki } from './nodes/BrowserCeki/BrowserCeki.node';\nimport { CekiApi } from './credentials/CekiApi.credentials';\n\nexport const nodes = [\n\tBrowserCeki,\n];\n\nexport const credentials = [\n\tCekiApi,\n];\n", "import type {\n\tIExecuteFunctions,\n\tINode,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tJsonObject,\n} from 'n8n-workflow';\nimport {\n\tNodeApiError,\n\tNodeOperationError,\n\tNodeConnectionTypes,\n} from 'n8n-workflow';\nimport { CekiClient } from '../../lib/ceki-client';\nimport { ContractClient } from '../../lib/contract-client';\n\n\nasync function waitForSelector(node: INode, browser: any, selector: string, timeoutMs: number, intervalMs = 500) {\n\tconst expr = `!!document.querySelector(${JSON.stringify(selector)})`;\n\tconst deadline = Date.now() + timeoutMs;\n\tlet lastErr: unknown = null;\n\twhile (Date.now() < deadline) {\n\t\ttry {\n\t\t\tconst res = await browser.send('Runtime.evaluate', { expression: expr, returnByValue: true }) as any;\n\t\t\tif (res?.result?.value === true) return true;\n\t\t} catch (e) {\n\t\t\tlastErr = e;\n\t\t}\n\t\tawait sleep(intervalMs);\n\t}\n\tthrow new NodeOperationError(\n\t\tnode,\n\t\t`waitForSelector(\"${selector}\") timed out after ${timeoutMs}ms${lastErr ? ': ' + (lastErr as Error).message : ''}`,\n\t);\n}\n\nasync function extractHtml(browser: any, selector: string): Promise<string> {\n\tconst expr =\n\t\tselector.trim() === '' || selector === 'body'\n\t\t\t? 'document.body ? document.body.outerHTML : \\'\\''\n\t\t\t: '(function(){ var el = document.querySelector(' + JSON.stringify(selector) + '); return el ? el.outerHTML : \\'\\'; })()';\n\tconst res = await browser.send('Runtime.evaluate', { expression: expr, returnByValue: true }) as any;\n\treturn (res?.result?.value as string) ?? '';\n}\nconst sleep = (ms: number) => new Promise<void>((resolve) => {\n\tAbortSignal.timeout(ms).addEventListener('abort', () => resolve(), { once: true });\n});\n\n/**\n * Browser Ceki \u2014 one node, many operations.\n * Uses native WebSocket (not the ws library) \u2014 zero external runtime deps.\n *\n * Resume flow:\n * 1. Rent \u2192 browser session created, client disconnects (session in grace).\n * 2. Navigate/Screenshot/etc \u2192 new client, connect, resume(sessionId) \u2192 server\n * responds with resume_ok, do the op, disconnect.\n * 3. Close \u2192 same, sends Ceki.close, client.close().\n *\n * This works because the server supports session resume across different\n * WebSocket connections (same auth token). Each n8n node independently\n * creates a fresh WS connection and resumes the session by ID.\n */\nexport class BrowserCeki implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Browser Ceki',\n\t\tname: 'browserCeki',\n\t\ticon: {\n\t\tlight: 'file:ceki-light.svg',\n\t\tdark: 'file:ceki-dark.svg',\n\t},\n\t\tgroup: ['transform'],\n\t\tversion: 1,\n\t\tusableAsTool: true,\n\t\tsubtitle: '={{ \"Ceki: \" + $parameter.operation }}',\n\t\tdescription: 'Rent a real human browser and control it: rent, navigate, click, type, screenshot, solve captchas, and more',\n\t\tdefaults: { name: 'Browser Ceki' },\n\t\tinputs: [NodeConnectionTypes.Main],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [{ name: 'cekiApi', required: true }],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Operation',\n\t\t\t\tname: 'operation',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'search',\n\t\t\t\tnoDataExpression: true,\n\t\t\t\toptions: [\n\t\t\t\t\t// Browser operations\n\t\t\t\t\t{ name: 'Captcha-Protected Scrape', value: 'captchaScrape' },\n\t\t\t\t\t{ name: 'Click', value: 'click' },\n\t\t\t\t\t{ name: 'Close', value: 'close' },\n\t\t\t\t\t// Contract operations\n\t\t\t\t\t{ name: 'Contract: Assign Executor', value: 'contract_assign' },\n\t\t\t\t\t{ name: 'Contract: Call Human', value: 'contract_callHuman' },\n\t\t\t\t\t{ name: 'Contract: Comment', value: 'contract_comment' },\n\t\t\t\t\t{ name: 'Contract: Create Task', value: 'contract_create' },\n\t\t\t\t\t{ name: 'Contract: Get Task', value: 'contract_get' },\n\t\t\t\t\t{ name: 'Contract: List My Contracts', value: 'contract_list' },\n\t\t\t\t\t{ name: 'Contract: List Tasks in Contract', value: 'contract_tasks' },\n\t\t\t\t\t{ name: 'Contract: My Assigned Events', value: 'contract_myEvents' },\n\t\t\t\t\t{ name: 'Contract: Poll Notifications', value: 'contract_poll' },\n\t\t\t\t\t{ name: 'Contract: Progress Report', value: 'contract_progress' },\n\t\t\t\t\t{ name: 'Contract: Update Status', value: 'contract_setStatus' },\n\t\t\t\t\t{ name: 'Full: Rent \u2192 Navigate \u2192 Screenshot', value: 'full' },\n\t\t\t\t\t{ name: 'My Sessions', value: 'my_sessions' },\n\t\t\t\t\t{ name: 'Navigate', value: 'navigate' },\n\t\t\t\t\t{ name: 'Rent', value: 'rent' },\n\t\t\t\t\t{ name: 'Screenshot', value: 'screenshot' },\n\t\t\t\t\t{ name: 'Screenshot in Geo', value: 'screenshotGeo' },\n\t\t\t\t\t{ name: 'Scroll', value: 'scroll' },\n\t\t\t\t\t{ name: 'Search', value: 'search' },\n\t\t\t\t\t{ name: 'Snapshot', value: 'snapshot' },\n\t\t\t\t\t{ name: 'Stop Session', value: 'stop_session' },\n\t\t\t\t\t{ name: 'Type', value: 'type' },\n\t\t\t\t\t{ name: 'Upload', value: 'upload' },\n\t\t\t\t\t{ name: 'Wait', value: 'wait' },\n\t\t\t\t\t{ name: 'Wait for Selector', value: 'waitForSelector' },\n\t\t\t\t]\n\t\t\t},\n\t\t\t// === Rent: rental parameters ===\n\t\t\t{\n\t\t\t\tdisplayName: 'Schedule ID',\n\t\t\t\tname: 'scheduleId',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdescription: '0 \u2014 search by the filters below',\n\t\t\t\tdisplayOptions: { show: { operation: ['rent'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Geo',\n\t\t\t\tname: 'geo',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'RU, EE, US\u2026',\n\t\t\t\tdisplayOptions: { show: { operation: ['search', 'captchaScrape', 'screenshotGeo'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Max $/Min',\n\t\t\t\tname: 'maxPrice',\n\t\t\t\ttype: 'number',\n\t\t\t\ttypeOptions: { numberPrecision: 4 },\n\t\t\t\tdefault: 0.02,\n\t\t\t\tdisplayOptions: { show: { operation: ['search', 'captchaScrape', 'screenshotGeo'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Min Rating',\n\t\t\t\tname: 'minRating',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdisplayOptions: { show: { operation: ['search', 'captchaScrape', 'screenshotGeo'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Profile Mode',\n\t\t\t\tname: 'mode',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'incognito',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Incognito', value: 'incognito' },\n\t\t\t\t\t{ name: 'Main', value: 'main' },\n\t\t\t\t],\n\t\t\t\tdisplayOptions: { show: { operation: ['rent', 'full'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'https://example.com',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['navigate', 'full'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Demo Mode (No Browser Needed)',\n\t\t\t\tname: 'demoMode',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdescription: 'Whether to skip actual browser rent and generate demo output',\n\t\t\t\tdisplayOptions: { show: { operation: ['full'] } },\n\t\t\t},\n\t\t\t// === Captcha-protected Scrape params ===\n\t\t\t{\n\t\t\t\tdisplayName: 'Captcha URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'https://example.com',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'Page protected by anti-bot / captcha',\n\t\t\t\tdisplayOptions: { show: { operation: ['captchaScrape'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Geo',\n\t\t\t\tname: 'geo',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'RU',\n\t\t\t\tplaceholder: 'RU, EE, US\\u2026',\n\t\t\t\tdisplayOptions: { show: { operation: ['captchaScrape'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Max $/Min',\n\t\t\t\tname: 'maxPrice',\n\t\t\t\ttype: 'number',\n\t\t\t\ttypeOptions: { numberPrecision: 4 },\n\t\t\t\tdefault: 0.02,\n\t\t\t\tdisplayOptions: { show: { operation: ['captchaScrape'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Wait for Selector',\n\t\t\t\tname: 'waitSelector',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'CSS selector (optional)',\n\t\t\t\tdescription: 'Wait until this selector appears in the DOM',\n\t\t\t\tdisplayOptions: { show: { operation: ['captchaScrape'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Wait Timeout (Ms)',\n\t\t\t\tname: 'waitTimeout',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 30000,\n\t\t\t\tdisplayOptions: { show: { operation: ['captchaScrape'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Extract HTML',\n\t\t\t\tname: 'extractHtml',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['captchaScrape'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'HTML Selector',\n\t\t\t\tname: 'htmlSelector',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'body',\n\t\t\t\tplaceholder: 'CSS selector or \"body\"',\n\t\t\t\tdescription: 'OuterHTML of this selector is returned as html',\n\t\t\t\tdisplayOptions: { show: { operation: ['captchaScrape'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Full Page Screenshot',\n\t\t\t\tname: 'fullPage',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t\tdisplayOptions: { show: { operation: ['captchaScrape'] } },\n\t\t\t},\n\t\t\t// === Screenshot in Geo params ===\n\t\t\t{\n\t\t\t\tdisplayName: 'Geo URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'https://ifconfig.me',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['screenshotGeo'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Geo',\n\t\t\t\tname: 'geo',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'RU',\n\t\t\t\tplaceholder: 'RU, EE, US\\u2026',\n\t\t\t\tdisplayOptions: { show: { operation: ['screenshotGeo'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Full Page Screenshot',\n\t\t\t\tname: 'fullPage',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t\tdisplayOptions: { show: { operation: ['screenshotGeo'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Max $/Min',\n\t\t\t\tname: 'maxPrice',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0.02,\n\t\t\t\tdisplayOptions: { show: { operation: ['screenshotGeo'] } },\n\t\t\t},\n\t\t\t// === Contract params ===\n\t\t\t{\n\t\t\t\tdisplayName: 'Contract ID',\n\t\t\t\tname: 'contractId',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdescription: 'Ceki contract ID',\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_tasks', 'contract_create'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Event ID',\n\t\t\t\tname: 'eventId',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdescription: 'Task / event ID (KalEvent)',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: { operation: ['contract_get', 'contract_assign', 'contract_setStatus', 'contract_comment', 'contract_progress', 'contract_callHuman'] },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Label',\n\t\t\t\tname: 'label',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_create'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Description',\n\t\t\t\tname: 'description',\n\t\t\t\ttype: 'string',\n\t\t\t\ttypeOptions: { rows: 4 },\n\t\t\t\tdefault: '',\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_create', 'contract_comment'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Executor Type',\n\t\t\t\tname: 'benefitableType',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'agent',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Agent', value: 'agent' },\n\t\t\t\t\t{ name: 'User (Human)', value: 'user' },\n\t\t\t\t],\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_create', 'contract_assign'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Executor ID',\n\t\t\t\tname: 'benefitableValue',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdescription: 'Agent ID or user ID of the executor',\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_create', 'contract_assign'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Status',\n\t\t\t\tname: 'status',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: '100 \\u00b7 Backlog', value: 100 },\n\t\t\t\t\t{ name: '200 \\u00b7 Hand (Assigned)', value: 200 },\n\t\t\t\t\t{ name: '222 \\u00b7 Hand Done', value: 222 },\n\t\t\t\t\t{ name: '300 \\u00b7 QA', value: 300 },\n\t\t\t\t\t{ name: '350 \\u00b7 QA Done', value: 350 },\n\t\t\t\t\t{ name: '499 \\u00b7 Reviewer', value: 499 },\n\t\t\t\t],\n\t\t\t\tdefault: 200,\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_create', 'contract_setStatus', 'contract_progress'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Progress Description',\n\t\t\t\tname: 'progressDesc',\n\t\t\t\ttype: 'string',\n\t\t\t\ttypeOptions: { rows: 4 },\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'Body of the progress comment (does not overwrite the task spec)',\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_progress'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Call Kind',\n\t\t\t\tname: 'callKind',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'review',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Input (Need Clarification)', value: 'input' },\n\t\t\t\t\t{ name: 'Review (Done, Take a Look)', value: 'review' },\n\t\t\t\t\t{ name: 'Stuck (Blocked)', value: 'stuck' },\n\t\t\t\t],\n\t\t\t\tdescription: 'Type of escalation to a human (the call-human action)',\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_callHuman'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Message',\n\t\t\t\tname: 'callDesc',\n\t\t\t\ttype: 'string',\n\t\t\t\ttypeOptions: { rows: 4 },\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdescription: 'What to tell the human \\u2014 context, question, or what was done',\n\t\t\t\tdisplayOptions: { show: { operation: ['contract_callHuman'] } },\n\t\t\t},\n\t\t\t// === Operations: session_id ===\n\n\n\t\t\t{\n\t\t\t\tdisplayName: 'Session ID',\n\t\t\t\tname: 'sessionId',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tdescription: 'From the Rent operation',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\toperation: ['navigate', 'click', 'type', 'scroll', 'screenshot', 'snapshot', 'wait', 'waitForSelector', 'upload', 'close', 'stop_session'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'URL',\n\t\t\t\tname: 'url',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['navigate'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'X',\n\t\t\t\tname: 'x',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdisplayOptions: { show: { operation: ['click'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Y',\n\t\t\t\tname: 'y',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 0,\n\t\t\t\tdisplayOptions: { show: { operation: ['click'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Text',\n\t\t\t\tname: 'text',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tdisplayOptions: { show: { operation: ['type'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Delta Y',\n\t\t\t\tname: 'deltaY',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: -300,\n\t\t\t\tdisplayOptions: { show: { operation: ['scroll'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Format',\n\t\t\t\tname: 'format',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'png',\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Base64', value: 'base64' },\n\t\t\t\t\t{ name: 'PNG (Binary)', value: 'png' },\n\t\t\t\t],\n\t\t\t\tdisplayOptions: { show: { operation: ['screenshot'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Full Page',\n\t\t\t\tname: 'fullPage',\n\t\t\t\ttype: 'boolean',\n\t\t\t\tdefault: false,\n\t\t\t\tdisplayOptions: { show: { operation: ['screenshot'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Milliseconds',\n\t\t\t\tname: 'ms',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 1000,\n\t\t\t\ttypeOptions: { minValue: 0 },\n\t\t\t\tdescription: 'Fixed delay on the active session',\n\t\t\t\tdisplayOptions: { show: { operation: ['wait', 'full'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'CSS Selector',\n\t\t\t\tname: 'waitSelector',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tplaceholder: 'e.g. .results, #content, table tr',\n\t\t\t\tdisplayOptions: { show: { operation: ['waitForSelector'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Timeout (Ms)',\n\t\t\t\tname: 'waitTimeout',\n\t\t\t\ttype: 'number',\n\t\t\t\tdefault: 30000,\n\t\t\t\tdescription: 'Waits until the selector appears in the DOM',\n\t\t\t\tdisplayOptions: { show: { operation: ['waitForSelector'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'CSS Selector',\n\t\t\t\tname: 'selector',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: { show: { operation: ['upload'] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Binary Property',\n\t\t\t\tname: 'binaryPropertyName',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'data',\n\t\t\t\tdisplayOptions: { show: { operation: ['upload'] } },\n\t\t\t},\n\t\t],\n\t};\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tconst items = this.getInputData();\n\t\tconst out: INodeExecutionData[] = [];\n\t\tconst creds = await this.getCredentials('cekiApi');\n\t\tconst token = creds.token as string;\n\t\tconst node = this.getNode();\n\n\t\tconst touchedSessions = new Set<string>();\n\t\tconst _stopSession = async (sid: string): Promise<void> => {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tconst stopWs = new WebSocket('wss://browser.ceki.me/ws/agent', ['bearer.' + token]);\n\t\t\t\tconst _t = AbortSignal.timeout(10000);\n\t\t\t\tconst _done = () => { try { stopWs.close(); } catch { /* best-effort close -- stop */ } resolve(); };\n\t\t\t\t_t.addEventListener('abort', _done, { once: true });\n\t\t\t\tstopWs.onopen = () => { try { stopWs.send(JSON.stringify({ type: 'stop', session_id: sid, reason: 'n8n error' })); } catch { /* ws may already be closing */ } };\n\t\t\t\tstopWs.onmessage = (ev) => { try { const m = JSON.parse(ev.data as string); if (m.type === 'session_ended') { _t.removeEventListener('abort', _done); _done(); } } catch { /* parse best-effort */ } };\n\t\t\t\tstopWs.onerror = _done;\n\t\t\t\tstopWs.onclose = _done;\n\t\t\t});\n\t\t};\n\n\t\tconst resolveSid = async (i: number, client: CekiClient) => {\n\t\t\tconst scheduleId = this.getNodeParameter('scheduleId', i) as number;\n\t\t\tif (scheduleId) return scheduleId;\n\t\t\tconst geo = this.getNodeParameter('geo', i) as string;\n\t\t\tconst maxPrice = this.getNodeParameter('maxPrice', i) as number;\n\t\t\tconst list = await client.search({\n\t\t\t\tgeo: geo || undefined,\n\t\t\t\tmax_price_per_min: maxPrice,\n\t\t\t});\n\t\t\tif (!list.length) throw new NodeOperationError(node, 'No browsers found by filters');\n\t\t\treturn list[0].schedule_id;\n\t\t};\n\n\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\ttry {\n\t\t\t\tconst op = this.getNodeParameter('operation', i) as string;\n\t\t\t\tconst client = new CekiClient(token);\n\t\t\t\tlet browser: any;\n\t\t\t\tlet needFullClose = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait client.connect();\n\n\t\t\t\t\tif (op === 'rent') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst sid = await resolveSid(i, client);\n\t\t\t\t\t\t\tconst mode = this.getNodeParameter('mode', i) as 'main' | 'incognito';\n\t\t\t\t\t\t\tbrowser = await client.rent(sid, { mode });\n\t\t\t\t\t\t\tout.push({\n\t\t\t\t\t\t\t\tjson: { session_id: browser.sessionId, schedule_id: sid, mode },\n\t\t\t\t\t\t\t\tpairedItem: { item: i },\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Rent failed' });\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tawait client.disconnect();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (op === 'search') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst geo = this.getNodeParameter('geo', i) as string;\n\t\t\t\t\t\t\tconst maxPrice = this.getNodeParameter('maxPrice', i) as number;\n\t\t\t\t\t\t\tconst list = await client.search({\n\t\t\t\t\t\t\t\tgeo: geo || undefined,\n\t\t\t\t\t\t\t\tmax_price_per_min: maxPrice,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tout.push({ json: { browsers: list, count: list.length }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Search failed' });\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tawait client.disconnect();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (op === 'my_sessions') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst resp = await fetch(\"https://api.ceki.me/api/agent/sessions\", {\n\t\t\t\t\t\t\t\theaders: { Authorization: `Bearer ${token}` },\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (!resp.ok) throw new NodeApiError(node, undefined as any, { itemIndex: i, message: `HTTP ${resp.status}`, httpCode: `${resp.status}` });\n\t\t\t\t\t\t\tconst body = await resp.json() as any;\n\t\t\t\t\t\t\tconst sessions = body.data ?? [];\n\t\t\t\t\t\t\tout.push({ json: { sessions, count: sessions.length }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'My sessions failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (op === 'stop_session') {\n\t\t\t\t\t\tconst sessionId = this.getNodeParameter(\"sessionId\", i) as string;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\t\t\t\t\tconst ws = new WebSocket(\"wss://browser.ceki.me/ws/agent\", [`bearer.${token}`]);\n\t\t\t\t\t\t\t\tconst t = AbortSignal.timeout(15000);\n\t\t\t\t\t\t\t\tt.addEventListener(\"abort\", () => { try { ws.close(); } catch { /* ws already closed */ } reject(new NodeApiError(node, undefined as any, { itemIndex: i, message: \"Stop session timed out\" })); }, { once: true });\n\t\t\t\t\t\t\t\tws.onopen = () => {\n\t\t\t\t\t\t\t\t\tws.send(JSON.stringify({ type: \"stop\", session_id: sessionId, reason: \"n8n stop_session\" }));\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tws.onmessage = (ev) => {\n\t\t\t\t\t\t\t\t\tconst msg = JSON.parse(ev.data as string);\n\t\t\t\t\t\t\t\t\tif (msg.type === \"session_ended\" || msg.type === \"pong\") {\n\t\t\t\t\t\t\t\t\t\ttry { ws.close(); } catch { /* close best-effort */ }\n\t\t\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tws.onerror = () => { reject(new NodeApiError(node, undefined as any, { itemIndex: i, message: \"WebSocket connection failed\" })); };\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tout.push({ json: { stopped: true, session_id: sessionId }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Stop session failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (op === 'full') {\n\t\t\t\t\t\tconst demoMode = this.getNodeParameter('demoMode', i) as boolean;\n\t\t\t\t\t\tlet sid: number;\n\t\t\t\t\t\tif (demoMode) {\n\t\t\t\t\t\t\tsid = 99999; // mock\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tsid = await resolveSid(i, client);\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Full: resolve schedule failed' });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst mode = this.getNodeParameter('mode', i) as 'main' | 'incognito';\n\t\t\t\t\t\tconst url = this.getNodeParameter('url', i) as string;\n\t\t\t\t\t\tconst ms = this.getNodeParameter('ms', i) as number;\n\n\t\t\t\t\t\tlet session_id: string;\n\t\t\t\t\t\tlet binary: any;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (demoMode) {\n\t\t\t\t\t\t\tsession_id = 'demo-' + Date.now();\n\t\t\t\t\t\t\tconst demoPng = Buffer.from('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', 'base64');\n\t\t\t\t\t\t\tbinary = await this.helpers.prepareBinaryData(demoPng, 'screenshot.png', 'image/png');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tbrowser = await client.rent(sid, { mode });\n\t\t\t\t\t\t\t\tsession_id = browser.sessionId;\n\t\t\t\t\t\t\t\tawait browser.navigate(url);\n\t\t\t\t\t\t\t\tawait sleep(ms);\n\t\t\t\t\t\t\t\tconst shot = await browser.screenshot({ format: 'png', fullPage: true }) as any;\n\t\t\t\t\t\t\t\tconst data = (shot as Buffer).toString('base64');\n\t\t\t\t\t\t\t\tbinary = await this.helpers.prepareBinaryData(Buffer.from(data, 'base64'), 'screenshot.png', 'image/png');\n\t\t\t\t\t\t\t\tawait browser.close();\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Full op failed' });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tout.push({\n\t\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\t\tsession_id,\n\t\t\t\t\t\t\t\tschedule_id: sid,\n\t\t\t\t\t\t\t\tmode,\n\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\twaited: ms,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbinary: { data: binary },\n\t\t\t\t\t\tpairedItem: { item: i },\n\t\t\t\t\t\t});\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tawait client.close().catch(() => { /* best-effort close */ });\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// === Captcha-Protected Scrape (rent browser \u2192 navigate \u2192 wait \u2192 screenshot \u2192 release) ===\n\t\t\t\tif (op === 'captchaScrape') {\n\t\t\t\t\tconst url = this.getNodeParameter('url', i) as string;\n\t\t\t\t\tconst geo = this.getNodeParameter('geo', i) as string;\n\t\t\t\t\tconst maxPrice = this.getNodeParameter('maxPrice', i) as number;\n\t\t\t\t\tconst waitSelector = (this.getNodeParameter('waitSelector', i) as string) || '';\n\t\t\t\t\tconst waitTimeout = this.getNodeParameter('waitTimeout', i) as number;\n\t\t\t\t\tconst extractHtmlFlag = this.getNodeParameter('extractHtml', i) as boolean;\n\t\t\t\t\tconst htmlSelector = (this.getNodeParameter('htmlSelector', i) as string) || 'body';\n\t\t\t\t\tconst fullPage = this.getNodeParameter('fullPage', i) as boolean;\n\t\t\t\t\tlet scheduleId = 0;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst list = await client.search({ geo: geo || undefined, max_price_per_min: maxPrice });\n\t\t\t\t\t\tif (!list.length) throw new NodeOperationError(node, 'No browsers in geo ' + (geo || '*'), { itemIndex: i });\n\t\t\t\t\t\tscheduleId = list[0].schedule_id;\n\t\t\t\t\t\tbrowser = await client.rent(scheduleId);\n\t\t\t\t\t\ttouchedSessions.add(browser.sessionId);\n\t\t\t\t\t\tawait browser.navigate(url);\n\t\t\t\t\t\tif (waitSelector) {\n\t\t\t\t\t\t\tawait waitForSelector(node, browser, waitSelector, waitTimeout);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst shot = await browser.screenshot({ format: 'base64', fullPage }) as any;\n\t\t\t\t\t\tconst data = shot.data ?? (shot instanceof Buffer ? shot.toString('base64') : '');\n\t\t\t\t\t\tconst binary = await this.helpers.prepareBinaryData(\n\t\t\t\t\t\t\tBuffer.from(data, 'base64'),\n\t\t\t\t\t\t\t'captcha-scrape.png',\n\t\t\t\t\t\t\t'image/png',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst json: Record<string, unknown> = {\n\t\t\t\t\t\t\turl, geo, schedule_id: scheduleId,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (extractHtmlFlag) {\n\t\t\t\t\t\t\tjson.html = await extractHtml(browser, htmlSelector);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tout.push({ json: json as any, binary: { data: binary }, pairedItem: { item: i } });\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Captcha-protected scrape failed' });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif (browser) {\n\t\t\t\t\t\t\ttry { await browser.close(); } catch { /* best-effort close -- captcha scrape */ }\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry { await client.close(); } catch { /* best-effort close -- captcha scrape */ }\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// === Screenshot in Geo (rent \u2192 navigate \u2192 screenshot \u2192 release) ===\n\t\t\t\tif (op === 'screenshotGeo') {\n\t\t\t\t\tconst url = this.getNodeParameter('url', i) as string;\n\t\t\t\t\tconst geo = this.getNodeParameter('geo', i) as string;\n\t\t\t\t\tconst fullPage = this.getNodeParameter('fullPage', i) as boolean;\n\t\t\t\t\tconst maxPrice = this.getNodeParameter('maxPrice', i) as number;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst list = await client.search({ geo, max_price_per_min: maxPrice });\n\t\t\t\t\t\tif (!list.length) throw new NodeOperationError(node, 'No browsers in geo ' + geo, { itemIndex: i });\n\t\t\t\t\t\tbrowser = await client.rent(list[0].schedule_id);\n\t\t\t\t\t\ttouchedSessions.add(browser.sessionId);\n\t\t\t\t\t\tawait browser.navigate(url);\n\t\t\t\t\t\tconst shot = await browser.screenshot({ format: 'base64', fullPage }) as any;\n\t\t\t\t\t\tconst binary = await this.helpers.prepareBinaryData(\n\t\t\t\t\t\t\tBuffer.from(shot.data, 'base64'),\n\t\t\t\t\t\t\t'screenshot.png',\n\t\t\t\t\t\t\t'image/png',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tout.push({\n\t\t\t\t\t\t\tjson: { url, geo, schedule_id: list[0].schedule_id },\n\t\t\t\t\t\t\tbinary: { data: binary },\n\t\t\t\t\t\t\tpairedItem: { item: i },\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Screenshot in geo ' + geo + ' failed' });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif (browser) {\n\t\t\t\t\t\t\ttry { await browser.close(); } catch { /* best-effort close -- screenshot geo */ }\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry { await client.close(); } catch { /* best-effort close -- screenshot geo */ }\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// === Contract operations (HTTP API, no WebSocket needed) ===\n\t\t\t\tif (op.startsWith('contract_')) {\n\t\t\t\t\tconst contractClient = new ContractClient(token);\n\t\t\t\t\tconst pop = op.replace('contract_', '');\n\t\t\t\t\tlet result: unknown;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tswitch (pop) {\n\t\t\t\t\t\t\tcase 'list':\n\t\t\t\t\t\t\t\tresult = await contractClient.listContracts();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'tasks': {\n\t\t\t\t\t\t\t\tconst contractId = this.getNodeParameter('contractId', i) as number;\n\t\t\t\t\t\t\t\tresult = await contractClient.tasks(contractId);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase 'get': {\n\t\t\t\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\t\t\t\tresult = await contractClient.task(eventId);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase 'myEvents':\n\t\t\t\t\t\t\t\tresult = await contractClient.myEvents();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'create': {\n\t\t\t\t\t\t\t\tconst contractId = this.getNodeParameter('contractId', i) as number;\n\t\t\t\t\t\t\t\tconst label = this.getNodeParameter('label', i) as string;\n\t\t\t\t\t\t\t\tconst description = (this.getNodeParameter('description', i) as string) || '';\n\t\t\t\t\t\t\t\tconst status = this.getNodeParameter('status', i) as number;\n\t\t\t\t\t\t\t\tconst bType = this.getNodeParameter('benefitableType', i) as string;\n\t\t\t\t\t\t\t\tconst bValue = this.getNodeParameter('benefitableValue', i) as number;\n\t\t\t\t\t\t\t\tresult = await contractClient.create(contractId, {\n\t\t\t\t\t\t\t\t\tlabel,\n\t\t\t\t\t\t\t\t\tdescription: description || undefined,\n\t\t\t\t\t\t\t\t\tstatus,\n\t\t\t\t\t\t\t\t\tbenefitable: bValue ? (bType + ':' + bValue) : undefined,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase 'assign': {\n\t\t\t\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\t\t\t\tconst bType = this.getNodeParameter('benefitableType', i) as string;\n\t\t\t\t\t\t\t\tconst bValue = this.getNodeParameter('benefitableValue', i) as number;\n\t\t\t\t\t\t\t\tresult = await contractClient.assign(eventId, bType + ':' + bValue);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase 'setStatus': {\n\t\t\t\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\t\t\t\tconst status = this.getNodeParameter('status', i) as number;\n\t\t\t\t\t\t\t\tresult = await contractClient.setStatus(eventId, status);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase 'comment': {\n\t\t\t\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\t\t\t\tconst text = (this.getNodeParameter('description', i) as string) || '';\n\t\t\t\t\t\t\t\tresult = await contractClient.comment(eventId, text);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase 'progress': {\n\t\t\t\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\t\t\t\tconst status = this.getNodeParameter('status', i) as number;\n\t\t\t\t\t\t\t\tconst desc = this.getNodeParameter('progressDesc', i) as string;\n\t\t\t\t\t\t\t\tresult = await contractClient.progress(eventId, status, desc);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase 'callHuman': {\n\t\t\t\t\t\t\t\tconst eventId = this.getNodeParameter('eventId', i) as number;\n\t\t\t\t\t\t\t\tconst kind = this.getNodeParameter('callKind', i) as string;\n\t\t\t\t\t\t\t\tconst msg = this.getNodeParameter('callDesc', i) as string;\n\t\t\t\t\t\t\t\tresult = await contractClient.callHuman(eventId, kind, msg);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase 'poll':\n\t\t\t\t\t\t\t\tresult = await contractClient.poll();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tthrow new NodeOperationError(node, 'Unknown contract operation: ' + pop, { itemIndex: i });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tout.push({\n\t\t\t\t\t\t\tjson: result as any,\n\t\t\t\t\t\t\tpairedItem: { item: i },\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Contract ' + pop + ' failed' });\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// All remaining operations: navigate, click, type, scroll, screenshot,\n\t\t\t\t// snapshot, wait, waitForSelector, upload, close.\n\t\t\t\t// Each creates a fresh WS connection and resumes the existing\n\t\t\t\t// browser session by sessionId (server supports cross-WS resume).\n\t\t\t\tconst sessionId = this.getNodeParameter('sessionId', i) as string;\n\t\t\t\ttry {\n\t\t\t\t\tbrowser = await client.resume(sessionId);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: `Resume session \"${sessionId}\" failed. Session may have expired or still be in grace.` });\n\t\t\t\t}\n\t\t\t\tconst sid = browser.sessionId;\n\n\t\t\t\tswitch (op) {\n\t\t\t\t\tcase 'navigate': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst url = this.getNodeParameter('url', i) as string;\n\t\t\t\t\t\t\tawait browser.navigate(url);\n\t\t\t\t\t\t\tout.push({ json: { session_id: sid, url }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Navigate failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'click': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst x = this.getNodeParameter('x', i) as number;\n\t\t\t\t\t\t\tconst y = this.getNodeParameter('y', i) as number;\n\t\t\t\t\t\t\tawait browser.click(x, y);\n\t\t\t\t\t\t\tout.push({ json: { session_id: sid, clicked: [x, y] }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Click failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'type': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst text = this.getNodeParameter('text', i) as string;\n\t\t\t\t\t\t\tawait browser.type(text);\n\t\t\t\t\t\t\tout.push({ json: { session_id: sid, typed: text }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Type failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'scroll': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst deltaY = this.getNodeParameter('deltaY', i) as number;\n\t\t\t\t\t\t\tawait browser.scroll(deltaY);\n\t\t\t\t\t\t\tout.push({ json: { session_id: sid, scrolled: deltaY }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Scroll failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'screenshot': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst format = this.getNodeParameter('format', i) as 'png' | 'base64';\n\t\t\t\t\t\t\tconst fullPage = this.getNodeParameter('fullPage', i) as boolean;\n\t\t\t\t\t\t\tconst shot = await browser.screenshot({ format, fullPage }) as any;\n\t\t\t\t\t\t\tconst data = format === 'base64' ? shot.data : (shot as Buffer).toString('base64');\n\t\t\t\t\t\t\tconst binary = await this.helpers.prepareBinaryData(\n\t\t\t\t\t\t\t\tBuffer.from(data, 'base64'),\n\t\t\t\t\t\t\t\t'screenshot.png',\n\t\t\t\t\t\t\t\t'image/png',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tout.push({ json: { session_id: sid }, binary: { data: binary }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Screenshot failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'snapshot': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst snap = await browser.snapshot();\n\t\t\t\t\t\t\tout.push({\n\t\t\t\t\t\t\t\tjson: { session_id: sid, screenshot: snap.screenshot },\n\t\t\t\t\t\t\t\tpairedItem: { item: i },\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Snapshot failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'wait': {\n\t\t\t\t\t\tconst ms = this.getNodeParameter('ms', i) as number;\n\t\t\t\t\t\tawait sleep(ms);\n\t\t\t\t\t\tout.push({ json: { session_id: sid, waited: ms }, pairedItem: { item: i } });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'waitForSelector': {\n\t\t\t\t\t\tconst selector = this.getNodeParameter('waitSelector', i) as string;\n\t\t\t\t\t\tconst timeout = this.getNodeParameter('waitTimeout', i) as number;\n\t\t\t\t\t\tconst expr = `!!document.querySelector(${JSON.stringify(selector)})`;\n\t\t\t\t\t\tconst deadline = Date.now() + timeout;\n\t\t\t\t\t\tlet ok = false;\n\t\t\t\t\t\tlet lastErr: unknown = null;\n\t\t\t\t\t\twhile (Date.now() < deadline) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst res = await browser.send('Runtime.evaluate', { expression: expr, returnByValue: true }) as any;\n\t\t\t\t\t\t\t\tif (res?.result?.value === true) {\n\t\t\t\t\t\t\t\t\tok = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\tlastErr = e;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tawait sleep(500);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!ok) {\n\t\t\t\t\t\t\tthrow new NodeOperationError(node,\n\t\t\t\t\t\t\t\t`waitForSelector(\"${selector}\") timed out after ${timeout}ms${lastErr ? `: ${(lastErr as Error).message}` : ''}`,\n\t\t\t\t\t\t\t\t{ itemIndex: i },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tout.push({ json: { session_id: sid, selector, found: true }, pairedItem: { item: i } });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'upload': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst selector = this.getNodeParameter('selector', i) as string;\n\t\t\t\t\t\t\tconst bpn = this.getNodeParameter('binaryPropertyName', i) as string;\n\t\t\t\t\t\t\tconst bin = items[i].binary?.[bpn];\n\t\t\t\t\t\t\tif (!bin) throw new NodeOperationError(node, `Binary property \"${bpn}\" not found on input`, { itemIndex: i });\n\t\t\t\t\t\t\tconst stream = await this.helpers.getBinaryStream(bin.id as string);\n\t\t\t\t\t\t\tconst chunks: Buffer[] = [];\n\t\t\t\t\t\t\tfor await (const c of stream) chunks.push(c as Buffer);\n\t\t\t\t\t\t\tconst buf = Buffer.concat(chunks);\n\t\t\t\t\t\t\tconst res = await browser.upload(selector, buf);\n\t\t\t\t\t\t\tout.push({ json: { session_id: sid, uploaded: res }, pairedItem: { item: i } });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthrow new NodeApiError(node, e as Error, { itemIndex: i, message: 'Upload failed' });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'close': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Try graceful CDP close first (best-effort)\n\t\t\t\t\t\t\tawait browser.close().catch(() => { /* best-effort CDP close */ });\n\t\t\t\t\t\t} catch { /* ignore CDP close errors */ }\n\t\t\t\t\t\t// Always send relay stop (force-end session) -- CDP can silently fail\n\t\t\t\t\t\t// eslint-disable-next-line no-async-promise-executor\n\t\t\t\t\t\tawait new Promise((resolve) => {\n\t\t\t\t\t\t\tconst stopWs = new WebSocket('wss://browser.ceki.me/ws/agent', [`bearer.${token}`]);\n\t\t\t\t\t\t\tconst abortTimer = AbortSignal.timeout(10000);\n\t\t\t\t\t\t\tconst onTimer = () => { try { stopWs.close(); } catch { /* close best-effort */ } resolve(); };\n\t\t\t\t\t\t\tabortTimer.addEventListener(\"abort\", onTimer, { once: true });\n\t\t\t\t\t\t\tstopWs.onopen = () => {\n\t\t\t\t\t\t\t\tstopWs.send(JSON.stringify({ type: 'stop', session_id: sessionId, reason: 'n8n close' }));\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tstopWs.onmessage = (ev) => {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst msg = JSON.parse(ev.data);\n\t\t\t\t\t\t\t\t\tif (msg.type === 'session_ended') {\n\t\t\t\t\t\t\t\t\t\tabortTimer.removeEventListener(\"abort\", onTimer);\n\t\t\t\t\t\t\t\t\t\ttry { stopWs.close(); } catch { /* close best-effort */ }\n\t\t\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch { /* msg parse best-effort */ }\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tstopWs.onerror = () => { abortTimer.removeEventListener(\"abort\", onTimer); resolve(); };\n\t\t\t\t\t\t\tstopWs.onclose = () => { abortTimer.removeEventListener(\"abort\", onTimer); resolve(); };\n\t\t\t\t\t\t});\n\t\t\t\t\t\tout.push({ json: { closed: true, session_id: sessionId }, pairedItem: { item: i } });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tneedFullClose = op === 'close';\n\t\t\t\t} finally {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (needFullClose) {\n\t\t\t\t\t\t\tawait client.close();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tawait client.disconnect();\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch { /* swallow cleanup errors */ }\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (this.continueOnFail()) {\n\t\t\t\t\tout.push({ json: { error: (error as Error).message }, pairedItem: { item: i } });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new NodeApiError(this.getNode(), error as JsonObject, { itemIndex: i });\n\t\t\t}\n\t\t}\n\n\t\tif (touchedSessions.size) {\n\t\t\tfor (const sid of touchedSessions) {\n\t\t\t\ttry { await _stopSession(sid); } catch { /* best-effort stop -- session cleanup */ }\n\t\t\t}\n\t\t}\n\t\treturn [out];\n\t}\n}\n", "/**\n * Minimal Ceki browser client \u2014 uses only native WebSocket + fetch (Node 22 globals).\n * Zero npm imports (no ws, no mime-types, no node built-in modules).\n *\n * Timeout management: uses AbortSignal.timeout() instead of restricted\n * setTimeout/clearTimeout globals to satisfy the n8n community-nodes\n * package scanner (no-restricted-globals rule).\n */\n\n// \u2500\u2500 types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface BrowserOption {\n\tschedule_id: number;\n\tgeo?: string;\n\tprice_per_min: number;\n\tonline: boolean;\n\trating?: number | null;\n}\n\nexport interface Match {\n\tsession_id: string;\n\tschedule_id: number;\n\tevent_id?: string | null;\n\tchat_topic_id?: string | null;\n\tprovider_user_id?: number | null;\n\tbrowser_info?: Record<string, unknown>;\n}\n\nexport interface RentOptions {\n\tmode?: 'main' | 'incognito';\n}\n\nexport interface ScreenshotOptions {\n\tformat?: 'png' | 'base64';\n\tfullPage?: boolean;\n}\n\n// \u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction jsonParse(raw: string): unknown {\n\ttry { return JSON.parse(raw); } catch { return null; }\n}\n\n// \u2500\u2500 Client \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class CekiClient {\n\tprivate _ws: WebSocket | null = null;\n\tprivate _connected = false;\n\tprivate _pendingRents = new Map<string, {\n\t\tresolve: (m: Match) => void;\n\t\treject: (e: Error) => void;\n\t}>();\n\tprivate _pendingResumes = new Map<string, {\n\t\tresolve: (m: Match) => void;\n\t\treject: (e: Error) => void;\n\t}>();\n\tprivate _pendingCdp = new Map<number, {\n\t\tresolve: (v: unknown) => void;\n\t\treject: (e: Error) => void;\n\t}>();\n\tprivate _cdpCounter = 1;\n\t_activeSessions = new Map<string, CekiBrowser>();\n\tprivate _connectReject: ((e: Error) => void) | null = null;\n\tprivate _closed = false;\n\n\tconstructor(\n\t\tprivate _token: string,\n\t\tprivate _relayUrl = 'wss://browser.ceki.me/ws/agent',\n\t\tprivate _apiUrl = 'https://api.ceki.me',\n\t) {}\n\n\t/** Connect to the relay WebSocket. */\n\tasync connect(): Promise<void> {\n\t\tif (this._connected) return;\n\t\tconst protocols = [`bearer.${this._token}`];\n\t\tthis._ws = new WebSocket(this._relayUrl, protocols);\n\t\tthis._ws.onopen = () => {\n\t\t\tthis._connected = true;\n\t\t};\n\t\tthis._ws.onmessage = (ev: MessageEvent) => {\n\t\t\tthis._handleMessage(ev.data);\n\t\t};\n\t\tthis._ws.onclose = (ev: CloseEvent) => {\n\t\t\tthis._connected = false;\n\t\t\tif ((ev.code === 4401 || ev.code === 4403) && this._connectReject) {\n\t\t\t\tthis._connectReject(new Error(`Auth failed: ${ev.reason || String(ev.code)}`));\n\t\t\t\tthis._connectReject = null;\n\t\t\t}\n\t\t};\n\t\tthis._ws.onerror = () => {\n\t\t\tif (!this._connected && this._connectReject) {\n\t\t\t\tthis._connectReject(new Error('WebSocket connection failed'));\n\t\t\t\tthis._connectReject = null;\n\t\t\t}\n\t\t};\n\t\tif (this._ws.readyState === WebSocket.CONNECTING) {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tif (!this._ws) { reject(new Error('No WebSocket')); return; }\n\t\t\t\tthis._connectReject = reject;\n\t\t\t\tthis._ws!.onopen = () => {\n\t\t\t\t\tthis._connected = true;\n\t\t\t\t\tresolve();\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\t}\n\n\t_sendRaw(msg: Record<string, unknown>): void {\n\t\tif (!this._ws || this._ws.readyState !== WebSocket.OPEN) {\n\t\t\tthrow new Error('WebSocket not connected');\n\t\t}\n\t\tthis._ws.send(JSON.stringify(msg));\n\t}\n\n\t/** Search for available browser providers (HTTP GET). */\n\tasync search(filters?: Record<string, unknown>, limit?: number): Promise<BrowserOption[]> {\n\t\tconst params = new URLSearchParams();\n\t\tif (limit != null) params.set('limit', String(limit));\n\t\tif (filters) {\n\t\t\tfor (const [k, v] of Object.entries(filters)) {\n\t\t\t\tif (v != null) params.set(k, String(v));\n\t\t\t}\n\t\t}\n\t\tconst resp = await fetch(`${this._apiUrl}/api/browsers/search?${params}`, {\n\t\t\theaders: { Authorization: `Bearer ${this._token}` },\n\t\t});\n\t\tif (!resp.ok) throw new Error(`Search failed: ${resp.status}`);\n\t\tconst body = (await resp.json()) as Record<string, unknown>;\n\t\tconst data = (body.data ?? body) as unknown[];\n\t\treturn Array.isArray(data) ? data as BrowserOption[] : [];\n\t}\n\n\t/** Rent a browser by schedule_id. */\n\tasync rent(scheduleId: number, opts?: RentOptions): Promise<CekiBrowser> {\n\t\tconst msg: Record<string, unknown> = { type: 'rent', browser_id: scheduleId };\n\t\tif (opts?.mode) msg.mode = opts.mode;\n\t\tthis._sendRaw(msg);\n\t\treturn this._awaitRent(`rent:${scheduleId}`, scheduleId, 90000);\n\t}\n\n\t/** Resume an existing session. */\n\tasync resume(sessionId: string): Promise<CekiBrowser> {\n\t\tthis._sendRaw({ type: 'resume', session_id: sessionId });\n\t\treturn this._awaitResume(sessionId);\n\t}\n\n\t/** Close the WS connection \u2014 session stays alive in grace.\n\t * Waits for the close handshake so the relay processes the close\n\t * before a new connection with the same renterId is established\n\t * (avoids the close-handler race condition).\n\t */\n\tasync disconnect(): Promise<void> {\n\t\tthis._closed = true;\n\t\tthis._activeSessions.clear();\n\t\tthis._pendingRents.clear();\n\t\tthis._pendingResumes.clear();\n\t\tif (!this._ws) return;\n\t\tconst ws = this._ws;\n\t\tif (ws.readyState === WebSocket.CLOSED) {\n\t\t\tthis._ws = null;\n\t\t\treturn;\n\t\t}\n\t\tif (ws.readyState === WebSocket.CLOSING) {\n\t\t\tawait new Promise<void>(r => { ws.onclose = () => { this._connected = false; r(); }; });\n\t\t\tthis._ws = null;\n\t\t\treturn;\n\t\t}\n\t\t// OPEN \u2192 initiate close and wait for handshake (up to 5s safety timeout)\n\t\tawait new Promise<void>(r => {\n\t\t\tconst onAbort = () => r();\n\t\t\tconst abortTimer = AbortSignal.timeout(5000);\n\t\t\tabortTimer.addEventListener('abort', onAbort, { once: true });\n\t\t\tws.onclose = () => { this._connected = false; abortTimer.removeEventListener('abort', onAbort); r(); };\n\t\t\ttry { ws.close(); } catch { abortTimer.removeEventListener('abort', onAbort); r(); }\n\t\t});\n\t\tthis._ws = null;\n\t}\n\n\t/** Close everything. */\n\tasync close(): Promise<void> {\n\t\tawait this.disconnect();\n\t}\n\n\t// \u2500\u2500 private \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\tprivate _awaitRent(key: string, scheduleId: number, timeoutMs: number): Promise<CekiBrowser> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeoutSignal = AbortSignal.timeout(timeoutMs);\n\t\t\ttimeoutSignal.addEventListener('abort', () => {\n\t\t\t\tthis._pendingRents.delete(key);\n\t\t\t\treject(new Error('Rent timed out'));\n\t\t\t}, { once: true });\n\t\t\tthis._pendingRents.set(key, {\n\t\t\t\tresolve: (match: Match) => {\n\t\t\t\t\tconst browser = new CekiBrowser(this, match);\n\t\t\t\t\tthis._activeSessions.set(browser.sessionId, browser);\n\t\t\t\t\tresolve(browser);\n\t\t\t\t},\n\t\t\t\treject: (err: Error) => {\n\t\t\t\t\treject(err);\n\t\t\t\t},\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate _awaitResume(sessionId: string): Promise<CekiBrowser> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeoutSignal = AbortSignal.timeout(60000);\n\t\t\ttimeoutSignal.addEventListener('abort', () => {\n\t\t\t\tthis._pendingResumes.delete(sessionId);\n\t\t\t\treject(new Error('Resume timed out'));\n\t\t\t}, { once: true });\n\t\t\tthis._pendingResumes.set(sessionId, {\n\t\t\t\tresolve: (match: Match) => {\n\t\t\t\t\tconst browser = new CekiBrowser(this, match);\n\t\t\t\t\tthis._activeSessions.set(browser.sessionId, browser);\n\t\t\t\t\tresolve(browser);\n\t\t\t\t},\n\t\t\t\treject: (err: Error) => {\n\t\t\t\t\treject(err);\n\t\t\t\t},\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate _closeWs(): void {\n\t\tif (this._ws) {\n\t\t\ttry { this._ws.onopen = null; this._ws.onmessage = null; this._ws.onclose = null; this._ws.onerror = null; this._ws.close(); } catch { /* ignore */ }\n\t\t\tthis._ws = null;\n\t\t}\n\t}\n\n\tprivate _handleMessage(data: unknown): void {\n\t\tconst msg = jsonParse(String(data)) as Record<string, unknown> | null;\n\t\tif (!msg || typeof msg !== 'object') return;\n\t\tconst type = String(msg.type ?? '');\n\t\tconst sid = msg.session_id ? String(msg.session_id) : null;\n\n\t\tswitch (type) {\n\t\t\tcase 'pong':\n\t\t\tcase 'rent_pending':\n\t\t\t\tbreak;\n\t\t\tcase 'match':\n\t\t\t\tthis._onMatch(msg);\n\t\t\t\tbreak;\n\t\t\tcase 'rent.error':\n\t\t\t\tthis._onRentError(msg);\n\t\t\t\tbreak;\n\t\t\tcase 'resume_ok':\n\t\t\t\tthis._onResumeOk(msg);\n\t\t\t\tbreak;\n\t\t\tcase 'resume_failed':\n\t\t\t\tthis._onResumeFailed(msg);\n\t\t\t\tbreak;\n\t\t\tcase 'cdp_response':\n\t\t\t\tif (sid) this._onCdpResponse(sid, msg);\n\t\t\t\tbreak;\n\t\t\tcase 'session.ended':\n\t\t\t\tif (sid) {\n\t\t\t\t\tthis._activeSessions.delete(sid);\n\t\t\t\t\tconst b = this._activeSessions.get(sid);\n\t\t\t\t\tif (b) (b as any)._ended = String(msg.reason ?? 'ended');\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate _onMatch(msg: Record<string, unknown>): void {\n\t\tconst scheduleId = Number(msg.schedule_id ?? 0);\n\t\tconst eventId = msg.event_id ? String(msg.event_id) : null;\n\t\tconst sessionId = String(msg.session_id ?? '');\n\t\t// Send match_ack to transition session from ACCEPTED to ACTIVE.\n\t\t// Without this, subsequent resume from other n8n nodes would receive\n\t\t// \"match\" instead of \"resume_ok\" (session stays ACCEPTED).\n\t\tif (sessionId && this._ws?.readyState === WebSocket.OPEN) {\n\t\t\ttry { this._ws.send(JSON.stringify({ type: 'match_ack', session_id: sessionId })); } catch { /* ignore */ }\n\t\t}\n\t\t// Check pending rents (normal rent flow)\n\t\tlet pending = this._pendingRents.get(`event:${eventId}`);\n\t\tif (!pending) pending = this._pendingRents.get(`rent:${scheduleId}`);\n\t\tif (pending) {\n\t\t\tthis._pendingRents.delete(`event:${eventId}`);\n\t\t\tthis._pendingRents.delete(`rent:${scheduleId}`);\n\t\t\tpending.resolve({\n\t\t\t\tsession_id: sessionId,\n\t\t\t\tschedule_id: scheduleId,\n\t\t\t\tevent_id: eventId,\n\t\t\t\tchat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,\n\t\t\t\tprovider_user_id: msg.provider_user_id != null ? Number(msg.provider_user_id) : null,\n\t\t\t\tbrowser_info: (msg.browser_info ?? {}) as Record<string, unknown>,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\t// Fallback: relay may send \"match\" during resume if session is ACCEPTED\n\t\t// (e.g. when rent node finished without sending match_ack).\n\t\t// Treat it like resume_ok so the next node doesn't hang.\n\t\tconst resumePending = sessionId ? this._pendingResumes.get(sessionId) : null;\n\t\tif (resumePending) {\n\t\t\tthis._pendingResumes.delete(sessionId);\n\t\t\tresumePending.resolve({\n\t\t\t\tsession_id: sessionId,\n\t\t\t\tschedule_id: scheduleId,\n\t\t\t\tevent_id: eventId,\n\t\t\t\tchat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,\n\t\t\t\tprovider_user_id: msg.provider_user_id != null ? Number(msg.provider_user_id) : null,\n\t\t\t\tbrowser_info: (msg.browser_info ?? {}) as Record<string, unknown>,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate _onRentError(msg: Record<string, unknown>): void {\n\t\tconst code = String(msg.code ?? '');\n\t\tconst message = String(msg.message ?? '');\n\t\tfor (const [key, pending] of this._pendingRents) {\n\t\t\tthis._pendingRents.delete(key);\n\t\t\tpending.reject(new Error(message || `Rent error: ${code}`));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate _onResumeOk(msg: Record<string, unknown>): void {\n\t\tconst sessionId = String(msg.session_id ?? '');\n\t\tconst pending = this._pendingResumes.get(sessionId);\n\t\tif (!pending) return;\n\t\tthis._pendingResumes.delete(sessionId);\n\t\tpending.resolve({\n\t\t\tsession_id: sessionId,\n\t\t\tschedule_id: Number(msg.schedule_id ?? 0),\n\t\t\tevent_id: msg.event_id ? String(msg.event_id) : null,\n\t\t\tchat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,\n\t\t\tprovider_user_id: msg.provider_user_id != null ? Number(msg.provider_user_id) : null,\n\t\t\tbrowser_info: (msg.browser_info ?? {}) as Record<string, unknown>,\n\t\t});\n\t}\n\n\tprivate _onResumeFailed(msg: Record<string, unknown>): void {\n\t\tconst sessionId = String(msg.session_id ?? '');\n\t\tconst pending = this._pendingResumes.get(sessionId);\n\t\tif (!pending) return;\n\t\tthis._pendingResumes.delete(sessionId);\n\t\tpending.reject(new Error(String(msg.reason ?? 'Resume failed')));\n\t}\n\n\tprivate _onCdpResponse(sessionId: string, msg: Record<string, unknown>): void {\n\t\tconst browser = this._activeSessions.get(sessionId);\n\t\tif (!browser) return;\n\t\tconst id = Number(msg.id ?? 0);\n\t\t// NOTE: pending CDP is stored on CekiBrowser._pendingCdp (set by CekiBrowser.send()),\n\t\t// NOT on CekiClient._pendingCdp \u2014 they are different maps.\n\t\tconst pending = browser._pendingCdp.get(id);\n\t\tif (!pending) return;\n\t\tbrowser._pendingCdp.delete(id);\n\t\tif (msg.error) {\n\t\t\tpending.reject(new Error(String((msg.error as Record<string, unknown>).message ?? 'CDP error')));\n\t\t} else {\n\t\t\tpending.resolve(msg.result);\n\t\t}\n\t}\n}\n\n// \u2500\u2500 Browser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class CekiBrowser {\n\treadonly sessionId: string;\n\treadonly scheduleId: number;\n\treadonly chatTopicId: string | null;\n\treadonly browserInfo: Record<string, unknown>;\n\treadonly providerUserId: number | null;\n\n\tprivate _client: CekiClient;\n\tprivate _cdpId = 1;\n\t_pendingCdp = new Map<number, { resolve: (v: unknown) => void; reject: (e: Error) => void }>();\n\n\tconstructor(client: CekiClient, match: Match) {\n\t\tthis._client = client;\n\t\tthis.sessionId = match.session_id;\n\t\tthis.scheduleId = match.schedule_id;\n\t\tthis.chatTopicId = match.chat_topic_id ?? null;\n\t\tthis.browserInfo = match.browser_info ?? {};\n\t\tthis.providerUserId = match.provider_user_id ?? null;\n\t}\n\n\t/** Send a CDP command. Uses AbortSignal.timeout() (no restricted setTimeout global). */\n\tasync send(method: string, params?: Record<string, unknown>, timeoutMs = 30000): Promise<unknown> {\n\t\tconst id = this._cdpId++;\n\t\tconst msg = { type: 'cdp', session_id: this.sessionId, id, method, params: params ?? {} };\n\t\tthis._client._sendRaw(msg);\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timeoutSignal = AbortSignal.timeout(timeoutMs);\n\t\t\ttimeoutSignal.addEventListener('abort', () => {\n\t\t\t\tthis._pendingCdp.delete(id);\n\t\t\t\treject(new Error(`CDP ${method} timed out after ${timeoutMs}ms`));\n\t\t\t}, { once: true });\n\t\t\tthis._pendingCdp.set(id, {\n\t\t\t\tresolve: (v) => { resolve(v); },\n\t\t\t\treject: (e) => { reject(e); },\n\t\t\t});\n\t\t});\n\t}\n\n\tasync navigate(url: string, timeoutMs?: number): Promise<void> {\n\t\tawait this.send('Page.navigate', { url }, timeoutMs);\n\t}\n\n\tasync click(x: number, y: number): Promise<void> {\n\t\tawait this.send('Input.dispatchMouseEvent', { type: 'mousePressed', x, y, button: 'left', clickCount: 1 });\n\t\tawait this.send('Input.dispatchMouseEvent', { type: 'mouseReleased', x, y, button: 'left', clickCount: 1 });\n\t}\n\n\tasync type(text: string): Promise<void> {\n\t\tawait this.send('Ceki.typeText', { text });\n\t}\n\n\tasync scroll(deltaY: number): Promise<void> {\n\t\tawait this.send('Input.dispatchMouseEvent', { type: 'mouseWheel', x: 0, y: 0, deltaX: 0, deltaY });\n\t}\n\n\tasync screenshot(opts?: ScreenshotOptions): Promise<{ data: string } | Buffer> {\n\t\tconst format = opts?.format ?? 'base64';\n\t\tconst fullPage = opts?.fullPage ?? false;\n\t\tlet clip: Record<string, number> | undefined;\n\t\tif (fullPage) {\n\t\t\tconst metrics = await this.send('Page.getLayoutMetrics') as Record<string, unknown> | null;\n\t\t\tconst contentSize = metrics?.contentSize as Record<string, number> | undefined;\n\t\t\tif (contentSize) {\n\t\t\t\tclip = { x: 0, y: 0, width: Number(contentSize.width ?? 1920), height: Math.min(Number(contentSize.height ?? 1080), 16384), scale: 1 };\n\t\t\t}\n\t\t}\n\t\tconst result = await this.send('Page.captureScreenshot', { format: 'png', ...(clip ? { clip } : {}) }) as Record<string, unknown> | null;\n\t\tconst data = String(result?.data ?? '');\n\t\tif (format === 'png') {\n\t\t\treturn Buffer.from(data, 'base64');\n\t\t}\n\t\treturn { data };\n\t}\n\n\tasync snapshot(): Promise<{ screenshot: string; ts: Date }> {\n\t\tconst ssResult = await this.screenshot({ format: 'base64' }) as { data: string };\n\t\treturn { screenshot: ssResult.data, ts: new Date() };\n\t}\n\n\tasync upload(selector: string, buf: Buffer, filename = 'file'): Promise<Record<string, unknown>> {\n\t\tconst b64 = buf.toString('base64');\n\t\tconst size = buf.length;\n\t\tconst mime = 'application/octet-stream';\n\t\tconst expression = `(function(){\n\t\t\tvar input = document.querySelector(${JSON.stringify(selector)});\n\t\t\tif (!input) return JSON.stringify({ok:false,error:'Element not found'});\n\t\t\tvar b = atob(${JSON.stringify(b64)});\n\t\t\tvar u = new Uint8Array(b.length);\n\t\t\tfor (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i);\n\t\t\tvar f = new File([u], ${JSON.stringify(filename)}, {type: ${JSON.stringify(mime)}});\n\t\t\tvar dt = new DataTransfer(); dt.items.add(f);\n\t\t\tinput.files = dt.files;\n\t\t\tinput.dispatchEvent(new Event('change',{bubbles:true}));\n\t\t\treturn JSON.stringify({ok:true,filename:${JSON.stringify(filename)},size:${size}});\n\t\t})()`;\n\t\tconst result = await this.send('Runtime.evaluate', { expression, returnByValue: true }) as Record<string, unknown> | null;\n\t\ttry {\n\t\t\tawait this.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Escape', code: 'Escape', windowsVirtualKeyCode: 27, nativeVirtualKeyCode: 27 });\n\t\t\tawait this.send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Escape', code: 'Escape', windowsVirtualKeyCode: 27, nativeVirtualKeyCode: 27 });\n\t\t} catch { /* ignore */ }\n\t\tconst resultObj = result?.result as Record<string, unknown> | undefined;\n\t\tif (resultObj?.value) return JSON.parse(String(resultObj.value)) as Record<string, unknown>;\n\t\treturn { ok: true, filename, size };\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.send('Ceki.close', {}).catch(() => {});\n\t\tthis._client._activeSessions.delete(this.sessionId);\n\t}\n}\n", "/**\n * Minimal Ceki contract client \u2014 uses only native fetch (Node 22 global).\n * Zero npm imports (no ws, no axios, no node built-in modules beyond globals).\n *\n * Communicates with Ceki's MCP endpoint via JSON-RPC 2.0 over HTTP POST.\n */\n\n// \u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction cleanArgs<T extends Record<string, unknown>>(o: T): Partial<T> {\n\tconst out = { ...o };\n\tfor (const k of Object.keys(out)) {\n\t\tif ((out as any)[k] === undefined || (out as any)[k] === null) delete (out as any)[k];\n\t}\n\treturn out;\n}\n\nfunction parseBenefitable(value: string | null | undefined): { type: string; value: number } | null {\n\tif (!value) return null;\n\tconst m = /^(agent|user):(\\d+)$/.exec(value);\n\tif (!m) return null;\n\treturn { type: m[1], value: Number(m[2]) };\n}\n\ninterface ParticipantSpec {\n\tparticipable_id: number;\n\ttype: string;\n\trole_id: number;\n}\n\nfunction parseParticipant(value: string | null | undefined, roleId: number): ParticipantSpec | null {\n\tconst b = parseBenefitable(value);\n\tif (!b) return null;\n\treturn { participable_id: b.value, type: b.type, role_id: roleId };\n}\n\nfunction deriveLabel(desc: string | null | undefined): string {\n\tif (!desc) return '';\n\tconst line = desc.split('\\n')[0].trim();\n\treturn line.length > 60 ? line.slice(0, 57) + '...' : line;\n}\n\nconst ROLE_REVIEWER = 5;\nconst ROLE_QA = 6;\n\n// \u2500\u2500 types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface CreateOptions {\n\tlabel: string;\n\ttype?: number;\n\tstatus?: number;\n\tdescription?: string;\n\tbenefitable?: string;\n\treviewer?: string;\n\tqa?: string;\n}\n\nexport interface ProposeOptions {\n\tstatus?: number;\n\tlabel?: string;\n\tdescription?: string;\n\tbenefitable?: string;\n}\n\nexport interface CommentOptions {\n\tlabel?: string;\n\tdescription?: string;\n}\n\nexport interface ProgressOptions {\n\tstatus?: number;\n\tdesc: string;\n}\n\n// \u2500\u2500 client \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class ContractClient {\n\tprivate _endpoint: string;\n\tprivate _apiBase: string;\n\tprivate _token: string;\n\n\tconstructor(token: string, endpoint?: string, apiBase?: string) {\n\t\tthis._endpoint = (endpoint ?? 'https://api.ceki.me/mcp').replace(/\\/+$/, '');\n\t\tthis._apiBase = (apiBase ?? 'https://api.ceki.me').replace(/\\/+$/, '');\n\t\tthis._token = token;\n\t}\n\n\tprivate _headers(): Record<string, string> {\n\t\treturn {\n\t\t\t'Content-Type': 'application/json',\n\t\t\tAccept: 'application/json',\n\t\t\tAuthorization: `Bearer ${this._token}`,\n\t\t};\n\t}\n\n\tprivate async _rpc(method: string, params: Record<string, unknown>): Promise<any> {\n\t\tconst body = JSON.stringify({ jsonrpc: '2.0', id: Date.now(), method, params });\n\t\tconst resp = await fetch(this._endpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: this._headers(),\n\t\t\tbody,\n\t\t});\n\t\tif (!resp.ok) {\n\t\t\tconst text = await resp.text().catch(() => '');\n\t\t\tthrow new Error(`HTTP ${resp.status}: ${text.slice(0, 400)}`);\n\t\t}\n\t\treturn resp.json();\n\t}\n\n\tprivate async _call(tool: string, args?: Record<string, unknown>): Promise<any> {\n\t\tconst body = await this._rpc('tools/call', { name: tool, arguments: args ?? {} });\n\t\tif (body.error) throw new Error(`${tool} \u2192 ${JSON.stringify(body.error).slice(0, 400)}`);\n\t\tconst result = body.result ?? {};\n\t\tconst content = result.content;\n\t\tif (Array.isArray(content)) {\n\t\t\tconst texts = content.filter((c: any) => c.type === 'text').map((c: any) => String(c.text ?? ''));\n\t\t\tconst joined = texts.join('\\n');\n\t\t\ttry { return JSON.parse(joined); } catch { return joined; }\n\t\t}\n\t\tif (result.structuredContent !== undefined) return result.structuredContent;\n\t\treturn result;\n\t}\n\n\t// \u2500\u2500 domain methods \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\tasync listContracts(): Promise<any> {\n\t\treturn this._call('list-contracts');\n\t}\n\n\tasync members(contractId: number): Promise<any> {\n\t\treturn this._call('contract-members', { contract_id: contractId });\n\t}\n\n\tasync tasks(contractId: number): Promise<any> {\n\t\treturn this._call('contract-tasks', { contract_id: contractId });\n\t}\n\n\tasync myEvents(): Promise<any> {\n\t\treturn this._call('get-my-events');\n\t}\n\n\tasync task(eventId: number): Promise<any> {\n\t\treturn this._call('get-event', { event_id: eventId });\n\t}\n\n\tasync create(contractId: number, opts: CreateOptions): Promise<any> {\n\t\tconst args = cleanArgs({\n\t\t\tcontract_id: contractId,\n\t\t\tlabel: opts.label,\n\t\t\ttype_id: opts.type,\n\t\t\tstatus_id: opts.status,\n\t\t\tdescription: opts.description,\n\t\t\tbenefitable: opts.benefitable ? parseBenefitable(opts.benefitable) : undefined,\n\t\t});\n\t\tconst users: ParticipantSpec[] = [];\n\t\tconst rev = parseParticipant(opts.reviewer, ROLE_REVIEWER);\n\t\tif (rev) users.push(rev);\n\t\tconst qa = parseParticipant(opts.qa, ROLE_QA);\n\t\tif (qa) users.push(qa);\n\t\tif (users.length) (args as any).users = users;\n\t\treturn this._call('create-contract-event', args);\n\t}\n\n\tasync propose(eventId: number, opts: ProposeOptions): Promise<any> {\n\t\treturn this._call('propose-correction', cleanArgs({\n\t\t\tevent_id: eventId,\n\t\t\tstatus_id: opts.status,\n\t\t\tlabel: opts.label,\n\t\t\tdescription: opts.description,\n\t\t\tbenefitable: opts.benefitable ? parseBenefitable(opts.benefitable) : undefined,\n\t\t}));\n\t}\n\n\tasync comment(eventId: number, opts?: CommentOptions): Promise<any> {\n\t\treturn this._call('comment', cleanArgs({\n\t\t\tevent_id: eventId,\n\t\t\tlabel: opts?.label,\n\t\t\tdescription: opts?.description,\n\t\t}));\n\t}\n\n\tasync progress(eventId: number, opts: ProgressOptions): Promise<any> {\n\t\tlet statusResult: any = null;\n\t\tif (opts.status != null) {\n\t\t\tstatusResult = await this.propose(eventId, { status: opts.status });\n\t\t}\n\t\tconst commentResult = await this.comment(eventId, { label: deriveLabel(opts.desc), description: opts.desc });\n\t\treturn { status_correction: statusResult, comment: commentResult };\n\t}\n\n\tasync callHuman(eventId: number, kind: 'input' | 'review' | 'stuck', desc: string): Promise<any> {\n\t\tif (!['input', 'review', 'stuck'].includes(kind)) throw new Error(`kind must be input|review|stuck, got ${kind}`);\n\t\treturn this._call('call-human', { event_id: eventId, kind, desc });\n\t}\n\n\t/** GET /agent/polling. Returns [] on 429. */\n\tasync poll(): Promise<any[]> {\n\t\tconst resp = await fetch(`${this._apiBase}/agent/polling`, {\n\t\t\theaders: { Accept: 'application/json', Authorization: `Bearer ${this._token}` },\n\t\t});\n\t\tif (resp.status === 429) return [];\n\t\tif (!resp.ok) {\n\t\t\tconst text = await resp.text().catch(() => '');\n\t\t\tthrow new Error(`poll HTTP ${resp.status}: ${text.slice(0, 300)}`);\n\t\t}\n\t\tconst body = (await resp.json()) as Record<string, unknown>;\n\t\tif (Array.isArray(body)) return body;\n\t\tif (body && typeof body === 'object') {\n\t\t\tfor (const k of ['notifications', 'data', 'items']) {\n\t\t\t\tif (Array.isArray(body[k])) return body[k] as any[];\n\t\t\t}\n\t\t}\n\t\treturn [];\n\t}\n}\n", "import type {\n\tIAuthenticateGeneric,\n\tICredentialTestRequest,\n\tICredentialType,\n\tINodeProperties,\n} from 'n8n-workflow';\n\n/**\n * Ceki agent token (ag_...). Authorizes every Ceki node.\n * Get it from the Ceki panel \u2192 agent profile \u2192 API key.\n */\nexport class CekiApi implements ICredentialType {\n\tname = 'cekiApi';\n\tdisplayName = 'Ceki API';\n\ticon = { light: 'file:ceki-light.svg', dark: 'file:ceki-dark.svg' };\n\tdocumentationUrl = 'https://browser.ceki.me/docs#api-key';\n\tproperties: INodeProperties[] = [\n\t\t{\n\t\t\tdisplayName: 'API Key',\n\t\t\tname: 'token',\n\t\t\ttype: 'string',\n\t\t\ttypeOptions: { password: true },\n\t\t\tdefault: '',\n\t\t\tdescription:\n\t\t\t\t'Agent token (ag_...). [Get your API key \u2192](https://browser.ceki.me/docs#api-key)',\n\t\t\trequired: true,\n\t\t},\n\t];\n\n\tauthenticate: IAuthenticateGeneric = {\n\t\ttype: 'generic',\n\t\tproperties: {\n\t\t\theaders: {\n\t\t\t\tAuthorization: '=Bearer {{$credentials?.token}}',\n\t\t\t},\n\t\t},\n\t};\n\n\ttest: ICredentialTestRequest = {\n\t\trequest: {\n\t\t\tbaseURL: 'https://api.ceki.me',\n\t\t\turl: '/api/browsers/search',\n\t\t\tmethod: 'GET',\n\t\t},\n\t};\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["sid", "sessionId"]
7
7
  }