@elizaos/plugin-browser 1.0.3 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +75 -23
  2. package/dist/actions/click.d.ts +3 -0
  3. package/dist/actions/click.d.ts.map +1 -0
  4. package/dist/actions/click.js +98 -0
  5. package/dist/actions/click.js.map +1 -0
  6. package/dist/actions/extract.d.ts +3 -0
  7. package/dist/actions/extract.d.ts.map +1 -0
  8. package/dist/actions/extract.js +110 -0
  9. package/dist/actions/extract.js.map +1 -0
  10. package/dist/actions/index.d.ts +7 -0
  11. package/dist/actions/index.d.ts.map +1 -0
  12. package/dist/actions/index.js +7 -0
  13. package/dist/actions/index.js.map +1 -0
  14. package/dist/actions/navigate.d.ts +3 -0
  15. package/dist/actions/navigate.d.ts.map +1 -0
  16. package/dist/actions/navigate.js +129 -0
  17. package/dist/actions/navigate.js.map +1 -0
  18. package/dist/actions/screenshot.d.ts +3 -0
  19. package/dist/actions/screenshot.d.ts.map +1 -0
  20. package/dist/actions/screenshot.js +107 -0
  21. package/dist/actions/screenshot.js.map +1 -0
  22. package/dist/actions/select.d.ts +3 -0
  23. package/dist/actions/select.d.ts.map +1 -0
  24. package/dist/actions/select.js +105 -0
  25. package/dist/actions/select.js.map +1 -0
  26. package/dist/actions/type.d.ts +3 -0
  27. package/dist/actions/type.d.ts.map +1 -0
  28. package/dist/actions/type.js +105 -0
  29. package/dist/actions/type.js.map +1 -0
  30. package/dist/index.d.ts +17 -5
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +119 -348
  33. package/dist/index.js.map +1 -1
  34. package/dist/providers/browser-state.d.ts +3 -0
  35. package/dist/providers/browser-state.d.ts.map +1 -0
  36. package/dist/providers/browser-state.js +47 -0
  37. package/dist/providers/browser-state.js.map +1 -0
  38. package/dist/providers/index.d.ts +2 -0
  39. package/dist/providers/index.d.ts.map +1 -0
  40. package/dist/providers/index.js +2 -0
  41. package/dist/providers/index.js.map +1 -0
  42. package/dist/services/browser-service.d.ts +30 -0
  43. package/dist/services/browser-service.d.ts.map +1 -0
  44. package/dist/services/browser-service.js +164 -0
  45. package/dist/services/browser-service.js.map +1 -0
  46. package/dist/services/index.d.ts +4 -0
  47. package/dist/services/index.d.ts.map +1 -0
  48. package/dist/services/index.js +4 -0
  49. package/dist/services/index.js.map +1 -0
  50. package/dist/services/process-manager.d.ts +15 -0
  51. package/dist/services/process-manager.d.ts.map +1 -0
  52. package/dist/services/process-manager.js +186 -0
  53. package/dist/services/process-manager.js.map +1 -0
  54. package/dist/services/websocket-client.d.ts +35 -0
  55. package/dist/services/websocket-client.d.ts.map +1 -0
  56. package/dist/services/websocket-client.js +219 -0
  57. package/dist/services/websocket-client.js.map +1 -0
  58. package/dist/types.d.ts +101 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/utils/captcha.d.ts +33 -0
  63. package/dist/utils/captcha.d.ts.map +1 -0
  64. package/dist/utils/captcha.js +219 -0
  65. package/dist/utils/captcha.js.map +1 -0
  66. package/dist/utils/errors.d.ts +37 -0
  67. package/dist/utils/errors.d.ts.map +1 -0
  68. package/dist/utils/errors.js +81 -0
  69. package/dist/utils/errors.js.map +1 -0
  70. package/dist/utils/index.d.ts +5 -0
  71. package/dist/utils/index.d.ts.map +1 -0
  72. package/dist/utils/index.js +5 -0
  73. package/dist/utils/index.js.map +1 -0
  74. package/dist/utils/retry.d.ts +26 -0
  75. package/dist/utils/retry.d.ts.map +1 -0
  76. package/dist/utils/retry.js +55 -0
  77. package/dist/utils/retry.js.map +1 -0
  78. package/dist/utils/security.d.ts +27 -0
  79. package/dist/utils/security.d.ts.map +1 -0
  80. package/dist/utils/security.js +138 -0
  81. package/dist/utils/security.js.map +1 -0
  82. package/dist/utils/url.d.ts +12 -0
  83. package/dist/utils/url.d.ts.map +1 -0
  84. package/dist/utils/url.js +38 -0
  85. package/dist/utils/url.js.map +1 -0
  86. package/package.json +60 -42
  87. package/LICENSE +0 -21
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captcha.js","sourceRoot":"","sources":["../../src/utils/captcha.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger } from \"@elizaos/core\";\nimport axios from \"axios\";\nimport type { CapSolverConfig, CaptchaTask, CaptchaType } from \"../types.js\";\n\ninterface CapSolverTaskResult {\n token?: string;\n gRecaptchaResponse?: string;\n}\n\nexport class CapSolverService {\n private readonly apiUrl: string;\n private readonly retryAttempts: number;\n private readonly pollingInterval: number;\n\n constructor(private config: CapSolverConfig) {\n this.apiUrl = config.apiUrl ?? \"https://api.capsolver.com\";\n this.retryAttempts = config.retryAttempts ?? 60;\n this.pollingInterval = config.pollingInterval ?? 2000;\n }\n\n /**\n * Create a CAPTCHA solving task\n */\n async createTask(task: CaptchaTask): Promise<string> {\n try {\n const response = await axios.post(\n `${this.apiUrl}/createTask`,\n {\n clientKey: this.config.apiKey,\n task,\n },\n {\n headers: { \"Content-Type\": \"application/json\" },\n timeout: 30000,\n }\n );\n\n if (response.data.errorId !== 0) {\n throw new Error(`CapSolver error: ${response.data.errorDescription ?? \"Unknown error\"}`);\n }\n\n logger.info(\"CapSolver task created:\", response.data.taskId);\n return response.data.taskId;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Error creating CapSolver task: ${errorMessage}`);\n throw error;\n }\n }\n\n async getTaskResult(taskId: string): Promise<CapSolverTaskResult> {\n let attempts = 0;\n\n while (attempts < this.retryAttempts) {\n try {\n const response = await axios.post(\n `${this.apiUrl}/getTaskResult`,\n {\n clientKey: this.config.apiKey,\n taskId,\n },\n {\n headers: { \"Content-Type\": \"application/json\" },\n timeout: 30000,\n }\n );\n\n if (response.data.errorId !== 0) {\n throw new Error(`CapSolver error: ${response.data.errorDescription ?? \"Unknown error\"}`);\n }\n\n if (response.data.status === \"ready\") {\n logger.info(\"CapSolver task completed successfully\");\n return response.data.solution;\n }\n\n await new Promise((resolve) => setTimeout(resolve, this.pollingInterval));\n attempts++;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Error getting CapSolver task result: ${errorMessage}`);\n throw error;\n }\n }\n\n throw new Error(\"CapSolver task timeout\");\n }\n\n async solveTurnstile(\n websiteURL: string,\n websiteKey: string,\n proxy?: string,\n userAgent?: string\n ): Promise<string> {\n logger.info(\"Solving Cloudflare Turnstile captcha\");\n\n const task: CaptchaTask = {\n type: proxy ? \"AntiTurnstileTask\" : \"AntiTurnstileTaskProxyLess\",\n websiteURL,\n websiteKey,\n };\n\n if (proxy) {\n const proxyParts = proxy.split(\":\");\n task.proxy = `${proxyParts[0]}:${proxyParts[1]}`;\n if (proxyParts.length > 2) {\n task.proxyLogin = proxyParts[2];\n task.proxyPassword = proxyParts[3];\n }\n }\n\n if (userAgent) {\n task.userAgent = userAgent;\n }\n\n const taskId = await this.createTask(task);\n const solution = await this.getTaskResult(taskId);\n\n return solution.token ?? \"\";\n }\n\n async solveRecaptchaV2(\n websiteURL: string,\n websiteKey: string,\n isInvisible = false,\n proxy?: string\n ): Promise<string> {\n logger.info(\"Solving reCAPTCHA v2\");\n\n const task: CaptchaTask = {\n type: proxy ? \"RecaptchaV2Task\" : \"RecaptchaV2TaskProxyless\",\n websiteURL,\n websiteKey,\n isInvisible,\n };\n\n if (proxy) {\n const proxyParts = proxy.split(\":\");\n task.proxy = `${proxyParts[0]}:${proxyParts[1]}`;\n if (proxyParts.length > 2) {\n task.proxyLogin = proxyParts[2];\n task.proxyPassword = proxyParts[3];\n }\n }\n\n const taskId = await this.createTask(task);\n const solution = await this.getTaskResult(taskId);\n\n return solution.gRecaptchaResponse ?? \"\";\n }\n\n async solveRecaptchaV3(\n websiteURL: string,\n websiteKey: string,\n pageAction: string,\n minScore = 0.7,\n proxy?: string\n ): Promise<string> {\n logger.info(\"Solving reCAPTCHA v3\");\n\n const task: CaptchaTask = {\n type: proxy ? \"RecaptchaV3Task\" : \"RecaptchaV3TaskProxyless\",\n websiteURL,\n websiteKey,\n pageAction,\n minScore,\n };\n\n if (proxy) {\n const proxyParts = proxy.split(\":\");\n task.proxy = `${proxyParts[0]}:${proxyParts[1]}`;\n if (proxyParts.length > 2) {\n task.proxyLogin = proxyParts[2];\n task.proxyPassword = proxyParts[3];\n }\n }\n\n const taskId = await this.createTask(task);\n const solution = await this.getTaskResult(taskId);\n\n return solution.gRecaptchaResponse ?? \"\";\n }\n\n async solveHCaptcha(websiteURL: string, websiteKey: string, proxy?: string): Promise<string> {\n logger.info(\"Solving hCaptcha\");\n\n const task: CaptchaTask = {\n type: proxy ? \"HCaptchaTask\" : \"HCaptchaTaskProxyless\",\n websiteURL,\n websiteKey,\n };\n\n if (proxy) {\n const proxyParts = proxy.split(\":\");\n task.proxy = `${proxyParts[0]}:${proxyParts[1]}`;\n if (proxyParts.length > 2) {\n task.proxyLogin = proxyParts[2];\n task.proxyPassword = proxyParts[3];\n }\n }\n\n const taskId = await this.createTask(task);\n const solution = await this.getTaskResult(taskId);\n\n return solution.token ?? \"\";\n }\n}\n\nexport async function detectCaptchaType(page: {\n $: (selector: string) => Promise<Element | null>;\n evaluate: <T>(fn: () => T) => Promise<T>;\n}): Promise<{\n type: CaptchaType;\n siteKey?: string;\n}> {\n try {\n const turnstileElement = await page.$(\"[data-sitekey]\");\n if (turnstileElement) {\n const cfTurnstile = await page.$(\".cf-turnstile\");\n if (cfTurnstile) {\n return { type: \"turnstile\" };\n }\n }\n\n const recaptchaElement = await page.$(\"[data-sitekey], .g-recaptcha\");\n if (recaptchaElement) {\n const isV3 = await page.evaluate(() => {\n const grecaptcha = (\n globalThis as typeof globalThis & {\n grecaptcha?: { execute?: () => void };\n }\n ).grecaptcha;\n return typeof grecaptcha?.execute === \"function\";\n });\n return { type: isV3 ? \"recaptcha-v3\" : \"recaptcha-v2\" };\n }\n\n const hcaptchaElement = await page.$(\"[data-sitekey].h-captcha, [data-hcaptcha-sitekey]\");\n if (hcaptchaElement) {\n return { type: \"hcaptcha\" };\n }\n\n return { type: \"none\" };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Error detecting CAPTCHA type: ${errorMessage}`);\n return { type: \"none\" };\n }\n}\n\nexport async function injectCaptchaSolution(\n page: { evaluate: <T>(fn: (token: string) => T, token: string) => Promise<T> },\n captchaType: CaptchaType,\n solution: string\n): Promise<void> {\n switch (captchaType) {\n case \"turnstile\":\n await page.evaluate((token: string) => {\n const doc = globalThis as typeof globalThis & {\n document: Document;\n turnstileCallback?: (token: string) => void;\n };\n const textarea = doc.document.querySelector(\n '[name=\"cf-turnstile-response\"]'\n ) as HTMLTextAreaElement | null;\n if (textarea) {\n textarea.value = token;\n }\n doc.turnstileCallback?.(token);\n }, solution);\n break;\n\n case \"recaptcha-v2\":\n case \"recaptcha-v3\":\n await page.evaluate((token: string) => {\n const doc = globalThis as typeof globalThis & {\n document: Document;\n onRecaptchaSuccess?: (token: string) => void;\n };\n const textarea = doc.document.querySelector(\n '[name=\"g-recaptcha-response\"]'\n ) as HTMLTextAreaElement | null;\n if (textarea) {\n textarea.value = token;\n (textarea as HTMLElement).style.display = \"block\";\n }\n doc.onRecaptchaSuccess?.(token);\n }, solution);\n break;\n\n case \"hcaptcha\":\n await page.evaluate((token: string) => {\n const doc = globalThis as typeof globalThis & {\n document: Document;\n hcaptchaCallback?: (token: string) => void;\n };\n const textarea = doc.document.querySelector(\n '[name=\"h-captcha-response\"]'\n ) as HTMLTextAreaElement | null;\n if (textarea) {\n textarea.value = token;\n }\n const input = doc.document.querySelector(\n '[name=\"g-recaptcha-response\"]'\n ) as HTMLInputElement | null;\n if (input) {\n input.value = token;\n }\n doc.hcaptchaCallback?.(token);\n }, solution);\n break;\n }\n}\n"]}
@@ -0,0 +1,37 @@
1
+ export type ErrorCode = "SERVICE_NOT_AVAILABLE" | "SESSION_ERROR" | "NAVIGATION_ERROR" | "ACTION_ERROR" | "SECURITY_ERROR" | "CAPTCHA_ERROR" | "TIMEOUT_ERROR" | "NO_URL_FOUND";
2
+ export declare class BrowserError extends Error {
3
+ readonly code: ErrorCode;
4
+ readonly userMessage: string;
5
+ readonly recoverable: boolean;
6
+ readonly details?: Record<string, unknown>;
7
+ constructor(message: string, code: ErrorCode, userMessage: string, recoverable?: boolean, details?: Record<string, unknown>);
8
+ }
9
+ export declare class ServiceNotAvailableError extends BrowserError {
10
+ constructor();
11
+ }
12
+ export declare class SessionError extends BrowserError {
13
+ constructor(message: string, details?: Record<string, unknown>);
14
+ }
15
+ export declare class NavigationError extends BrowserError {
16
+ constructor(url: string, originalError?: Error);
17
+ }
18
+ export declare class ActionError extends BrowserError {
19
+ constructor(action: string, target: string, originalError?: Error);
20
+ }
21
+ export declare class SecurityError extends BrowserError {
22
+ constructor(message: string, details?: Record<string, unknown>);
23
+ }
24
+ export declare class CaptchaError extends BrowserError {
25
+ constructor(message: string, details?: Record<string, unknown>);
26
+ }
27
+ export declare class TimeoutError extends BrowserError {
28
+ constructor(operation: string, timeoutMs: number);
29
+ }
30
+ export declare class NoUrlFoundError extends BrowserError {
31
+ constructor();
32
+ }
33
+ export declare function handleBrowserError(error: Error | BrowserError, callback?: (content: {
34
+ text: string;
35
+ error?: boolean;
36
+ }) => Promise<unknown>, action?: string): void;
37
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GACjB,uBAAuB,GACvB,eAAe,GACf,kBAAkB,GAClB,cAAc,GACd,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,cAAc,CAAC;AAEnB,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAgB,IAAI,EAAE,SAAS,CAAC;IAChC,SAAgB,WAAW,EAAE,MAAM,CAAC;IACpC,SAAgB,WAAW,EAAE,OAAO,CAAC;IACrC,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGhD,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,OAAc,EAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CASpC;AAED,qBAAa,wBAAyB,SAAQ,YAAY;;CASzD;AAED,qBAAa,YAAa,SAAQ,YAAY;gBAChC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAS/D;AAED,qBAAa,eAAgB,SAAQ,YAAY;gBACnC,GAAG,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,KAAK;CAa/C;AAED,qBAAa,WAAY,SAAQ,YAAY;gBAC/B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,KAAK;CAalE;AAED,qBAAa,aAAc,SAAQ,YAAY;gBACjC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAS/D;AAED,qBAAa,YAAa,SAAQ,YAAY;gBAChC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAS/D;AAED,qBAAa,YAAa,SAAQ,YAAY;gBAChC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CASjD;AAED,qBAAa,eAAgB,SAAQ,YAAY;;CAShD;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,KAAK,GAAG,YAAY,EAC3B,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAC3E,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAiBN"}
@@ -0,0 +1,81 @@
1
+ import { logger } from "@elizaos/core";
2
+ export class BrowserError extends Error {
3
+ code;
4
+ userMessage;
5
+ recoverable;
6
+ details;
7
+ constructor(message, code, userMessage, recoverable = true, details) {
8
+ super(message);
9
+ this.name = "BrowserError";
10
+ this.code = code;
11
+ this.userMessage = userMessage;
12
+ this.recoverable = recoverable;
13
+ this.details = details;
14
+ }
15
+ }
16
+ export class ServiceNotAvailableError extends BrowserError {
17
+ constructor() {
18
+ super("Browser service is not available", "SERVICE_NOT_AVAILABLE", "The browser automation service is not available. Please ensure the plugin is properly configured.", false);
19
+ }
20
+ }
21
+ export class SessionError extends BrowserError {
22
+ constructor(message, details) {
23
+ super(message, "SESSION_ERROR", "There was an error with the browser session. Please try again.", true, details);
24
+ }
25
+ }
26
+ export class NavigationError extends BrowserError {
27
+ constructor(url, originalError) {
28
+ const message = originalError
29
+ ? `Failed to navigate to ${url}: ${originalError.message}`
30
+ : `Failed to navigate to ${url}`;
31
+ super(message, "NAVIGATION_ERROR", "I couldn't navigate to the requested page. Please check the URL and try again.", true, { url, originalError: originalError?.message });
32
+ }
33
+ }
34
+ export class ActionError extends BrowserError {
35
+ constructor(action, target, originalError) {
36
+ const message = originalError
37
+ ? `Failed to ${action} on ${target}: ${originalError.message}`
38
+ : `Failed to ${action} on ${target}`;
39
+ super(message, "ACTION_ERROR", `I couldn't ${action} on the requested element. Please check if the element exists and try again.`, true, { action, target, originalError: originalError?.message });
40
+ }
41
+ }
42
+ export class SecurityError extends BrowserError {
43
+ constructor(message, details) {
44
+ super(message, "SECURITY_ERROR", "This action was blocked for security reasons.", false, details);
45
+ }
46
+ }
47
+ export class CaptchaError extends BrowserError {
48
+ constructor(message, details) {
49
+ super(message, "CAPTCHA_ERROR", "Failed to solve the CAPTCHA. Please try again.", true, details);
50
+ }
51
+ }
52
+ export class TimeoutError extends BrowserError {
53
+ constructor(operation, timeoutMs) {
54
+ super(`${operation} timed out after ${timeoutMs}ms`, "TIMEOUT_ERROR", `The operation timed out. Please try again.`, true, { operation, timeoutMs });
55
+ }
56
+ }
57
+ export class NoUrlFoundError extends BrowserError {
58
+ constructor() {
59
+ super("No URL found in message", "NO_URL_FOUND", "I couldn't find a URL in your request. Please provide a valid URL to navigate to.", false);
60
+ }
61
+ }
62
+ export function handleBrowserError(error, callback, action) {
63
+ if (error instanceof BrowserError) {
64
+ logger.error(`Browser error [${error.code}]:`, error.message);
65
+ void callback?.({
66
+ text: error.userMessage,
67
+ error: true,
68
+ });
69
+ }
70
+ else {
71
+ const errorMessage = error instanceof Error ? error.message : String(error);
72
+ logger.error(`Unexpected browser error: ${errorMessage}`);
73
+ void callback?.({
74
+ text: action
75
+ ? `I encountered an error while trying to ${action}. Please try again.`
76
+ : "I encountered an unexpected error. Please try again.",
77
+ error: true,
78
+ });
79
+ }
80
+ }
81
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger } from \"@elizaos/core\";\n\nexport type ErrorCode =\n | \"SERVICE_NOT_AVAILABLE\"\n | \"SESSION_ERROR\"\n | \"NAVIGATION_ERROR\"\n | \"ACTION_ERROR\"\n | \"SECURITY_ERROR\"\n | \"CAPTCHA_ERROR\"\n | \"TIMEOUT_ERROR\"\n | \"NO_URL_FOUND\";\n\nexport class BrowserError extends Error {\n public readonly code: ErrorCode;\n public readonly userMessage: string;\n public readonly recoverable: boolean;\n public readonly details?: Record<string, unknown>;\n\n constructor(\n message: string,\n code: ErrorCode,\n userMessage: string,\n recoverable: boolean = true,\n details?: Record<string, unknown>\n ) {\n super(message);\n this.name = \"BrowserError\";\n this.code = code;\n this.userMessage = userMessage;\n this.recoverable = recoverable;\n this.details = details;\n }\n}\n\nexport class ServiceNotAvailableError extends BrowserError {\n constructor() {\n super(\n \"Browser service is not available\",\n \"SERVICE_NOT_AVAILABLE\",\n \"The browser automation service is not available. Please ensure the plugin is properly configured.\",\n false\n );\n }\n}\n\nexport class SessionError extends BrowserError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(\n message,\n \"SESSION_ERROR\",\n \"There was an error with the browser session. Please try again.\",\n true,\n details\n );\n }\n}\n\nexport class NavigationError extends BrowserError {\n constructor(url: string, originalError?: Error) {\n const message = originalError\n ? `Failed to navigate to ${url}: ${originalError.message}`\n : `Failed to navigate to ${url}`;\n\n super(\n message,\n \"NAVIGATION_ERROR\",\n \"I couldn't navigate to the requested page. Please check the URL and try again.\",\n true,\n { url, originalError: originalError?.message }\n );\n }\n}\n\nexport class ActionError extends BrowserError {\n constructor(action: string, target: string, originalError?: Error) {\n const message = originalError\n ? `Failed to ${action} on ${target}: ${originalError.message}`\n : `Failed to ${action} on ${target}`;\n\n super(\n message,\n \"ACTION_ERROR\",\n `I couldn't ${action} on the requested element. Please check if the element exists and try again.`,\n true,\n { action, target, originalError: originalError?.message }\n );\n }\n}\n\nexport class SecurityError extends BrowserError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(\n message,\n \"SECURITY_ERROR\",\n \"This action was blocked for security reasons.\",\n false,\n details\n );\n }\n}\n\nexport class CaptchaError extends BrowserError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(\n message,\n \"CAPTCHA_ERROR\",\n \"Failed to solve the CAPTCHA. Please try again.\",\n true,\n details\n );\n }\n}\n\nexport class TimeoutError extends BrowserError {\n constructor(operation: string, timeoutMs: number) {\n super(\n `${operation} timed out after ${timeoutMs}ms`,\n \"TIMEOUT_ERROR\",\n `The operation timed out. Please try again.`,\n true,\n { operation, timeoutMs }\n );\n }\n}\n\nexport class NoUrlFoundError extends BrowserError {\n constructor() {\n super(\n \"No URL found in message\",\n \"NO_URL_FOUND\",\n \"I couldn't find a URL in your request. Please provide a valid URL to navigate to.\",\n false\n );\n }\n}\n\nexport function handleBrowserError(\n error: Error | BrowserError,\n callback?: (content: { text: string; error?: boolean }) => Promise<unknown>,\n action?: string\n): void {\n if (error instanceof BrowserError) {\n logger.error(`Browser error [${error.code}]:`, error.message);\n void callback?.({\n text: error.userMessage,\n error: true,\n });\n } else {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Unexpected browser error: ${errorMessage}`);\n void callback?.({\n text: action\n ? `I encountered an error while trying to ${action}. Please try again.`\n : \"I encountered an unexpected error. Please try again.\",\n error: true,\n });\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export * from "./errors.js";
2
+ export * from "./retry.js";
3
+ export * from "./security.js";
4
+ export * from "./url.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from "./errors.js";
2
+ export * from "./retry.js";
3
+ export * from "./security.js";
4
+ export * from "./url.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC","sourcesContent":["export * from \"./errors.js\";\nexport * from \"./retry.js\";\nexport * from \"./security.js\";\nexport * from \"./url.js\";\n"]}
@@ -0,0 +1,26 @@
1
+ import type { RetryConfig } from "../types.js";
2
+ export declare const DEFAULT_RETRY_CONFIGS: {
3
+ navigation: {
4
+ maxAttempts: number;
5
+ initialDelayMs: number;
6
+ maxDelayMs: number;
7
+ backoffMultiplier: number;
8
+ };
9
+ action: {
10
+ maxAttempts: number;
11
+ initialDelayMs: number;
12
+ maxDelayMs: number;
13
+ backoffMultiplier: number;
14
+ };
15
+ extraction: {
16
+ maxAttempts: number;
17
+ initialDelayMs: number;
18
+ maxDelayMs: number;
19
+ backoffMultiplier: number;
20
+ };
21
+ };
22
+ export declare function retryWithBackoff<T>(fn: () => Promise<T>, config: Partial<RetryConfig> & {
23
+ timeout?: number;
24
+ }, operation: string): Promise<T>;
25
+ export declare function sleep(ms: number): Promise<void>;
26
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;CAmBK,CAAC;AAExC,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EACnD,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,CAAC,CAAC,CAuCZ;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C"}
@@ -0,0 +1,55 @@
1
+ import { logger } from "@elizaos/core";
2
+ export const DEFAULT_RETRY_CONFIGS = {
3
+ navigation: {
4
+ maxAttempts: 3,
5
+ initialDelayMs: 1000,
6
+ maxDelayMs: 5000,
7
+ backoffMultiplier: 2,
8
+ },
9
+ action: {
10
+ maxAttempts: 2,
11
+ initialDelayMs: 500,
12
+ maxDelayMs: 2000,
13
+ backoffMultiplier: 1.5,
14
+ },
15
+ extraction: {
16
+ maxAttempts: 2,
17
+ initialDelayMs: 500,
18
+ maxDelayMs: 3000,
19
+ backoffMultiplier: 2,
20
+ },
21
+ };
22
+ export async function retryWithBackoff(fn, config, operation) {
23
+ const maxAttempts = config.maxAttempts ?? 3;
24
+ const initialDelay = config.initialDelayMs ?? 1000;
25
+ const maxDelay = config.maxDelayMs ?? 5000;
26
+ const backoffMultiplier = config.backoffMultiplier ?? 2;
27
+ let lastError;
28
+ let delay = initialDelay;
29
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
30
+ try {
31
+ logger.info(`Attempting ${operation} (attempt ${attempt}/${maxAttempts})`);
32
+ if (config.timeout) {
33
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`${operation} timed out after ${config.timeout}ms`)), config.timeout));
34
+ return await Promise.race([fn(), timeoutPromise]);
35
+ }
36
+ return await fn();
37
+ }
38
+ catch (error) {
39
+ lastError = error;
40
+ const errorMessage = error instanceof Error ? error.message : String(error);
41
+ logger.warn(`${operation} failed (attempt ${attempt}/${maxAttempts}): ${errorMessage}`);
42
+ if (attempt < maxAttempts) {
43
+ logger.info(`Retrying ${operation} in ${delay}ms...`);
44
+ await new Promise((resolve) => setTimeout(resolve, delay));
45
+ delay = Math.min(delay * backoffMultiplier, maxDelay);
46
+ }
47
+ }
48
+ }
49
+ logger.error(`${operation} failed after ${maxAttempts} attempts`);
50
+ throw lastError ?? new Error(`${operation} failed after ${maxAttempts} attempts`);
51
+ }
52
+ export function sleep(ms) {
53
+ return new Promise((resolve) => setTimeout(resolve, ms));
54
+ }
55
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger } from \"@elizaos/core\";\nimport type { RetryConfig } from \"../types.js\";\n\nexport const DEFAULT_RETRY_CONFIGS = {\n navigation: {\n maxAttempts: 3,\n initialDelayMs: 1000,\n maxDelayMs: 5000,\n backoffMultiplier: 2,\n },\n action: {\n maxAttempts: 2,\n initialDelayMs: 500,\n maxDelayMs: 2000,\n backoffMultiplier: 1.5,\n },\n extraction: {\n maxAttempts: 2,\n initialDelayMs: 500,\n maxDelayMs: 3000,\n backoffMultiplier: 2,\n },\n} satisfies Record<string, RetryConfig>;\n\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n config: Partial<RetryConfig> & { timeout?: number },\n operation: string\n): Promise<T> {\n const maxAttempts = config.maxAttempts ?? 3;\n const initialDelay = config.initialDelayMs ?? 1000;\n const maxDelay = config.maxDelayMs ?? 5000;\n const backoffMultiplier = config.backoffMultiplier ?? 2;\n\n let lastError: Error | undefined;\n let delay = initialDelay;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n logger.info(`Attempting ${operation} (attempt ${attempt}/${maxAttempts})`);\n\n if (config.timeout) {\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`${operation} timed out after ${config.timeout}ms`)),\n config.timeout\n )\n );\n return await Promise.race([fn(), timeoutPromise]);\n }\n\n return await fn();\n } catch (error) {\n lastError = error as Error;\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.warn(`${operation} failed (attempt ${attempt}/${maxAttempts}): ${errorMessage}`);\n\n if (attempt < maxAttempts) {\n logger.info(`Retrying ${operation} in ${delay}ms...`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n delay = Math.min(delay * backoffMultiplier, maxDelay);\n }\n }\n }\n\n logger.error(`${operation} failed after ${maxAttempts} attempts`);\n throw lastError ?? new Error(`${operation} failed after ${maxAttempts} attempts`);\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import type { RateLimitConfig, SecurityConfig } from "../types.js";
2
+ export declare class UrlValidator {
3
+ private config;
4
+ constructor(config?: Partial<SecurityConfig>);
5
+ validate(url: string): {
6
+ valid: boolean;
7
+ sanitized?: string;
8
+ error?: string;
9
+ };
10
+ updateConfig(config: Partial<SecurityConfig>): void;
11
+ }
12
+ export declare const InputSanitizer: {
13
+ sanitizeText(input: string): string;
14
+ sanitizeSelector(selector: string): string;
15
+ sanitizeFilePath(path: string): string;
16
+ };
17
+ export declare function validateSecureAction(url: string | null, validator: UrlValidator): void;
18
+ export declare const defaultUrlValidator: UrlValidator;
19
+ export declare class RateLimiter {
20
+ private config;
21
+ private actionCounts;
22
+ private sessionCounts;
23
+ constructor(config: RateLimitConfig);
24
+ checkActionLimit(userId: string): boolean;
25
+ checkSessionLimit(userId: string): boolean;
26
+ }
27
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAkB,cAAc,EAAE,MAAM,aAAa,CAAC;AAWnF,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA2B;gBAE7B,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM;IAIhD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAuD7E,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;CAGpD;AAED,eAAO,MAAM,cAAc;wBACL,MAAM,GAAG,MAAM;+BAQR,MAAM,GAAG,MAAM;2BAInB,MAAM,GAAG,MAAM;CAMvC,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI,CAYtF;AAED,eAAO,MAAM,mBAAmB,cAAqB,CAAC;AAEtD,qBAAa,WAAW;IAIV,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,YAAY,CAAqC;IACzD,OAAO,CAAC,aAAa,CAAqC;gBAEtC,MAAM,EAAE,eAAe;IAE3C,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAoBzC,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;CAmB3C"}
@@ -0,0 +1,138 @@
1
+ import { SecurityError } from "./errors.js";
2
+ const DEFAULT_SECURITY_CONFIG = {
3
+ allowedDomains: [],
4
+ blockedDomains: ["malware.com", "phishing.com"],
5
+ maxUrlLength: 2048,
6
+ allowLocalhost: true,
7
+ allowFileProtocol: false,
8
+ };
9
+ export class UrlValidator {
10
+ config;
11
+ constructor(config = {}) {
12
+ this.config = { ...DEFAULT_SECURITY_CONFIG, ...config };
13
+ }
14
+ validate(url) {
15
+ try {
16
+ if (url.length > this.config.maxUrlLength) {
17
+ return { valid: false, error: "URL is too long" };
18
+ }
19
+ let parsedUrl;
20
+ try {
21
+ parsedUrl = new URL(url);
22
+ }
23
+ catch {
24
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
25
+ try {
26
+ parsedUrl = new URL(`https://${url}`);
27
+ }
28
+ catch {
29
+ return { valid: false, error: "Invalid URL format" };
30
+ }
31
+ }
32
+ else {
33
+ return { valid: false, error: "Invalid URL format" };
34
+ }
35
+ }
36
+ if (parsedUrl.protocol === "file:" && !this.config.allowFileProtocol) {
37
+ return { valid: false, error: "File protocol is not allowed" };
38
+ }
39
+ if (!["http:", "https:", "file:"].includes(parsedUrl.protocol)) {
40
+ return { valid: false, error: "Only HTTP(S) protocols are allowed" };
41
+ }
42
+ const isLocalhost = ["localhost", "127.0.0.1", "::1"].includes(parsedUrl.hostname);
43
+ if (isLocalhost && !this.config.allowLocalhost) {
44
+ return { valid: false, error: "Localhost URLs are not allowed" };
45
+ }
46
+ for (const blocked of this.config.blockedDomains) {
47
+ if (parsedUrl.hostname.includes(blocked)) {
48
+ return { valid: false, error: `Domain ${blocked} is blocked` };
49
+ }
50
+ }
51
+ if (this.config.allowedDomains.length > 0) {
52
+ const isAllowed = this.config.allowedDomains.some((allowed) => parsedUrl.hostname === allowed || parsedUrl.hostname.endsWith(`.${allowed}`));
53
+ if (!isAllowed) {
54
+ return { valid: false, error: "Domain is not in the allowed list" };
55
+ }
56
+ }
57
+ return { valid: true, sanitized: parsedUrl.href };
58
+ }
59
+ catch {
60
+ return { valid: false, error: "Error validating URL" };
61
+ }
62
+ }
63
+ updateConfig(config) {
64
+ this.config = { ...this.config, ...config };
65
+ }
66
+ }
67
+ export const InputSanitizer = {
68
+ sanitizeText(input) {
69
+ return input
70
+ .replace(/[<>]/g, "")
71
+ .replace(/javascript:/gi, "")
72
+ .replace(/on\w+\s*=/gi, "")
73
+ .trim();
74
+ },
75
+ sanitizeSelector(selector) {
76
+ return selector.replace(/['"]/g, "").replace(/[<>]/g, "").trim();
77
+ },
78
+ sanitizeFilePath(path) {
79
+ return path
80
+ .replace(/\.\./g, "")
81
+ .replace(/[<>:"|?*]/g, "")
82
+ .trim();
83
+ },
84
+ };
85
+ export function validateSecureAction(url, validator) {
86
+ if (!url) {
87
+ return;
88
+ }
89
+ const validation = validator.validate(url);
90
+ if (!validation.valid) {
91
+ throw new SecurityError(`URL validation failed: ${validation.error}`, {
92
+ url,
93
+ error: validation.error,
94
+ });
95
+ }
96
+ }
97
+ export const defaultUrlValidator = new UrlValidator();
98
+ export class RateLimiter {
99
+ config;
100
+ actionCounts = new Map();
101
+ sessionCounts = new Map();
102
+ constructor(config) {
103
+ this.config = config;
104
+ }
105
+ checkActionLimit(userId) {
106
+ const now = Date.now();
107
+ const userLimit = this.actionCounts.get(userId);
108
+ if (!userLimit || now > userLimit.resetTime) {
109
+ this.actionCounts.set(userId, {
110
+ count: 1,
111
+ resetTime: now + 60000,
112
+ });
113
+ return true;
114
+ }
115
+ if (userLimit.count >= this.config.maxActionsPerMinute) {
116
+ return false;
117
+ }
118
+ userLimit.count++;
119
+ return true;
120
+ }
121
+ checkSessionLimit(userId) {
122
+ const now = Date.now();
123
+ const userLimit = this.sessionCounts.get(userId);
124
+ if (!userLimit || now > userLimit.resetTime) {
125
+ this.sessionCounts.set(userId, {
126
+ count: 1,
127
+ resetTime: now + 3600000,
128
+ });
129
+ return true;
130
+ }
131
+ if (userLimit.count >= this.config.maxSessionsPerHour) {
132
+ return false;
133
+ }
134
+ userLimit.count++;
135
+ return true;
136
+ }
137
+ }
138
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RateLimitConfig, RateLimitEntry, SecurityConfig } from \"../types.js\";\nimport { SecurityError } from \"./errors.js\";\n\nconst DEFAULT_SECURITY_CONFIG: Required<SecurityConfig> = {\n allowedDomains: [],\n blockedDomains: [\"malware.com\", \"phishing.com\"],\n maxUrlLength: 2048,\n allowLocalhost: true,\n allowFileProtocol: false,\n};\n\nexport class UrlValidator {\n private config: Required<SecurityConfig>;\n\n constructor(config: Partial<SecurityConfig> = {}) {\n this.config = { ...DEFAULT_SECURITY_CONFIG, ...config };\n }\n\n validate(url: string): { valid: boolean; sanitized?: string; error?: string } {\n try {\n if (url.length > this.config.maxUrlLength) {\n return { valid: false, error: \"URL is too long\" };\n }\n\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(url);\n } catch {\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n try {\n parsedUrl = new URL(`https://${url}`);\n } catch {\n return { valid: false, error: \"Invalid URL format\" };\n }\n } else {\n return { valid: false, error: \"Invalid URL format\" };\n }\n }\n\n if (parsedUrl.protocol === \"file:\" && !this.config.allowFileProtocol) {\n return { valid: false, error: \"File protocol is not allowed\" };\n }\n\n if (![\"http:\", \"https:\", \"file:\"].includes(parsedUrl.protocol)) {\n return { valid: false, error: \"Only HTTP(S) protocols are allowed\" };\n }\n\n const isLocalhost = [\"localhost\", \"127.0.0.1\", \"::1\"].includes(parsedUrl.hostname);\n if (isLocalhost && !this.config.allowLocalhost) {\n return { valid: false, error: \"Localhost URLs are not allowed\" };\n }\n\n for (const blocked of this.config.blockedDomains) {\n if (parsedUrl.hostname.includes(blocked)) {\n return { valid: false, error: `Domain ${blocked} is blocked` };\n }\n }\n\n if (this.config.allowedDomains.length > 0) {\n const isAllowed = this.config.allowedDomains.some(\n (allowed) => parsedUrl.hostname === allowed || parsedUrl.hostname.endsWith(`.${allowed}`)\n );\n if (!isAllowed) {\n return { valid: false, error: \"Domain is not in the allowed list\" };\n }\n }\n\n return { valid: true, sanitized: parsedUrl.href };\n } catch {\n return { valid: false, error: \"Error validating URL\" };\n }\n }\n\n updateConfig(config: Partial<SecurityConfig>): void {\n this.config = { ...this.config, ...config };\n }\n}\n\nexport const InputSanitizer = {\n sanitizeText(input: string): string {\n return input\n .replace(/[<>]/g, \"\")\n .replace(/javascript:/gi, \"\")\n .replace(/on\\w+\\s*=/gi, \"\")\n .trim();\n },\n\n sanitizeSelector(selector: string): string {\n return selector.replace(/['\"]/g, \"\").replace(/[<>]/g, \"\").trim();\n },\n\n sanitizeFilePath(path: string): string {\n return path\n .replace(/\\.\\./g, \"\")\n .replace(/[<>:\"|?*]/g, \"\")\n .trim();\n },\n};\n\nexport function validateSecureAction(url: string | null, validator: UrlValidator): void {\n if (!url) {\n return;\n }\n\n const validation = validator.validate(url);\n if (!validation.valid) {\n throw new SecurityError(`URL validation failed: ${validation.error}`, {\n url,\n error: validation.error,\n });\n }\n}\n\nexport const defaultUrlValidator = new UrlValidator();\n\nexport class RateLimiter {\n private actionCounts = new Map<string, RateLimitEntry>();\n private sessionCounts = new Map<string, RateLimitEntry>();\n\n constructor(private config: RateLimitConfig) {}\n\n checkActionLimit(userId: string): boolean {\n const now = Date.now();\n const userLimit = this.actionCounts.get(userId);\n\n if (!userLimit || now > userLimit.resetTime) {\n this.actionCounts.set(userId, {\n count: 1,\n resetTime: now + 60000,\n });\n return true;\n }\n\n if (userLimit.count >= this.config.maxActionsPerMinute) {\n return false;\n }\n\n userLimit.count++;\n return true;\n }\n\n checkSessionLimit(userId: string): boolean {\n const now = Date.now();\n const userLimit = this.sessionCounts.get(userId);\n\n if (!userLimit || now > userLimit.resetTime) {\n this.sessionCounts.set(userId, {\n count: 1,\n resetTime: now + 3600000,\n });\n return true;\n }\n\n if (userLimit.count >= this.config.maxSessionsPerHour) {\n return false;\n }\n\n userLimit.count++;\n return true;\n }\n}\n"]}
@@ -0,0 +1,12 @@
1
+ export declare function extractUrl(text: string): string | null;
2
+ export declare function parseClickTarget(text: string): string;
3
+ export declare function parseTypeAction(text: string): {
4
+ text: string;
5
+ field: string;
6
+ };
7
+ export declare function parseSelectAction(text: string): {
8
+ option: string;
9
+ dropdown: string;
10
+ };
11
+ export declare function parseExtractInstruction(text: string): string;
12
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmBtD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAQ7E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAQpF;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5D"}
@@ -0,0 +1,38 @@
1
+ export function extractUrl(text) {
2
+ const quotedUrlMatch = text.match(/["']([^"']+)["']/);
3
+ if (quotedUrlMatch && (quotedUrlMatch[1].startsWith("http") || quotedUrlMatch[1].includes("."))) {
4
+ return quotedUrlMatch[1];
5
+ }
6
+ const urlMatch = text.match(/(https?:\/\/[^\s]+)/);
7
+ if (urlMatch) {
8
+ return urlMatch[1];
9
+ }
10
+ const domainMatch = text.match(/(?:go to|navigate to|open|visit)\s+([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\.[a-zA-Z]{2,})/i);
11
+ if (domainMatch) {
12
+ return `https://${domainMatch[1]}`;
13
+ }
14
+ return null;
15
+ }
16
+ export function parseClickTarget(text) {
17
+ const match = text.match(/click (?:on |the )?(.+)$/i);
18
+ return match ? match[1] : "element";
19
+ }
20
+ export function parseTypeAction(text) {
21
+ const textMatch = text.match(/["']([^"']+)["']/);
22
+ const textToType = textMatch ? textMatch[1] : "";
23
+ const fieldMatch = text.match(/(?:in|into) (?:the )?(.+)$/i);
24
+ const field = fieldMatch ? fieldMatch[1] : "input field";
25
+ return { text: textToType, field };
26
+ }
27
+ export function parseSelectAction(text) {
28
+ const optionMatch = text.match(/["']([^"']+)["']/);
29
+ const option = optionMatch ? optionMatch[1] : "";
30
+ const dropdownMatch = text.match(/from (?:the )?(.+)$/i);
31
+ const dropdown = dropdownMatch ? dropdownMatch[1] : "dropdown";
32
+ return { option, dropdown };
33
+ }
34
+ export function parseExtractInstruction(text) {
35
+ const match = text.match(/(?:extract|get|find|scrape|read) (?:the )?(.+?)(?:\s+from|\s*$)/i);
36
+ return match ? match[1] : text;
37
+ }
38
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtD,IAAI,cAAc,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAChG,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACnD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,+FAA+F,CAChG,CAAC;IACF,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,WAAW,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACrC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACtD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEjD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;IAEzD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEjD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAE/D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;IAC7F,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC","sourcesContent":["export function extractUrl(text: string): string | null {\n const quotedUrlMatch = text.match(/[\"']([^\"']+)[\"']/);\n if (quotedUrlMatch && (quotedUrlMatch[1].startsWith(\"http\") || quotedUrlMatch[1].includes(\".\"))) {\n return quotedUrlMatch[1];\n }\n\n const urlMatch = text.match(/(https?:\\/\\/[^\\s]+)/);\n if (urlMatch) {\n return urlMatch[1];\n }\n\n const domainMatch = text.match(\n /(?:go to|navigate to|open|visit)\\s+([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\\.[a-zA-Z]{2,})/i\n );\n if (domainMatch) {\n return `https://${domainMatch[1]}`;\n }\n\n return null;\n}\n\nexport function parseClickTarget(text: string): string {\n const match = text.match(/click (?:on |the )?(.+)$/i);\n return match ? match[1] : \"element\";\n}\n\nexport function parseTypeAction(text: string): { text: string; field: string } {\n const textMatch = text.match(/[\"']([^\"']+)[\"']/);\n const textToType = textMatch ? textMatch[1] : \"\";\n\n const fieldMatch = text.match(/(?:in|into) (?:the )?(.+)$/i);\n const field = fieldMatch ? fieldMatch[1] : \"input field\";\n\n return { text: textToType, field };\n}\n\nexport function parseSelectAction(text: string): { option: string; dropdown: string } {\n const optionMatch = text.match(/[\"']([^\"']+)[\"']/);\n const option = optionMatch ? optionMatch[1] : \"\";\n\n const dropdownMatch = text.match(/from (?:the )?(.+)$/i);\n const dropdown = dropdownMatch ? dropdownMatch[1] : \"dropdown\";\n\n return { option, dropdown };\n}\n\nexport function parseExtractInstruction(text: string): string {\n const match = text.match(/(?:extract|get|find|scrape|read) (?:the )?(.+?)(?:\\s+from|\\s*$)/i);\n return match ? match[1] : text;\n}\n"]}