@humanjs/playwright 0.1.0
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/LICENSE +21 -0
- package/README.md +35 -0
- package/dist/index.cjs +78 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +56 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gonzalo Muñoz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# @humanjs/playwright
|
|
2
|
+
|
|
3
|
+
Humanize Playwright sessions for AI agents, QA tests, and demos. Drop-in adapter for an existing Playwright `Page`.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @humanjs/playwright playwright
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`playwright` is a peer dependency — bring your own version.
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { chromium } from 'playwright';
|
|
17
|
+
import { createHuman } from '@humanjs/playwright';
|
|
18
|
+
|
|
19
|
+
const browser = await chromium.launch();
|
|
20
|
+
const page = await browser.newPage();
|
|
21
|
+
|
|
22
|
+
const human = await createHuman(page, {
|
|
23
|
+
personality: 'careful', // careful | fast | distracted | precise
|
|
24
|
+
seed: 'session-42', // deterministic for tests
|
|
25
|
+
speed: 'human', // human | fast | instant
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
await human.goto('https://example.com');
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
See [humanjs.dev](https://humanjs.dev) for full documentation.
|
|
32
|
+
|
|
33
|
+
## License
|
|
34
|
+
|
|
35
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@humanjs/core');
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
6
|
+
async function createHuman(page, options = {}) {
|
|
7
|
+
const personality = core.resolvePersonality(options.personality ?? "careful");
|
|
8
|
+
const rng = core.createRng(options.seed);
|
|
9
|
+
const speed = options.speed ?? "human";
|
|
10
|
+
const plugins = options.plugins ?? [];
|
|
11
|
+
const context = { personality, rng };
|
|
12
|
+
for (const plugin of plugins) {
|
|
13
|
+
await plugin.install?.(context);
|
|
14
|
+
}
|
|
15
|
+
async function performAction(action, actionFn) {
|
|
16
|
+
for (const plugin of plugins) {
|
|
17
|
+
await plugin.beforeAction?.(action);
|
|
18
|
+
}
|
|
19
|
+
const startedAt = Date.now();
|
|
20
|
+
try {
|
|
21
|
+
const value = await actionFn();
|
|
22
|
+
const result = {
|
|
23
|
+
type: action.type,
|
|
24
|
+
durationMs: Date.now() - startedAt
|
|
25
|
+
};
|
|
26
|
+
for (const plugin of plugins) {
|
|
27
|
+
await plugin.afterAction?.(action, result);
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
for (const plugin of plugins) {
|
|
32
|
+
await plugin.onError?.(action, error);
|
|
33
|
+
}
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
personality,
|
|
39
|
+
speed,
|
|
40
|
+
async goto(url) {
|
|
41
|
+
await performAction({ type: "goto", params: { url } }, async () => {
|
|
42
|
+
await page.goto(url);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Object.defineProperty(exports, "blend", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return core.blend; }
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(exports, "careful", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function () { return core.careful; }
|
|
55
|
+
});
|
|
56
|
+
Object.defineProperty(exports, "createRng", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
get: function () { return core.createRng; }
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "distracted", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () { return core.distracted; }
|
|
63
|
+
});
|
|
64
|
+
Object.defineProperty(exports, "fast", {
|
|
65
|
+
enumerable: true,
|
|
66
|
+
get: function () { return core.fast; }
|
|
67
|
+
});
|
|
68
|
+
Object.defineProperty(exports, "precise", {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: function () { return core.precise; }
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "resolvePersonality", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () { return core.resolvePersonality; }
|
|
75
|
+
});
|
|
76
|
+
exports.createHuman = createHuman;
|
|
77
|
+
//# sourceMappingURL=index.cjs.map
|
|
78
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["resolvePersonality","createRng"],"mappings":";;;;;AA4FA,eAAsB,WAAA,CAAY,IAAA,EAAY,OAAA,GAA8B,EAAC,EAAmB;AAC9F,EAAA,MAAM,WAAA,GAAcA,uBAAA,CAAmB,OAAA,CAAQ,WAAA,IAAe,SAAS,CAAA;AACvE,EAAA,MAAM,GAAA,GAAMC,cAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,OAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,EAAC;AAEpC,EAAA,MAAM,OAAA,GAAyB,EAAE,WAAA,EAAa,GAAA,EAAI;AAClD,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,MAAA,CAAO,UAAU,OAAO,CAAA;AAAA,EAChC;AAEA,EAAA,eAAe,aAAA,CAAiB,QAAqB,QAAA,EAAwC;AAC3F,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,MAAM,MAAA,CAAO,eAAe,MAAM,CAAA;AAAA,IACpC;AACA,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,EAAS;AAC7B,MAAA,MAAM,MAAA,GAAuB;AAAA,QAC3B,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,OAC3B;AACA,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,QAAA,MAAM,MAAA,CAAO,WAAA,GAAc,MAAA,EAAQ,MAAM,CAAA;AAAA,MAC3C;AACA,MAAA,OAAO,KAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,QAAA,MAAM,MAAA,CAAO,OAAA,GAAU,MAAA,EAAQ,KAAK,CAAA;AAAA,MACtC;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAM,KAAK,GAAA,EAAK;AACd,MAAA,MAAM,aAAA,CAAc,EAAE,IAAA,EAAM,MAAA,EAAQ,QAAQ,EAAE,GAAA,EAAI,EAAE,EAAG,YAAY;AACjE,QAAA,MAAM,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,MACrB,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF","file":"index.cjs","sourcesContent":["import {\n type ActionResult,\n createRng,\n type HumanAction,\n type HumanPlugin,\n type Personality,\n type PersonalityConfig,\n type PluginContext,\n resolvePersonality,\n} from '@humanjs/core';\nimport type { Page } from 'playwright';\n\nexport type {\n ActionResult,\n ActionType,\n DwellProfile,\n HumanAction,\n HumanPlugin,\n KnownActionType,\n MouseProfile,\n Personality,\n PersonalityConfig,\n PersonalityExtension,\n PluginContext,\n PresetName,\n ReadingProfile,\n Rng,\n TypingProfile,\n} from '@humanjs/core';\n// Re-exports of the public core API so consumers have one import surface.\nexport {\n blend,\n careful,\n createRng,\n distracted,\n fast,\n precise,\n resolvePersonality,\n} from '@humanjs/core';\n\n/**\n * How fast the humanized session runs.\n * - `'human'` — full humanization (default)\n * - `'fast'` — humanized but accelerated\n * - `'instant'` — bypass all humanization, straight Playwright\n */\nexport type Speed = 'fast' | 'human' | 'instant';\n\n/** Options for {@link createHuman}. */\nexport interface CreateHumanOptions {\n /** Personality preset, extension, or fully built personality. Defaults to `'careful'`. */\n readonly personality?: PersonalityConfig;\n /** Seed for the session's PRNG. Same seed produces identical trajectories. */\n readonly seed?: number | string;\n /** Speed mode. Defaults to `'human'`. */\n readonly speed?: Speed;\n /** Plugins installed on this session, invoked in registration order. */\n readonly plugins?: readonly HumanPlugin[];\n}\n\n/** A humanized Playwright session bound to a single `Page`. */\nexport interface Human {\n /** The resolved personality this session is using. */\n readonly personality: Personality;\n /** The speed mode this session was created with. */\n readonly speed: Speed;\n /**\n * Navigate to `url`. Plugins observe the action via `'goto'`; the underlying\n * `page.goto(url)` is awaited unchanged.\n */\n goto(url: string): Promise<void>;\n}\n\n/**\n * Creates a humanized session bound to a Playwright `Page`.\n *\n * @example\n * ```ts\n * import { chromium } from 'playwright';\n * import { createHuman } from '@humanjs/playwright';\n *\n * const browser = await chromium.launch();\n * const page = await browser.newPage();\n *\n * const human = await createHuman(page, {\n * personality: 'careful',\n * seed: 'session-42',\n * });\n *\n * await human.goto('https://example.com');\n * ```\n */\nexport async function createHuman(page: Page, options: CreateHumanOptions = {}): Promise<Human> {\n const personality = resolvePersonality(options.personality ?? 'careful');\n const rng = createRng(options.seed);\n const speed = options.speed ?? 'human';\n const plugins = options.plugins ?? [];\n\n const context: PluginContext = { personality, rng };\n for (const plugin of plugins) {\n await plugin.install?.(context);\n }\n\n async function performAction<T>(action: HumanAction, actionFn: () => Promise<T>): Promise<T> {\n for (const plugin of plugins) {\n await plugin.beforeAction?.(action);\n }\n const startedAt = Date.now();\n try {\n const value = await actionFn();\n const result: ActionResult = {\n type: action.type,\n durationMs: Date.now() - startedAt,\n };\n for (const plugin of plugins) {\n await plugin.afterAction?.(action, result);\n }\n return value;\n } catch (error) {\n for (const plugin of plugins) {\n await plugin.onError?.(action, error);\n }\n throw error;\n }\n }\n\n return {\n personality,\n speed,\n async goto(url) {\n await performAction({ type: 'goto', params: { url } }, async () => {\n await page.goto(url);\n });\n },\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PersonalityConfig, HumanPlugin, Personality } from '@humanjs/core';
|
|
2
|
+
export { ActionResult, ActionType, DwellProfile, HumanAction, HumanPlugin, KnownActionType, MouseProfile, Personality, PersonalityConfig, PersonalityExtension, PluginContext, PresetName, ReadingProfile, Rng, TypingProfile, blend, careful, createRng, distracted, fast, precise, resolvePersonality } from '@humanjs/core';
|
|
3
|
+
import { Page } from 'playwright';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* How fast the humanized session runs.
|
|
7
|
+
* - `'human'` — full humanization (default)
|
|
8
|
+
* - `'fast'` — humanized but accelerated
|
|
9
|
+
* - `'instant'` — bypass all humanization, straight Playwright
|
|
10
|
+
*/
|
|
11
|
+
type Speed = 'fast' | 'human' | 'instant';
|
|
12
|
+
/** Options for {@link createHuman}. */
|
|
13
|
+
interface CreateHumanOptions {
|
|
14
|
+
/** Personality preset, extension, or fully built personality. Defaults to `'careful'`. */
|
|
15
|
+
readonly personality?: PersonalityConfig;
|
|
16
|
+
/** Seed for the session's PRNG. Same seed produces identical trajectories. */
|
|
17
|
+
readonly seed?: number | string;
|
|
18
|
+
/** Speed mode. Defaults to `'human'`. */
|
|
19
|
+
readonly speed?: Speed;
|
|
20
|
+
/** Plugins installed on this session, invoked in registration order. */
|
|
21
|
+
readonly plugins?: readonly HumanPlugin[];
|
|
22
|
+
}
|
|
23
|
+
/** A humanized Playwright session bound to a single `Page`. */
|
|
24
|
+
interface Human {
|
|
25
|
+
/** The resolved personality this session is using. */
|
|
26
|
+
readonly personality: Personality;
|
|
27
|
+
/** The speed mode this session was created with. */
|
|
28
|
+
readonly speed: Speed;
|
|
29
|
+
/**
|
|
30
|
+
* Navigate to `url`. Plugins observe the action via `'goto'`; the underlying
|
|
31
|
+
* `page.goto(url)` is awaited unchanged.
|
|
32
|
+
*/
|
|
33
|
+
goto(url: string): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a humanized session bound to a Playwright `Page`.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { chromium } from 'playwright';
|
|
41
|
+
* import { createHuman } from '@humanjs/playwright';
|
|
42
|
+
*
|
|
43
|
+
* const browser = await chromium.launch();
|
|
44
|
+
* const page = await browser.newPage();
|
|
45
|
+
*
|
|
46
|
+
* const human = await createHuman(page, {
|
|
47
|
+
* personality: 'careful',
|
|
48
|
+
* seed: 'session-42',
|
|
49
|
+
* });
|
|
50
|
+
*
|
|
51
|
+
* await human.goto('https://example.com');
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare function createHuman(page: Page, options?: CreateHumanOptions): Promise<Human>;
|
|
55
|
+
|
|
56
|
+
export { type CreateHumanOptions, type Human, type Speed, createHuman };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PersonalityConfig, HumanPlugin, Personality } from '@humanjs/core';
|
|
2
|
+
export { ActionResult, ActionType, DwellProfile, HumanAction, HumanPlugin, KnownActionType, MouseProfile, Personality, PersonalityConfig, PersonalityExtension, PluginContext, PresetName, ReadingProfile, Rng, TypingProfile, blend, careful, createRng, distracted, fast, precise, resolvePersonality } from '@humanjs/core';
|
|
3
|
+
import { Page } from 'playwright';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* How fast the humanized session runs.
|
|
7
|
+
* - `'human'` — full humanization (default)
|
|
8
|
+
* - `'fast'` — humanized but accelerated
|
|
9
|
+
* - `'instant'` — bypass all humanization, straight Playwright
|
|
10
|
+
*/
|
|
11
|
+
type Speed = 'fast' | 'human' | 'instant';
|
|
12
|
+
/** Options for {@link createHuman}. */
|
|
13
|
+
interface CreateHumanOptions {
|
|
14
|
+
/** Personality preset, extension, or fully built personality. Defaults to `'careful'`. */
|
|
15
|
+
readonly personality?: PersonalityConfig;
|
|
16
|
+
/** Seed for the session's PRNG. Same seed produces identical trajectories. */
|
|
17
|
+
readonly seed?: number | string;
|
|
18
|
+
/** Speed mode. Defaults to `'human'`. */
|
|
19
|
+
readonly speed?: Speed;
|
|
20
|
+
/** Plugins installed on this session, invoked in registration order. */
|
|
21
|
+
readonly plugins?: readonly HumanPlugin[];
|
|
22
|
+
}
|
|
23
|
+
/** A humanized Playwright session bound to a single `Page`. */
|
|
24
|
+
interface Human {
|
|
25
|
+
/** The resolved personality this session is using. */
|
|
26
|
+
readonly personality: Personality;
|
|
27
|
+
/** The speed mode this session was created with. */
|
|
28
|
+
readonly speed: Speed;
|
|
29
|
+
/**
|
|
30
|
+
* Navigate to `url`. Plugins observe the action via `'goto'`; the underlying
|
|
31
|
+
* `page.goto(url)` is awaited unchanged.
|
|
32
|
+
*/
|
|
33
|
+
goto(url: string): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a humanized session bound to a Playwright `Page`.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { chromium } from 'playwright';
|
|
41
|
+
* import { createHuman } from '@humanjs/playwright';
|
|
42
|
+
*
|
|
43
|
+
* const browser = await chromium.launch();
|
|
44
|
+
* const page = await browser.newPage();
|
|
45
|
+
*
|
|
46
|
+
* const human = await createHuman(page, {
|
|
47
|
+
* personality: 'careful',
|
|
48
|
+
* seed: 'session-42',
|
|
49
|
+
* });
|
|
50
|
+
*
|
|
51
|
+
* await human.goto('https://example.com');
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare function createHuman(page: Page, options?: CreateHumanOptions): Promise<Human>;
|
|
55
|
+
|
|
56
|
+
export { type CreateHumanOptions, type Human, type Speed, createHuman };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { resolvePersonality, createRng } from '@humanjs/core';
|
|
2
|
+
export { blend, careful, createRng, distracted, fast, precise, resolvePersonality } from '@humanjs/core';
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
async function createHuman(page, options = {}) {
|
|
6
|
+
const personality = resolvePersonality(options.personality ?? "careful");
|
|
7
|
+
const rng = createRng(options.seed);
|
|
8
|
+
const speed = options.speed ?? "human";
|
|
9
|
+
const plugins = options.plugins ?? [];
|
|
10
|
+
const context = { personality, rng };
|
|
11
|
+
for (const plugin of plugins) {
|
|
12
|
+
await plugin.install?.(context);
|
|
13
|
+
}
|
|
14
|
+
async function performAction(action, actionFn) {
|
|
15
|
+
for (const plugin of plugins) {
|
|
16
|
+
await plugin.beforeAction?.(action);
|
|
17
|
+
}
|
|
18
|
+
const startedAt = Date.now();
|
|
19
|
+
try {
|
|
20
|
+
const value = await actionFn();
|
|
21
|
+
const result = {
|
|
22
|
+
type: action.type,
|
|
23
|
+
durationMs: Date.now() - startedAt
|
|
24
|
+
};
|
|
25
|
+
for (const plugin of plugins) {
|
|
26
|
+
await plugin.afterAction?.(action, result);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
for (const plugin of plugins) {
|
|
31
|
+
await plugin.onError?.(action, error);
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
personality,
|
|
38
|
+
speed,
|
|
39
|
+
async goto(url) {
|
|
40
|
+
await performAction({ type: "goto", params: { url } }, async () => {
|
|
41
|
+
await page.goto(url);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { createHuman };
|
|
48
|
+
//# sourceMappingURL=index.js.map
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;AA4FA,eAAsB,WAAA,CAAY,IAAA,EAAY,OAAA,GAA8B,EAAC,EAAmB;AAC9F,EAAA,MAAM,WAAA,GAAc,kBAAA,CAAmB,OAAA,CAAQ,WAAA,IAAe,SAAS,CAAA;AACvE,EAAA,MAAM,GAAA,GAAM,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,OAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,EAAC;AAEpC,EAAA,MAAM,OAAA,GAAyB,EAAE,WAAA,EAAa,GAAA,EAAI;AAClD,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,MAAA,CAAO,UAAU,OAAO,CAAA;AAAA,EAChC;AAEA,EAAA,eAAe,aAAA,CAAiB,QAAqB,QAAA,EAAwC;AAC3F,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,MAAM,MAAA,CAAO,eAAe,MAAM,CAAA;AAAA,IACpC;AACA,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,EAAS;AAC7B,MAAA,MAAM,MAAA,GAAuB;AAAA,QAC3B,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,OAC3B;AACA,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,QAAA,MAAM,MAAA,CAAO,WAAA,GAAc,MAAA,EAAQ,MAAM,CAAA;AAAA,MAC3C;AACA,MAAA,OAAO,KAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,QAAA,MAAM,MAAA,CAAO,OAAA,GAAU,MAAA,EAAQ,KAAK,CAAA;AAAA,MACtC;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAM,KAAK,GAAA,EAAK;AACd,MAAA,MAAM,aAAA,CAAc,EAAE,IAAA,EAAM,MAAA,EAAQ,QAAQ,EAAE,GAAA,EAAI,EAAE,EAAG,YAAY;AACjE,QAAA,MAAM,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,MACrB,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF","file":"index.js","sourcesContent":["import {\n type ActionResult,\n createRng,\n type HumanAction,\n type HumanPlugin,\n type Personality,\n type PersonalityConfig,\n type PluginContext,\n resolvePersonality,\n} from '@humanjs/core';\nimport type { Page } from 'playwright';\n\nexport type {\n ActionResult,\n ActionType,\n DwellProfile,\n HumanAction,\n HumanPlugin,\n KnownActionType,\n MouseProfile,\n Personality,\n PersonalityConfig,\n PersonalityExtension,\n PluginContext,\n PresetName,\n ReadingProfile,\n Rng,\n TypingProfile,\n} from '@humanjs/core';\n// Re-exports of the public core API so consumers have one import surface.\nexport {\n blend,\n careful,\n createRng,\n distracted,\n fast,\n precise,\n resolvePersonality,\n} from '@humanjs/core';\n\n/**\n * How fast the humanized session runs.\n * - `'human'` — full humanization (default)\n * - `'fast'` — humanized but accelerated\n * - `'instant'` — bypass all humanization, straight Playwright\n */\nexport type Speed = 'fast' | 'human' | 'instant';\n\n/** Options for {@link createHuman}. */\nexport interface CreateHumanOptions {\n /** Personality preset, extension, or fully built personality. Defaults to `'careful'`. */\n readonly personality?: PersonalityConfig;\n /** Seed for the session's PRNG. Same seed produces identical trajectories. */\n readonly seed?: number | string;\n /** Speed mode. Defaults to `'human'`. */\n readonly speed?: Speed;\n /** Plugins installed on this session, invoked in registration order. */\n readonly plugins?: readonly HumanPlugin[];\n}\n\n/** A humanized Playwright session bound to a single `Page`. */\nexport interface Human {\n /** The resolved personality this session is using. */\n readonly personality: Personality;\n /** The speed mode this session was created with. */\n readonly speed: Speed;\n /**\n * Navigate to `url`. Plugins observe the action via `'goto'`; the underlying\n * `page.goto(url)` is awaited unchanged.\n */\n goto(url: string): Promise<void>;\n}\n\n/**\n * Creates a humanized session bound to a Playwright `Page`.\n *\n * @example\n * ```ts\n * import { chromium } from 'playwright';\n * import { createHuman } from '@humanjs/playwright';\n *\n * const browser = await chromium.launch();\n * const page = await browser.newPage();\n *\n * const human = await createHuman(page, {\n * personality: 'careful',\n * seed: 'session-42',\n * });\n *\n * await human.goto('https://example.com');\n * ```\n */\nexport async function createHuman(page: Page, options: CreateHumanOptions = {}): Promise<Human> {\n const personality = resolvePersonality(options.personality ?? 'careful');\n const rng = createRng(options.seed);\n const speed = options.speed ?? 'human';\n const plugins = options.plugins ?? [];\n\n const context: PluginContext = { personality, rng };\n for (const plugin of plugins) {\n await plugin.install?.(context);\n }\n\n async function performAction<T>(action: HumanAction, actionFn: () => Promise<T>): Promise<T> {\n for (const plugin of plugins) {\n await plugin.beforeAction?.(action);\n }\n const startedAt = Date.now();\n try {\n const value = await actionFn();\n const result: ActionResult = {\n type: action.type,\n durationMs: Date.now() - startedAt,\n };\n for (const plugin of plugins) {\n await plugin.afterAction?.(action, result);\n }\n return value;\n } catch (error) {\n for (const plugin of plugins) {\n await plugin.onError?.(action, error);\n }\n throw error;\n }\n }\n\n return {\n personality,\n speed,\n async goto(url) {\n await performAction({ type: 'goto', params: { url } }, async () => {\n await page.goto(url);\n });\n },\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@humanjs/playwright",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Humanize Playwright sessions for AI agents, QA tests, and demos.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"humanjs",
|
|
7
|
+
"playwright",
|
|
8
|
+
"humanize",
|
|
9
|
+
"browser-automation",
|
|
10
|
+
"qa",
|
|
11
|
+
"ai-agents"
|
|
12
|
+
],
|
|
13
|
+
"author": "Gonzalo Muñoz <toti@eventurex.com.ar>",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"homepage": "https://humanjs.dev",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/totigm/humanjs.git",
|
|
19
|
+
"directory": "packages/playwright"
|
|
20
|
+
},
|
|
21
|
+
"bugs": "https://github.com/totigm/humanjs/issues",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "./dist/index.cjs",
|
|
24
|
+
"module": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"import": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"require": {
|
|
33
|
+
"types": "./dist/index.d.cts",
|
|
34
|
+
"default": "./dist/index.cjs"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md",
|
|
42
|
+
"LICENSE"
|
|
43
|
+
],
|
|
44
|
+
"sideEffects": false,
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@humanjs/core": "0.1.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"playwright": ">=1.40.0"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"playwright": "^1.60.0"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsup",
|
|
62
|
+
"dev": "tsup --watch",
|
|
63
|
+
"test": "vitest run",
|
|
64
|
+
"test:watch": "vitest",
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"lint": "biome check .",
|
|
67
|
+
"clean": "rm -rf dist .turbo"
|
|
68
|
+
}
|
|
69
|
+
}
|