@roxybrowser/playwright 2.0.2-beta.10 → 2.0.2-beta.13

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 (40) hide show
  1. package/dist/human/bubbleCursor.d.ts +2 -0
  2. package/dist/human/bubbleCursor.d.ts.map +1 -0
  3. package/dist/human/bubbleCursor.js +126 -0
  4. package/dist/human/bubbleCursor.js.map +1 -0
  5. package/dist/human/controller.d.ts +3 -0
  6. package/dist/human/controller.d.ts.map +1 -1
  7. package/dist/human/controller.js +41 -17
  8. package/dist/human/controller.js.map +1 -1
  9. package/dist/human/profile.d.ts.map +1 -1
  10. package/dist/human/profile.js +18 -22
  11. package/dist/human/profile.js.map +1 -1
  12. package/dist/human/types.d.ts +1 -1
  13. package/dist/human/types.d.ts.map +1 -1
  14. package/dist/locator.js +1 -1
  15. package/dist/locator.js.map +1 -1
  16. package/dist/mcp/backend/keyboard.d.ts +28 -0
  17. package/dist/mcp/backend/keyboard.d.ts.map +1 -1
  18. package/dist/mcp/backend/keyboard.js +9 -3
  19. package/dist/mcp/backend/keyboard.js.map +1 -1
  20. package/dist/mcp/connectedBrowser.d.ts.map +1 -1
  21. package/dist/mcp/connectedBrowser.js +83 -4
  22. package/dist/mcp/connectedBrowser.js.map +1 -1
  23. package/dist/mcp/runtime.d.ts +3 -1
  24. package/dist/mcp/runtime.d.ts.map +1 -1
  25. package/dist/mcp/runtime.js +6 -2
  26. package/dist/mcp/runtime.js.map +1 -1
  27. package/dist/mcp/tools/mouse.d.ts.map +1 -1
  28. package/dist/mcp/tools/mouse.js +5 -2
  29. package/dist/mcp/tools/mouse.js.map +1 -1
  30. package/dist/mcp/types.d.ts +5 -1
  31. package/dist/mcp/types.d.ts.map +1 -1
  32. package/dist/protocol/bidi/backend.d.ts.map +1 -1
  33. package/dist/protocol/bidi/backend.js +10 -3
  34. package/dist/protocol/bidi/backend.js.map +1 -1
  35. package/dist/protocol/cdp/backend.d.ts.map +1 -1
  36. package/dist/protocol/cdp/backend.js +8 -3
  37. package/dist/protocol/cdp/backend.js.map +1 -1
  38. package/dist/types/options.d.ts +0 -1
  39. package/dist/types/options.d.ts.map +1 -1
  40. package/package.json +1 -1
@@ -1,10 +1,14 @@
1
1
  import { z } from "zod";
2
2
  import { defineTabTool } from "./tool.js";
3
3
  import { elementSchema } from "./snapshot.js";
4
+ const humanSchema = z.object({
5
+ profile: z.enum(["cautious", "balanced", "fast"]).optional().describe("Humanization timing profile, defaults to balanced")
6
+ }).optional();
4
7
  const typeSchema = elementSchema.extend({
5
8
  text: z.string().describe("Text to type into the element"),
6
9
  submit: z.boolean().optional().describe("Whether to submit entered text (press Enter after)"),
7
- slowly: z.boolean().optional().describe("Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.")
10
+ slowly: z.boolean().optional().describe("Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once."),
11
+ human: humanSchema.describe("Humanization settings for this typing action")
8
12
  });
