@ceki/sdk 1.12.0 → 1.13.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/README.md +25 -8
- package/dist/cli.js +58 -37
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +29 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -4
- package/dist/index.d.ts +13 -4
- package/dist/index.js +29 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,24 +111,41 @@ await browser.profile.import(saved);
|
|
|
111
111
|
|
|
112
112
|
## Human Mode
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
Behavioral humanization is **ON by default** in both `main` and `incognito` profile modes:
|
|
115
|
+
|
|
116
|
+
- **Typing** — per-character keystrokes with natural inter-key cadence + jitter (extension-side, `Ceki.typeText`).
|
|
117
|
+
- **Mouse** — clicks are preceded by a bezier mousemove trajectory (8–35 intermediate `mouseMoved` events), so the page sees a real pointer trail instead of a teleport.
|
|
118
|
+
|
|
119
|
+
Fingerprint Tier-2 (UA / timezone / WebGL overrides) stays OFF in `main` mode to preserve the provider's identity — separate from behavioral humanization.
|
|
115
120
|
|
|
116
121
|
```typescript
|
|
117
|
-
// Default:
|
|
122
|
+
// Default: behavioral humanizer ON (natural profile)
|
|
118
123
|
const browser = await client.rent(scheduleId);
|
|
119
124
|
|
|
120
125
|
// Explicit profile
|
|
121
126
|
const browser = await client.rent(scheduleId, { human: 'careful' });
|
|
122
127
|
|
|
123
|
-
// Disable humanization
|
|
128
|
+
// Disable session-wide humanization
|
|
124
129
|
const browser = await client.rent(scheduleId, { human: null });
|
|
125
130
|
```
|
|
126
131
|
|
|
132
|
+
### Per-call disable
|
|
133
|
+
|
|
134
|
+
Pass `{ human: false }` to flatten **just one call**, without leaking jitter to siblings:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
await browser.type('user@example.com', { human: false }); // flat keystrokes
|
|
138
|
+
await browser.click(120, 240, { human: false }); // straight pointer jump
|
|
139
|
+
await browser.scroll({ deltaY: -300, human: false });
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The CLI equivalent is `--no-human` / `--raw` on `type`, `click`, `scroll`, `navigate`. Both flags mean "this call only".
|
|
143
|
+
|
|
127
144
|
### Environment overrides
|
|
128
145
|
|
|
129
146
|
- `CEKI_HUMAN_PROFILE` — Override default profile name (`careful`)
|
|
130
147
|
- `CEKI_HUMAN_PROFILE_PATH` — Path to custom JSON profile file
|
|
131
|
-
- `CEKI_HUMAN_DISABLE=1` —
|
|
148
|
+
- `CEKI_HUMAN_DISABLE=1` — **Global kill-switch**: disable humanization for every call regardless of per-call `human:` arguments or CLI flags
|
|
132
149
|
|
|
133
150
|
## Error Classes
|
|
134
151
|
|
|
@@ -194,10 +211,10 @@ The CLI persists session state locally — after `rent` it saves the session ID
|
|
|
194
211
|
|
|
195
212
|
| Command | Description |
|
|
196
213
|
|---|---|
|
|
197
|
-
| `navigate SID URL` | Open URL |
|
|
198
|
-
| `click SID X Y` | Click at viewport coordinates |
|
|
199
|
-
| `type SID TEXT [--
|
|
200
|
-
| `scroll SID X Y DY` | Scroll from (X, Y) by `DY` pixels |
|
|
214
|
+
| `navigate SID URL [--no-human\|--raw]` | Open URL (humanized by default; `--no-human` skips pre/post delays) |
|
|
215
|
+
| `click SID X Y [--no-human\|--raw]` | Click at viewport coordinates (mousemove trail ON by default; `--no-human` for direct jump) |
|
|
216
|
+
| `type SID TEXT [--selector CSS] [--no-human\|--raw]` | Type text (humanized by default; `--no-human` for flat keystrokes) |
|
|
217
|
+
| `scroll SID X Y DY [--no-human\|--raw]` | Scroll from (X, Y) by `DY` pixels (eased by default; `--no-human` for raw CDP wheel) |
|
|
201
218
|
| `screenshot SID -o FILE [--format png\|jpeg] [--full]` | Save screenshot |
|
|
202
219
|
| `snapshot SID -o FILE` | Screenshot + new chat messages |
|
|
203
220
|
| `switch-tab SID` | Switch active tab |
|
package/dist/cli.js
CHANGED
|
@@ -654,27 +654,39 @@ var Browser = class _Browser {
|
|
|
654
654
|
this._sendRaw(msg);
|
|
655
655
|
});
|
|
656
656
|
}
|
|
657
|
-
|
|
658
|
-
|
|
657
|
+
// task 427 — per-call kill-switch. human=false bypasses humanizer timings
|
|
658
|
+
// AND tells the extension to skip mouse-jitter via the `_ceki_raw` marker
|
|
659
|
+
// (see cdp.ts). human=true forces humanizer; human undefined = session
|
|
660
|
+
// default. Global env CEKI_HUMAN_DISABLE=1 nulls this._humanizer in the
|
|
661
|
+
// constructor so all paths become raw.
|
|
662
|
+
_humanizeForCall(human) {
|
|
663
|
+
if (human === false) return null;
|
|
664
|
+
return this._humanizer;
|
|
665
|
+
}
|
|
666
|
+
async navigate(url, timeout = 3e4, opts) {
|
|
667
|
+
const h = this._humanizeForCall(opts?.human);
|
|
668
|
+
if (h) await h.before("navigate");
|
|
659
669
|
const result = await this.send({ method: "Page.navigate", params: { url } }, timeout);
|
|
660
|
-
if (
|
|
670
|
+
if (h) await h.after("navigate");
|
|
661
671
|
return {
|
|
662
672
|
url: String(result?.url ?? url),
|
|
663
673
|
frameId: result?.frameId ? String(result.frameId) : void 0
|
|
664
674
|
};
|
|
665
675
|
}
|
|
666
|
-
async click(x, y) {
|
|
667
|
-
|
|
676
|
+
async click(x, y, opts) {
|
|
677
|
+
const h = this._humanizeForCall(opts?.human);
|
|
678
|
+
if (h) await h.before("click");
|
|
679
|
+
const rawFlag = h === null ? { _ceki_raw: true } : {};
|
|
668
680
|
await this.send({
|
|
669
681
|
method: "Input.dispatchMouseEvent",
|
|
670
|
-
params: { type: "mousePressed", x, y, button: "left", clickCount: 1 }
|
|
682
|
+
params: { type: "mousePressed", x, y, button: "left", clickCount: 1, ...rawFlag }
|
|
671
683
|
});
|
|
672
684
|
await this.send({
|
|
673
685
|
method: "Input.dispatchMouseEvent",
|
|
674
686
|
params: { type: "mouseReleased", x, y, button: "left", clickCount: 1 }
|
|
675
687
|
});
|
|
676
688
|
this._lastPointer = [x, y];
|
|
677
|
-
if (
|
|
689
|
+
if (h) await h.after("click");
|
|
678
690
|
}
|
|
679
691
|
async _sendKeystroke(char) {
|
|
680
692
|
const mapping = keymapForChar(char);
|
|
@@ -720,9 +732,10 @@ var Browser = class _Browser {
|
|
|
720
732
|
});
|
|
721
733
|
}
|
|
722
734
|
}
|
|
723
|
-
async type(text) {
|
|
724
|
-
|
|
725
|
-
|
|
735
|
+
async type(text, opts) {
|
|
736
|
+
const h = this._humanizeForCall(opts?.human);
|
|
737
|
+
if (h) {
|
|
738
|
+
await h.before("type");
|
|
726
739
|
if (this._lastPointer) {
|
|
727
740
|
const [px, py] = this._lastPointer;
|
|
728
741
|
await this.send({
|
|
@@ -735,10 +748,10 @@ var Browser = class _Browser {
|
|
|
735
748
|
});
|
|
736
749
|
}
|
|
737
750
|
}
|
|
738
|
-
const human =
|
|
751
|
+
const human = h ? ["natural", "careful"].includes(h.profile.name) ? h.profile.name : "natural" : null;
|
|
739
752
|
await this.send({ method: "Ceki.typeText", params: { text, human } });
|
|
740
|
-
if (
|
|
741
|
-
await
|
|
753
|
+
if (h) {
|
|
754
|
+
await h.after("type");
|
|
742
755
|
}
|
|
743
756
|
}
|
|
744
757
|
async scroll(opts) {
|
|
@@ -746,13 +759,14 @@ var Browser = class _Browser {
|
|
|
746
759
|
const y = opts?.y ?? 0;
|
|
747
760
|
const deltaX = opts?.deltaX ?? 0;
|
|
748
761
|
const deltaY = opts?.deltaY ?? -300;
|
|
749
|
-
|
|
762
|
+
const h = this._humanizeForCall(opts?.human);
|
|
763
|
+
if (h) await h.before("scroll");
|
|
750
764
|
await this.send({
|
|
751
765
|
method: "Input.dispatchMouseEvent",
|
|
752
766
|
params: { type: "mouseWheel", x, y, deltaX, deltaY }
|
|
753
767
|
});
|
|
754
768
|
this._lastPointer = [x, y];
|
|
755
|
-
if (
|
|
769
|
+
if (h) await h.after("scroll");
|
|
756
770
|
}
|
|
757
771
|
async screenshot(opts) {
|
|
758
772
|
const format = opts?.format ?? "base64";
|
|
@@ -2149,32 +2163,38 @@ async function cmdSnapshot(sid, args) {
|
|
|
2149
2163
|
await closeClient(client);
|
|
2150
2164
|
}
|
|
2151
2165
|
}
|
|
2166
|
+
function parseNoHuman(args) {
|
|
2167
|
+
return args.includes("--no-human") || args.includes("--raw");
|
|
2168
|
+
}
|
|
2152
2169
|
async function cmdNavigate(sid, args) {
|
|
2153
|
-
const url = args
|
|
2170
|
+
const url = args.find((a) => !a.startsWith("--"));
|
|
2154
2171
|
if (!url) {
|
|
2155
2172
|
err("URL is required", "args");
|
|
2156
2173
|
process.exit(1);
|
|
2157
2174
|
}
|
|
2175
|
+
const raw = parseNoHuman(args);
|
|
2158
2176
|
const apiKey = getApiKey();
|
|
2159
2177
|
const [client, browser] = await resumeBrowser(apiKey, sid);
|
|
2160
2178
|
try {
|
|
2161
|
-
await browser.navigate(url);
|
|
2179
|
+
await browser.navigate(url, 3e4, raw ? { human: false } : void 0);
|
|
2162
2180
|
out({ ok: true });
|
|
2163
2181
|
} finally {
|
|
2164
2182
|
await closeClient(client);
|
|
2165
2183
|
}
|
|
2166
2184
|
}
|
|
2167
2185
|
async function cmdClick(sid, args) {
|
|
2168
|
-
const
|
|
2169
|
-
const
|
|
2186
|
+
const positional = args.filter((a) => !a.startsWith("--"));
|
|
2187
|
+
const x = parseInt(positional[0], 10);
|
|
2188
|
+
const y = parseInt(positional[1], 10);
|
|
2170
2189
|
if (isNaN(x) || isNaN(y)) {
|
|
2171
2190
|
err("x and y coordinates are required", "args");
|
|
2172
2191
|
process.exit(1);
|
|
2173
2192
|
}
|
|
2193
|
+
const raw = parseNoHuman(args);
|
|
2174
2194
|
const apiKey = getApiKey();
|
|
2175
2195
|
const [client, browser] = await resumeBrowser(apiKey, sid);
|
|
2176
2196
|
try {
|
|
2177
|
-
await browser.click(x, y);
|
|
2197
|
+
await browser.click(x, y, raw ? { human: false } : void 0);
|
|
2178
2198
|
out({ ok: true, pointer: [x, y] });
|
|
2179
2199
|
} finally {
|
|
2180
2200
|
await closeClient(client);
|
|
@@ -2182,41 +2202,42 @@ async function cmdClick(sid, args) {
|
|
|
2182
2202
|
}
|
|
2183
2203
|
async function cmdType(sid, args) {
|
|
2184
2204
|
let text = "";
|
|
2185
|
-
let
|
|
2205
|
+
let raw = false;
|
|
2186
2206
|
for (let i = 0; i < args.length; i++) {
|
|
2187
|
-
if (args[i] === "--
|
|
2188
|
-
else if (
|
|
2207
|
+
if (args[i] === "--no-human" || args[i] === "--raw") raw = true;
|
|
2208
|
+
else if (args[i] === "--natural") {
|
|
2209
|
+
} else if (!text) text = args[i];
|
|
2189
2210
|
}
|
|
2190
2211
|
if (!text) {
|
|
2191
2212
|
err("text is required", "args");
|
|
2192
2213
|
process.exit(1);
|
|
2193
2214
|
}
|
|
2194
2215
|
const apiKey = getApiKey();
|
|
2195
|
-
const human = natural ? "natural" : null;
|
|
2196
2216
|
const client = await connect(apiKey, connectOptions());
|
|
2197
2217
|
try {
|
|
2198
|
-
const browser = await client.resume(sid
|
|
2199
|
-
|
|
2200
|
-
browser._humanizer = null;
|
|
2201
|
-
}
|
|
2202
|
-
await browser.type(text);
|
|
2218
|
+
const browser = await client.resume(sid);
|
|
2219
|
+
await browser.type(text, raw ? { human: false } : void 0);
|
|
2203
2220
|
out({ ok: true });
|
|
2204
2221
|
} finally {
|
|
2205
2222
|
await closeClient(client);
|
|
2206
2223
|
}
|
|
2207
2224
|
}
|
|
2208
2225
|
async function cmdScroll(sid, args) {
|
|
2209
|
-
const
|
|
2210
|
-
const
|
|
2211
|
-
const
|
|
2226
|
+
const positional = args.filter((a) => !a.startsWith("--"));
|
|
2227
|
+
const x = parseInt(positional[0], 10);
|
|
2228
|
+
const y = parseInt(positional[1], 10);
|
|
2229
|
+
const dy = parseInt(positional[2], 10);
|
|
2212
2230
|
if (isNaN(x) || isNaN(y) || isNaN(dy)) {
|
|
2213
2231
|
err("x, y, dy are required", "args");
|
|
2214
2232
|
process.exit(1);
|
|
2215
2233
|
}
|
|
2234
|
+
const raw = parseNoHuman(args);
|
|
2216
2235
|
const apiKey = getApiKey();
|
|
2217
2236
|
const [client, browser] = await resumeBrowser(apiKey, sid);
|
|
2218
2237
|
try {
|
|
2219
|
-
|
|
2238
|
+
const scrollOpts = { x, y, deltaY: dy };
|
|
2239
|
+
if (raw) scrollOpts.human = false;
|
|
2240
|
+
await browser.scroll(scrollOpts);
|
|
2220
2241
|
out({ ok: true });
|
|
2221
2242
|
} finally {
|
|
2222
2243
|
await closeClient(client);
|
|
@@ -2529,10 +2550,10 @@ Commands:
|
|
|
2529
2550
|
search [--limit N] [--filter k=v]...
|
|
2530
2551
|
snapshot <sid> -o PATH
|
|
2531
2552
|
screenshot <sid> -o PATH [--full]
|
|
2532
|
-
navigate <sid> <url>
|
|
2533
|
-
click <sid> <x> <y>
|
|
2534
|
-
type <sid> "<text>" [--
|
|
2535
|
-
scroll <sid> <x> <y> <dy>
|
|
2553
|
+
navigate <sid> <url> [--no-human|--raw]
|
|
2554
|
+
click <sid> <x> <y> [--no-human|--raw]
|
|
2555
|
+
type <sid> "<text>" [--no-human|--raw] (humanized by default)
|
|
2556
|
+
scroll <sid> <x> <y> <dy> [--no-human|--raw]
|
|
2536
2557
|
switch-tab <sid>
|
|
2537
2558
|
configure <sid> [--masking-mode true|false] [--fingerprint true|false]
|
|
2538
2559
|
cdp <sid> --method <M> [--params JSON]
|