9
13
  export const press = defineTabTool({
10
14
  capability: "core-input",
@@ -13,7 +17,8 @@ export const press = defineTabTool({
13
17
  title: "Press a key",
14
18
  description: "Press a key on the keyboard",
15
19
  inputSchema: z.object({
16
- key: z.string().describe("Key to press, e.g. Enter, Escape, Tab, ArrowLeft, Backspace, Delete, or printable characters")
20
+ key: z.string().describe("Key to press, e.g. Enter, Escape, Tab, ArrowLeft, Backspace, Delete, or printable characters"),
21
+ human: humanSchema.describe("Humanization settings for this key press")
17
22
  }),
18
23
  type: "input"
19
24
  },
@@ -22,7 +27,7 @@ export const press = defineTabTool({
22
27
  response.addTextResult(`Pressed key "${params.key}".`);
23
28
  response.addCode(`await page.keyboard.press(${JSON.stringify(params.key)});`);
24
29
  await tab.waitForCompletion(async () => {
25
- await tab.pressKey(params.key);
30
+ await tab.context.runtime.pressKey(params.key, undefined, params.human?.profile !== undefined ? { profile: params.human.profile } : undefined);
26
31
  });
27
32
  }
28
33
  });
@@ -55,6 +60,7 @@ export const type = defineTabTool({
55
60
  await locator.type(params.text, {
56
61
  ...(params.submit !== undefined ? { submit: params.submit } : {}),
57
62
  ...(params.slowly !== undefined ? { slowly: params.slowly } : {}),
63
+ ...(params.human !== undefined ? { human: params.human } : {}),
58
64
  ...tab.actionTimeoutOptions
59
65
  });
60
66
  });
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../../../src/mcp/backend/keyboard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../../../src/mcp/backend/keyboard.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"connectedBrowser.d.ts","sourceRoot":"","sources":["../../src/mcp/connectedBrowser.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAOV,uBAAuB,EACvB,sBAAsB,EAOvB,MAAM,YAAY,CAAC;AAy1GpB,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,uBAAuB,CAAC,CAMlC"}
1
+ {"version":3,"file":"connectedBrowser.d.ts","sourceRoot":"","sources":["../../src/mcp/connectedBrowser.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAOV,uBAAuB,EACvB,sBAAsB,EAQvB,MAAM,YAAY,CAAC;AAk8GpB,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,uBAAuB,CAAC,CAMlC"}
@@ -5,6 +5,7 @@ import { normalizeAriaSnapshotOptions, retryUntilReady } from "../ariaSnapshot.j
5
5
  import { PLAYWRIGHT_ARIA_SNAPSHOT_EVALUATE_SOURCE as ARIA_SNAPSHOT_EVALUATE_SOURCE } from "../vendor/playwright/ariaSnapshotEvaluate.js";
6
6
  import { getBidiClientFactory } from "../protocol/bidi/client.js";
7
7
  import { parseSerializedEvaluationResult, wrapWithSerializedEvaluationResult } from "../protocol/evaluationSerializer.js";
8
+ import { BUBBLE_CURSOR_INSTALL_SOURCE } from "../human/bubbleCursor.js";
8
9
  import { McpToolError } from "./errors.js";
9
10
  import { ACTION_POINT_EVALUATE_SOURCE, ACTION_POINT_BY_SELECTOR_SOURCE } from "./snapshot.js";
10
11
  import { configuredTempDir } from "./output.js";
@@ -214,6 +215,7 @@ const SCROLL_ELEMENT_SOURCE = String.raw `(payload) => {
214
215
  target.scrollBy({ left: payload.deltaX, top: payload.deltaY, behavior: 'instant' });
215
216
  return { ok: true };
216
217
  }`;
218
+ const ENSURE_BUBBLE_CURSOR_SOURCE = BUBBLE_CURSOR_INSTALL_SOURCE;
217
219
  const GET_ELEMENT_OBJECT_SOURCE = String.raw `(payload) => {
218
220
  const state = globalThis.__roxyMcpState;
219
221
  return payload.nodeToken
@@ -406,6 +408,45 @@ async function evaluateBiDiRef(client, contextId, functionSource, arg) {
406
408
  ...(response.result?.value?.handle !== undefined ? { handle: response.result.value.handle } : {})
407
409
  };
408
410
  }
411
+ async function splitScrollDeltas(deltaX, deltaY, stepPx) {
412
+ const dominantDistance = Math.max(Math.abs(deltaX), Math.abs(deltaY));
413
+ if (dominantDistance === 0) {
414
+ return [];
415
+ }
416
+ const steps = Math.max(1, Math.ceil(dominantDistance / Math.max(1, stepPx)));
417
+ const chunks = [];
418
+ let appliedX = 0;
419
+ let appliedY = 0;
420
+ for (let index = 0; index < steps; index += 1) {
421
+ const nextAppliedX = Math.round((deltaX * (index + 1)) / steps);
422
+ const nextAppliedY = Math.round((deltaY * (index + 1)) / steps);
423
+ chunks.push({
424
+ deltaX: nextAppliedX - appliedX,
425
+ deltaY: nextAppliedY - appliedY
426
+ });
427
+ appliedX = nextAppliedX;
428
+ appliedY = nextAppliedY;
429
+ }
430
+ return chunks.filter((chunk) => chunk.deltaX !== 0 || chunk.deltaY !== 0);
431
+ }
432
+ function maybeReverseScrollChunk(chunk, index, total) {
433
+ if (total < 3 || index === 0 || index === total - 1) {
434
+ return null;
435
+ }
436
+ if (Math.random() > 0.18) {
437
+ return null;
438
+ }
439
+ return {
440
+ deltaX: -Math.round(chunk.deltaX * (0.18 + Math.random() * 0.18)),
441
+ deltaY: -Math.round(chunk.deltaY * (0.18 + Math.random() * 0.18))
442
+ };
443
+ }
444
+ function shouldPauseToObserve(index, total) {
445
+ if (index === total - 1) {
446
+ return false;
447
+ }
448
+ return total > 2 && Math.random() < 0.22;
449
+ }
409
450
  function extractBiDiValue(value) {
410
451
  if (!value) {
411
452
  return undefined;
@@ -785,11 +826,26 @@ class CdpConnectedBrowserSession {
785
826
  deviceScaleFactor: 1
786
827
  });
787
828
  }
788
- async scroll(target, deltaX, deltaY) {
829
+ async scroll(target, deltaX, deltaY, options) {
789
830
  const pageClient = await this.getActivePageClient();
790
831
  const contextId = await this.getActiveUtilityContextId(pageClient);
791
832
  const arg = target ? this.targetArg(target) : {};
792
- await evaluateCdp(pageClient, SCROLL_ELEMENT_SOURCE, { ...arg, deltaX, deltaY }, contextId);
833
+ await evaluateCdp(pageClient, ENSURE_BUBBLE_CURSOR_SOURCE, undefined, contextId).catch(() => false);
834
+ const chunks = await splitScrollDeltas(deltaX, deltaY, options?.stepPx ?? Math.max(Math.abs(deltaX), Math.abs(deltaY), 1));
835
+ for (const [index, chunk] of chunks.entries()) {
836
+ await evaluateCdp(pageClient, SCROLL_ELEMENT_SOURCE, { ...arg, deltaX: chunk.deltaX, deltaY: chunk.deltaY }, contextId);
837
+ const reverseChunk = maybeReverseScrollChunk(chunk, index, chunks.length);
838
+ if (reverseChunk) {
839
+ await delay(60 + Math.round(Math.random() * 120));
840
+ await evaluateCdp(pageClient, SCROLL_ELEMENT_SOURCE, { ...arg, deltaX: reverseChunk.deltaX, deltaY: reverseChunk.deltaY }, contextId);
841
+ }
842
+ if (shouldPauseToObserve(index, chunks.length)) {
843
+ await delay(220 + Math.round(Math.random() * 520));
844
+ }
845
+ if ((options?.stepDelayMs ?? 0) > 0) {
846
+ await delay(options.stepDelayMs);
847
+ }
848
+ }
793
849
  }
794
850
  async screenshot(options = {}) {
795
851
  const pageClient = await this.getActivePageClient();
@@ -2032,10 +2088,33 @@ class BidiConnectedBrowserSession {
2032
2088
  viewport: { width, height }
2033
2089
  });
2034
2090
  }
2035
- async scroll(target, deltaX, deltaY) {
2091
+ async scroll(target, deltaX, deltaY, options) {
2036
2092
  const tabId = await this.getActiveTabId();
2037
2093
  const arg = target ? ("nodeToken" in target ? { nodeToken: target.nodeToken } : { selector: target.selector }) : {};
2038
- await evaluateBiDi(this.client, tabId, SCROLL_ELEMENT_SOURCE, { ...arg, deltaX, deltaY });
2094
+ await evaluateBiDi(this.client, tabId, ENSURE_BUBBLE_CURSOR_SOURCE).catch(() => false);
2095
+ const chunks = await splitScrollDeltas(deltaX, deltaY, options?.stepPx ?? Math.max(Math.abs(deltaX), Math.abs(deltaY), 1));
2096
+ for (const [index, chunk] of chunks.entries()) {
2097
+ await evaluateBiDi(this.client, tabId, SCROLL_ELEMENT_SOURCE, {
2098
+ ...arg,
2099
+ deltaX: chunk.deltaX,
2100
+ deltaY: chunk.deltaY
2101
+ });
2102
+ const reverseChunk = maybeReverseScrollChunk(chunk, index, chunks.length);
2103
+ if (reverseChunk) {
2104
+ await delay(60 + Math.round(Math.random() * 120));
2105
+ await evaluateBiDi(this.client, tabId, SCROLL_ELEMENT_SOURCE, {
2106
+ ...arg,
2107
+ deltaX: reverseChunk.deltaX,
2108
+ deltaY: reverseChunk.deltaY
2109
+ });
2110
+ }
2111
+ if (shouldPauseToObserve(index, chunks.length)) {
2112
+ await delay(220 + Math.round(Math.random() * 520));
2113
+ }
2114
+ if ((options?.stepDelayMs ?? 0) > 0) {
2115
+ await delay(options.stepDelayMs);
2116
+ }
2117
+ }
2039
2118
  }
2040
2119
  async screenshot(options = {}) {
2041
2120
  const tabId = await this.getActiveTabId();