clearcote 0.28.1 → 0.30.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 +70 -20
- package/dist/clearcote-cli.d.ts +3 -0
- package/dist/clearcote-cli.d.ts.map +1 -0
- package/dist/clearcote-cli.js +9 -0
- package/dist/clearcote-cli.js.map +1 -0
- package/dist/cli-commands.d.ts +62 -0
- package/dist/cli-commands.d.ts.map +1 -0
- package/dist/cli-commands.js +333 -0
- package/dist/cli-commands.js.map +1 -0
- package/dist/download.d.ts +28 -0
- package/dist/download.d.ts.map +1 -1
- package/dist/download.js +56 -6
- package/dist/download.js.map +1 -1
- package/dist/fingerprint.d.ts +16 -0
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +37 -0
- package/dist/fingerprint.js.map +1 -1
- package/dist/geoip.d.ts +37 -1
- package/dist/geoip.d.ts.map +1 -1
- package/dist/geoip.js +90 -68
- package/dist/geoip.js.map +1 -1
- package/dist/index.d.ts +49 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -50
- package/dist/index.js.map +1 -1
- package/dist/launchopts.d.ts +44 -0
- package/dist/launchopts.d.ts.map +1 -1
- package/dist/launchopts.js +78 -0
- package/dist/launchopts.js.map +1 -1
- package/dist/license.d.ts +69 -4
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +355 -28
- package/dist/license.js.map +1 -1
- package/dist/multiplex.d.ts +111 -0
- package/dist/multiplex.d.ts.map +1 -0
- package/dist/multiplex.js +536 -0
- package/dist/multiplex.js.map +1 -0
- package/dist/net.d.ts +36 -0
- package/dist/net.d.ts.map +1 -0
- package/dist/net.js +278 -0
- package/dist/net.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -97,6 +97,51 @@ official Docker image also works: `docker run -d --rm -p 9222:9222 teamflatearth
|
|
|
97
97
|
[`clearcote-mcp`](https://github.com/clearcotelabs/clearcote-browser/tree/main/mcp) server
|
|
98
98
|
(`npx -y clearcote-mcp` or `pip install clearcote-mcp`) — ~20 tools over one shared stealth browser.
|
|
99
99
|
|
|
100
|
+
### Many identities on one endpoint (`serveMultiplex`, `clearcote serve`)
|
|
101
|
+
|
|
102
|
+
One port, one browser per identity, chosen by the connection URL:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { chromium } from "playwright-core";
|
|
106
|
+
// in another process: npx clearcote serve --port 9222 --idle-timeout 300
|
|
107
|
+
const a = await chromium.connectOverCDP("http://127.0.0.1:9222?fingerprint=acct-1&timezone=Europe/Berlin");
|
|
108
|
+
const b = await chromium.connectOverCDP(`http://127.0.0.1:9222?fingerprint=acct-2&proxy=${encodeURIComponent("socks5://u:p@host:1080")}&geoip=true`);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- Query options: `fingerprint`, `timezone`, `locale`, `proxy`, `geoip`, plus any fingerprint option in kebab-case (`platform`, `hardware-concurrency`, `allow-third-party-cookies`, ...). Unknown options are rejected (400).
|
|
112
|
+
- The same identity reuses its browser. Asking for a running identity with *different* options returns 409 — close it first.
|
|
113
|
+
- `GET /` lists running browsers; `POST /fingerprint/<id>/close` stops one; `--idle-timeout <s>` closes a browser after its last client disconnects; `--max-browsers` caps them (default 16).
|
|
114
|
+
- Behind a reverse proxy, WebSocket URLs honour `X-Forwarded-Host` / `X-Forwarded-Proto`; add the public name with `--allow-host`.
|
|
115
|
+
- Binds `127.0.0.1` by default. Requests a web page could make (cross-site fetches, foreign `Origin`, a `Host` that isn't an IP / `localhost` / allowed) are refused.
|
|
116
|
+
|
|
117
|
+
In code: `serveMultiplex({ port: 9222, idleTimeoutSec: 300, dataDir: "./profiles" })`.
|
|
118
|
+
|
|
119
|
+
### `clearcote` command line
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npx clearcote install [--version 152] [--channel preview]
|
|
123
|
+
npx clearcote info [--quick] [--json] [--proxy <url>] # alias: doctor
|
|
124
|
+
npx clearcote login [key] # validates the key, saves it to ~/.clearcote/license.key
|
|
125
|
+
npx clearcote logout
|
|
126
|
+
npx clearcote clear-cache
|
|
127
|
+
npx clearcote serve [--port 9222] ...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`info` never downloads: it reports the SDK, the cached builds, which engine features the binary supports, a launch test (skipped with `--quick`), licence seats, fonts and missing system libraries.
|
|
131
|
+
|
|
132
|
+
### Engine options (PRO 152 r22+)
|
|
133
|
+
|
|
134
|
+
| Option | Effect |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `fingerprint: "off"` | No persona at all — for telling whether a problem comes from the spoofing or from your environment. |
|
|
137
|
+
| `fingerprintVoices: false` | Keep the host's own `speechSynthesis` voices under a persona. |
|
|
138
|
+
| `allowThirdPartyCookies: true` | Allow third-party cookies (blocked by default), for embedded sign-in, payment and captcha frames. |
|
|
139
|
+
| `transparentProxy: true` | With a proxy: send the headers a direct connection sends, and report connection timing as a reused connection. |
|
|
140
|
+
|
|
141
|
+
On an older engine each of these is skipped with a warning; the launch still works.
|
|
142
|
+
|
|
143
|
+
Also: `licenseThroughProxy: true` (or `CLEARCOTE_LICENSE_THROUGH_PROXY=1`) sends the licence calls through the launch proxy; `releaseChannel: "preview"` (or `CLEARCOTE_RELEASE_CHANNEL`) picks up PRO preview builds; `getSessionSeats()` reports seats in use.
|
|
144
|
+
|
|
100
145
|
### Through a proxy (report the proxy's IP, not your host's)
|
|
101
146
|
|
|
102
147
|
```ts
|
|
@@ -122,7 +167,9 @@ const browser = await launch({
|
|
|
122
167
|
});
|
|
123
168
|
```
|
|
124
169
|
|
|
125
|
-
Anything you set explicitly wins over `geoip`. With no proxy it uses your direct connection's IP. The lookup
|
|
170
|
+
Anything you set explicitly wins over `geoip`. With no proxy it uses your direct connection's IP. The lookup goes through the proxy — http(s) and SOCKS5 (with username/password) alike.
|
|
171
|
+
|
|
172
|
+
The whole lookup has one deadline, `CLEARCOTE_GEOIP_TIMEOUT_SECONDS` (default 20). If the region can't be resolved in time, `launch()` throws `GeoipError` (code `GEOIP_UNRESOLVED`) **before** any browser starts, instead of launching with this machine's clock and language. If you set both `timezone` and `acceptLanguage` yourself, it warns and launches anyway.
|
|
126
173
|
|
|
127
174
|
Geo data comes from the offline [geoip-all-in-one](https://github.com/daijro/geoip-all-in-one) MaxMind database (downloaded + cached on first use; GPL-3.0 data, the same source Camoufox uses) — more accurate than a single online API — with `ip-api.com` as a fallback.
|
|
128
175
|
|
|
@@ -433,25 +480,28 @@ contacts the license backend).
|
|
|
433
480
|
<!-- The rows below mirror site/lib/tiers.ts, which is the single source of truth for the
|
|
434
481
|
free/PRO split. If you change one, change the other (and the sibling SDK README). -->
|
|
435
482
|
|
|
436
|
-
The identity surface is **free in full**.
|
|
437
|
-
control below is in the
|
|
438
|
-
or engine work held out of the public tree
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
|
443
|
-
|
|
444
|
-
|
|
|
445
|
-
|
|
|
446
|
-
|
|
|
447
|
-
|
|
|
448
|
-
|
|
|
449
|
-
|
|
|
450
|
-
|
|
|
451
|
-
| **
|
|
452
|
-
| **
|
|
453
|
-
| **
|
|
454
|
-
|
|
|
483
|
+
The identity surface is **free in full**. A licence does not unlock "more spoofing" — every fingerprint
|
|
484
|
+
control below is in the open build. The licensed build adds behavioural realism that needs recorded
|
|
485
|
+
data or engine work held out of the public tree. **It is free with GitHub for one browser at a time**
|
|
486
|
+
(sign in at [clearcotelabs.com](https://clearcotelabs.com/pricing#free), needs SDK 0.29.0+); **PRO**
|
|
487
|
+
runs as many browsers at once as you need and adds email support.
|
|
488
|
+
|
|
489
|
+
| Capability | Open source | Free with GitHub | PRO |
|
|
490
|
+
|---|:---:|:---:|:---:|
|
|
491
|
+
| Seeded personas (`fingerprint`), per-site farbling | ✅ | ✅ | ✅ |
|
|
492
|
+
| Canvas / WebGL / audio / font identity controls | ✅ | ✅ | ✅ |
|
|
493
|
+
| All 18 metadata overrides (`screenWidth`, `deviceMemory`, `gpuVendor`, …) | ✅ | ✅ | ✅ |
|
|
494
|
+
| `light_stealth` preset | ✅ | ✅ | ✅ |
|
|
495
|
+
| TLS ClientHello profile (`tlsProfile`) | ✅ | ✅ | ✅ |
|
|
496
|
+
| Proxy + `geoip` locale/timezone coherence | ✅ | ✅ | ✅ |
|
|
497
|
+
| Humanized input (`humanize`) — synthetic bézier paths | ✅ | ✅ | ✅ |
|
|
498
|
+
| **Humanized input — real recorded human trajectories** | — | ✅ | ✅ |
|
|
499
|
+
| **Coalesced pointer samples** (`getCoalescedEvents` realism) | — | ✅ | ✅ |
|
|
500
|
+
| **Coherent WebRTC srflx fabrication** (`webrtcIp`) | — | ✅ | ✅ |
|
|
501
|
+
| **WebRTC host-candidate concealment** (`.local` names) | — | ✅ | ✅ |
|
|
502
|
+
| **Request-header hygiene** on revalidation | — | ✅ | ✅ |
|
|
503
|
+
| Floating-concurrency licensing + run-token gate | — | 1 browser | ✅ unlimited |
|
|
504
|
+
| Email support from the owner | — | — | ✅ |
|
|
455
505
|
|
|
456
506
|
The mouse tier is decided **at runtime** from a signed claim in the run-token — same SDK call,
|
|
457
507
|
same `humanize: true`. With a valid PRO lease the motion comes from recorded human trajectories;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearcote-cli.d.ts","sourceRoot":"","sources":["../src/clearcote-cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `clearcote` command-line entry. All logic lives in ./cli-commands.ts so it can be imported and
|
|
3
|
+
// tested without running anything; this file only runs it.
|
|
4
|
+
import { main } from "./cli-commands.js";
|
|
5
|
+
main().catch((e) => {
|
|
6
|
+
process.stderr.write(`clearcote: ${e.message}\n`);
|
|
7
|
+
process.exitCode = 1;
|
|
8
|
+
});
|
|
9
|
+
//# sourceMappingURL=clearcote-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearcote-cli.js","sourceRoot":"","sources":["../src/clearcote-cli.ts"],"names":[],"mappings":";AACA,iGAAiG;AACjG,2DAA2D;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAe,CAAW,CAAC,OAAO,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type SessionSeats } from "./index.js";
|
|
2
|
+
export declare const USAGE: string;
|
|
3
|
+
/** What `info` reports. Also the `--json` shape. */
|
|
4
|
+
export interface InfoReport {
|
|
5
|
+
sdk: {
|
|
6
|
+
version: string;
|
|
7
|
+
node: string;
|
|
8
|
+
platform: string;
|
|
9
|
+
};
|
|
10
|
+
license: {
|
|
11
|
+
source: string;
|
|
12
|
+
key?: string;
|
|
13
|
+
seats?: SessionSeats;
|
|
14
|
+
};
|
|
15
|
+
binary: {
|
|
16
|
+
source: "CLEARCOTE_BINARY" | "cache" | "none";
|
|
17
|
+
path?: string;
|
|
18
|
+
tag?: string;
|
|
19
|
+
cached: Array<{
|
|
20
|
+
tag: string;
|
|
21
|
+
path: string;
|
|
22
|
+
}>;
|
|
23
|
+
pinnedFree: string;
|
|
24
|
+
releaseChannel: string;
|
|
25
|
+
};
|
|
26
|
+
engineFeatures?: Record<string, boolean>;
|
|
27
|
+
launch?: {
|
|
28
|
+
tested: boolean;
|
|
29
|
+
ok?: boolean;
|
|
30
|
+
version?: string;
|
|
31
|
+
error?: string;
|
|
32
|
+
missingLibs?: string[];
|
|
33
|
+
reason?: string;
|
|
34
|
+
};
|
|
35
|
+
fonts?: {
|
|
36
|
+
bundled: boolean;
|
|
37
|
+
note: string;
|
|
38
|
+
};
|
|
39
|
+
geoip: {
|
|
40
|
+
databaseCached: boolean;
|
|
41
|
+
path: string;
|
|
42
|
+
proxy?: {
|
|
43
|
+
exitIp?: string;
|
|
44
|
+
country?: string;
|
|
45
|
+
timezone?: string;
|
|
46
|
+
acceptLanguage?: string;
|
|
47
|
+
error?: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export declare function buildInfo(flags: {
|
|
52
|
+
quick?: boolean;
|
|
53
|
+
proxy?: string;
|
|
54
|
+
}): Promise<InfoReport>;
|
|
55
|
+
export declare function main(argv?: string[]): Promise<void>;
|
|
56
|
+
/** `--proxy scheme://user:pass@host:port` as a launch proxy option with the credentials split out. */
|
|
57
|
+
export declare function proxyOption(url: string): {
|
|
58
|
+
server: string;
|
|
59
|
+
username?: string;
|
|
60
|
+
password?: string;
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=cli-commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-commands.d.ts","sourceRoot":"","sources":["../src/cli-commands.ts"],"names":[],"mappings":"AAiBA,OAAO,EAcL,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAcpB,eAAO,MAAM,KAAK,QAqBiF,CAAC;AAWpG,oDAAoD;AACpD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC;IAChE,MAAM,EAAE;QACN,MAAM,EAAE,kBAAkB,GAAG,OAAO,GAAG,MAAM,CAAC;QAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC7C,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,EAAE,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtH,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,KAAK,EAAE;QAAE,cAAc,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,cAAc,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;CAC7J;AAYD,wBAAsB,SAAS,CAAC,KAAK,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAkE/F;AAyDD,wBAAsB,IAAI,CAAC,IAAI,WAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0HtE;AAED,sGAAsG;AACtG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAKjG"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
// clearcote — manage the browser binary, diagnose a setup, save a licence key, run a CDP endpoint.
|
|
2
|
+
//
|
|
3
|
+
// clearcote install [--version 152] [--channel preview] download + verify the binary
|
|
4
|
+
// clearcote info [--quick] [--json] [--proxy URL] diagnostics (alias: doctor)
|
|
5
|
+
// clearcote update [--channel preview] fetch a newer build if one exists
|
|
6
|
+
// clearcote clear-cache delete every cached binary
|
|
7
|
+
// clearcote login [key] save a licence key (validated first)
|
|
8
|
+
// clearcote logout remove the saved key
|
|
9
|
+
// clearcote serve [--port 9222] [--idle-timeout 300] … multi-identity CDP endpoint
|
|
10
|
+
//
|
|
11
|
+
// `info` never downloads: it reports what is already cached and what a launch would resolve to.
|
|
12
|
+
import { parseArgs } from "node:util";
|
|
13
|
+
import * as readline from "node:readline";
|
|
14
|
+
import { existsSync, readdirSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
15
|
+
import { spawnSync } from "node:child_process";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
import { download, launch, getSessionSeats, saveLicenseKey, removeLicenseKey, licenseKeySource, licenseKeyPath, resolveLicenseKey, resolveGeoDetailed, resolveReleaseChannel, engineSupportsSwitch, serveMultiplex, RELEASE, } from "./index.js";
|
|
18
|
+
import { defaultCacheRoot, listCachedBuilds } from "./download.js";
|
|
19
|
+
import { geoCacheRoot } from "./geoip.js";
|
|
20
|
+
import { GATED_ENGINE_SWITCHES } from "./launchopts.js";
|
|
21
|
+
import { toProxySpec } from "./net.js";
|
|
22
|
+
const SDK_VERSION = (() => {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return "unknown";
|
|
28
|
+
}
|
|
29
|
+
})();
|
|
30
|
+
export const USAGE = `clearcote ${SDK_VERSION} — manage and diagnose the Clearcote browser.
|
|
31
|
+
|
|
32
|
+
USAGE
|
|
33
|
+
clearcote install [--version <v>] [--channel stable|preview]
|
|
34
|
+
clearcote info [--quick] [--json] [--proxy <url>] (alias: doctor)
|
|
35
|
+
clearcote update [--channel stable|preview]
|
|
36
|
+
clearcote clear-cache
|
|
37
|
+
clearcote login [key]
|
|
38
|
+
clearcote logout
|
|
39
|
+
clearcote serve [--port 9222] [--host 127.0.0.1] [--idle-timeout <s>] [--data-dir <dir>]
|
|
40
|
+
[--max-browsers 16] [--allow-origin <origin>]... [--allow-host <name>]... [--headed]
|
|
41
|
+
[--fingerprint <seed>] [--platform <os>] [--proxy <url>] [--timezone <tz>]
|
|
42
|
+
[--accept-language <l>] [--geoip]
|
|
43
|
+
|
|
44
|
+
INFO FLAGS
|
|
45
|
+
--quick skip everything that needs the network or a launch (seat count, launch test)
|
|
46
|
+
--json machine-readable output
|
|
47
|
+
--proxy <url> resolve the exit IP, timezone and language a launch through this proxy would use
|
|
48
|
+
|
|
49
|
+
ENVIRONMENT
|
|
50
|
+
CLEARCOTE_LICENSE_KEY, CLEARCOTE_RELEASE_CHANNEL, CLEARCOTE_GEOIP_TIMEOUT_SECONDS,
|
|
51
|
+
CLEARCOTE_LICENSE_THROUGH_PROXY, CLEARCOTE_BINARY, CLEARCOTE_CACHE, CLEARCOTE_SERVE_IDLE_TIMEOUT`;
|
|
52
|
+
function out(line = "") {
|
|
53
|
+
process.stdout.write(line + "\n");
|
|
54
|
+
}
|
|
55
|
+
function fail(msg, code = 1) {
|
|
56
|
+
process.stderr.write(`clearcote: ${msg}\n`);
|
|
57
|
+
process.exit(code);
|
|
58
|
+
}
|
|
59
|
+
function geoDbPath() {
|
|
60
|
+
return join(geoCacheRoot(), "geoip-aio-all.mmdb");
|
|
61
|
+
}
|
|
62
|
+
function missingSharedLibs(exe) {
|
|
63
|
+
if (process.platform !== "linux")
|
|
64
|
+
return [];
|
|
65
|
+
const r = spawnSync("ldd", ["--", exe], { encoding: "utf8" });
|
|
66
|
+
return (r.stdout || "").split("\n").filter((l) => l.includes("not found")).map((l) => l.trim().split(" ")[0]);
|
|
67
|
+
}
|
|
68
|
+
export async function buildInfo(flags) {
|
|
69
|
+
const src = licenseKeySource();
|
|
70
|
+
let channel;
|
|
71
|
+
try {
|
|
72
|
+
channel = resolveReleaseChannel();
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
channel = `invalid (${e.message})`;
|
|
76
|
+
}
|
|
77
|
+
const cached = listCachedBuilds();
|
|
78
|
+
const envBinary = process.env.CLEARCOTE_BINARY;
|
|
79
|
+
const pick = envBinary ? { path: envBinary } : cached[0];
|
|
80
|
+
const report = {
|
|
81
|
+
sdk: { version: SDK_VERSION, node: process.version, platform: `${process.platform}-${process.arch}` },
|
|
82
|
+
license: { source: src.source, ...(src.masked ? { key: src.masked } : {}) },
|
|
83
|
+
binary: {
|
|
84
|
+
source: envBinary ? "CLEARCOTE_BINARY" : pick ? "cache" : "none",
|
|
85
|
+
...(pick ? { path: pick.path } : {}),
|
|
86
|
+
...(!envBinary && pick ? { tag: pick.tag } : {}),
|
|
87
|
+
cached,
|
|
88
|
+
pinnedFree: `${RELEASE.version} (${RELEASE.tag})`,
|
|
89
|
+
releaseChannel: channel,
|
|
90
|
+
},
|
|
91
|
+
geoip: { databaseCached: existsSync(geoDbPath()), path: geoDbPath() },
|
|
92
|
+
};
|
|
93
|
+
if (pick && existsSync(pick.path)) {
|
|
94
|
+
report.engineFeatures = Object.fromEntries(["proxy-auth", "socks5-credentials", "socks5-udp", ...Object.keys(GATED_ENGINE_SWITCHES).map((s) => s.slice(2))]
|
|
95
|
+
.map((name) => [name, engineSupportsSwitch(pick.path, name)]));
|
|
96
|
+
}
|
|
97
|
+
if (process.platform === "linux" && pick) {
|
|
98
|
+
const template = join(dirname(pick.path), "fonts", "fonts.conf.template");
|
|
99
|
+
report.fonts = existsSync(template)
|
|
100
|
+
? { bundled: true, note: "metric-compatible Windows font clones are bundled with this build" }
|
|
101
|
+
: { bundled: false, note: "this build ships no font bundle; a Windows persona on this host may render with Linux fonts" };
|
|
102
|
+
}
|
|
103
|
+
if (!flags.quick && src.source !== "none") {
|
|
104
|
+
report.license.seats = await getSessionSeats();
|
|
105
|
+
}
|
|
106
|
+
if (flags.quick) {
|
|
107
|
+
report.launch = { tested: false, reason: "skipped (--quick)" };
|
|
108
|
+
}
|
|
109
|
+
else if (!pick) {
|
|
110
|
+
report.launch = { tested: false, reason: "no binary installed — run: clearcote install" };
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
try {
|
|
114
|
+
const b = await launch({ executablePath: pick.path, headless: true, quiet: true, ephemeralProfile: false });
|
|
115
|
+
const version = b.version();
|
|
116
|
+
await b.close();
|
|
117
|
+
report.launch = { tested: true, ok: true, version };
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
const libs = missingSharedLibs(pick.path);
|
|
121
|
+
report.launch = { tested: true, ok: false, error: e.message.split("\n")[0], ...(libs.length ? { missingLibs: libs } : {}) };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (flags.proxy) {
|
|
125
|
+
const r = await resolveGeoDetailed(flags.proxy, { quiet: true });
|
|
126
|
+
report.geoip.proxy = r.geo && r.geo.timezone
|
|
127
|
+
? { exitIp: r.geo.ip, country: r.geo.country, timezone: r.geo.timezone, acceptLanguage: r.geo.acceptLanguage }
|
|
128
|
+
: { error: r.reason };
|
|
129
|
+
}
|
|
130
|
+
return report;
|
|
131
|
+
}
|
|
132
|
+
function printInfo(r) {
|
|
133
|
+
const ok = (b) => (b ? "yes" : "no");
|
|
134
|
+
out(`clearcote SDK ${r.sdk.version} (node ${r.sdk.node}, ${r.sdk.platform})`);
|
|
135
|
+
out(`Licence ${r.license.source === "none" ? "none (free build)" : `${r.license.key} from ${r.license.source}`}`);
|
|
136
|
+
const seats = r.license.seats;
|
|
137
|
+
if (seats) {
|
|
138
|
+
if (seats.state === "ok")
|
|
139
|
+
out(`Seats ${seats.used} of ${seats.limit ?? "unlimited"} in use${seats.plan ? ` (plan: ${seats.plan})` : ""}`);
|
|
140
|
+
else
|
|
141
|
+
out(`Seats unavailable: ${seats.reason ?? seats.state}`);
|
|
142
|
+
}
|
|
143
|
+
out(`Binary ${r.binary.path ? `${r.binary.path}${r.binary.tag ? ` [${r.binary.tag}]` : ""} (${r.binary.source})` : "not installed — run: clearcote install"}`);
|
|
144
|
+
out(`Release channel ${r.binary.releaseChannel}`);
|
|
145
|
+
out(`Free pin ${r.binary.pinnedFree}`);
|
|
146
|
+
if (r.binary.cached.length > 1)
|
|
147
|
+
out(`Also cached ${r.binary.cached.slice(1).map((c) => c.tag).join(", ")}`);
|
|
148
|
+
if (r.engineFeatures) {
|
|
149
|
+
out(`Engine support ${Object.entries(r.engineFeatures).map(([k, v]) => `${k}=${ok(v)}`).join(" ")}`);
|
|
150
|
+
}
|
|
151
|
+
if (r.launch) {
|
|
152
|
+
if (!r.launch.tested)
|
|
153
|
+
out(`Launch test ${r.launch.reason}`);
|
|
154
|
+
else if (r.launch.ok)
|
|
155
|
+
out(`Launch test ok (${r.launch.version})`);
|
|
156
|
+
else {
|
|
157
|
+
out(`Launch test FAILED: ${r.launch.error}`);
|
|
158
|
+
for (const lib of r.launch.missingLibs ?? [])
|
|
159
|
+
out(` missing library: ${lib}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (r.fonts)
|
|
163
|
+
out(`Fonts ${r.fonts.note}`);
|
|
164
|
+
out(`GeoIP database ${r.geoip.databaseCached ? "cached" : "not cached (downloaded on first geoip launch)"}`);
|
|
165
|
+
if (r.geoip.proxy) {
|
|
166
|
+
const p = r.geoip.proxy;
|
|
167
|
+
out(p.error ? `Proxy geo FAILED: ${p.error}` : `Proxy geo exit ${p.exitIp} (${p.country}) timezone ${p.timezone} language ${p.acceptLanguage}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async function promptKey() {
|
|
171
|
+
if (!process.stdin.isTTY) {
|
|
172
|
+
fail("no key given. Run `clearcote login <key>`, or copy a key from https://www.clearcotelabs.com/dashboard/licenses");
|
|
173
|
+
}
|
|
174
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
175
|
+
const key = await new Promise((resolve) => rl.question("Paste your licence key (https://www.clearcotelabs.com/dashboard/licenses): ", (a) => resolve(a)));
|
|
176
|
+
rl.close();
|
|
177
|
+
return key.trim();
|
|
178
|
+
}
|
|
179
|
+
function dirSize(p) {
|
|
180
|
+
let total = 0;
|
|
181
|
+
try {
|
|
182
|
+
for (const e of readdirSync(p, { withFileTypes: true })) {
|
|
183
|
+
const full = join(p, e.name);
|
|
184
|
+
total += e.isDirectory() ? dirSize(full) : statSync(full).size;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch { /* unreadable — skip */ }
|
|
188
|
+
return total;
|
|
189
|
+
}
|
|
190
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
191
|
+
const [cmd, ...rest] = argv;
|
|
192
|
+
if (!cmd || cmd === "-h" || cmd === "--help" || cmd === "help") {
|
|
193
|
+
out(USAGE);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (cmd === "version" || cmd === "--version") {
|
|
197
|
+
out(SDK_VERSION);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (cmd === "info" || cmd === "doctor") {
|
|
201
|
+
const { values } = parseArgs({ args: rest, options: { quick: { type: "boolean" }, "no-launch": { type: "boolean" }, json: { type: "boolean" }, proxy: { type: "string" } } });
|
|
202
|
+
const report = await buildInfo({ quick: !!(values.quick || values["no-launch"]), proxy: values.proxy });
|
|
203
|
+
if (values.json)
|
|
204
|
+
out(JSON.stringify(report, null, 2));
|
|
205
|
+
else
|
|
206
|
+
printInfo(report);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (cmd === "install" || cmd === "update") {
|
|
210
|
+
const { values } = parseArgs({ args: rest, options: { version: { type: "string" }, channel: { type: "string" } } });
|
|
211
|
+
const releaseChannel = resolveReleaseChannel(values.channel);
|
|
212
|
+
const licenseKey = resolveLicenseKey();
|
|
213
|
+
const path = await download({
|
|
214
|
+
version: values.version,
|
|
215
|
+
releaseChannel,
|
|
216
|
+
licenseKey,
|
|
217
|
+
// update: re-resolve the newest build instead of reusing the SDK's pin (free) — PRO always asks the server
|
|
218
|
+
...(cmd === "update" ? { autoUpdate: true } : {}),
|
|
219
|
+
});
|
|
220
|
+
out(path);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (cmd === "clear-cache") {
|
|
224
|
+
const root = defaultCacheRoot();
|
|
225
|
+
if (!existsSync(root)) {
|
|
226
|
+
out(`nothing to clear (${root} does not exist)`);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// Only build directories: a CLEARCOTE_CACHE pointing at $HOME or a shared directory must not
|
|
230
|
+
// become `rm -rf` of that directory. A build dir carries a .verified marker once complete; a
|
|
231
|
+
// half-finished download has the build-tag name but no marker yet.
|
|
232
|
+
let bytes = 0;
|
|
233
|
+
const removed = [];
|
|
234
|
+
for (const name of readdirSync(root)) {
|
|
235
|
+
const dir = join(root, name);
|
|
236
|
+
let isDir = false;
|
|
237
|
+
try {
|
|
238
|
+
isDir = statSync(dir).isDirectory();
|
|
239
|
+
}
|
|
240
|
+
catch { /* vanished */ }
|
|
241
|
+
if (!isDir)
|
|
242
|
+
continue;
|
|
243
|
+
if (!existsSync(join(dir, ".verified")) && !/^(pro-\d|v\d)/.test(name))
|
|
244
|
+
continue;
|
|
245
|
+
bytes += dirSize(dir);
|
|
246
|
+
rmSync(dir, { recursive: true, force: true });
|
|
247
|
+
removed.push(name);
|
|
248
|
+
}
|
|
249
|
+
out(removed.length
|
|
250
|
+
? `removed ${removed.length} cached build${removed.length === 1 ? "" : "s"} from ${root} (${(bytes / 1e6).toFixed(0)} MB)`
|
|
251
|
+
: `no cached builds in ${root}`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (cmd === "login") {
|
|
255
|
+
const key = rest[0] ?? (await promptKey());
|
|
256
|
+
if (!key)
|
|
257
|
+
fail("empty key");
|
|
258
|
+
const seats = await getSessionSeats({ licenseKey: key });
|
|
259
|
+
if (seats.state === "invalid")
|
|
260
|
+
fail(`the licence server rejected this key (${seats.reason}). Nothing was saved.`);
|
|
261
|
+
const where = saveLicenseKey(key);
|
|
262
|
+
out(`saved to ${where}`);
|
|
263
|
+
if (seats.state === "ok")
|
|
264
|
+
out(`valid: ${seats.used} of ${seats.limit ?? "unlimited"} seats in use${seats.plan ? `, plan ${seats.plan}` : ""}`);
|
|
265
|
+
else
|
|
266
|
+
out(`note: could not confirm the key right now (${seats.reason}); it was saved anyway`);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (cmd === "logout") {
|
|
270
|
+
const removed = removeLicenseKey();
|
|
271
|
+
out(removed ? `removed ${licenseKeyPath()}` : "no saved key");
|
|
272
|
+
if (process.env.CLEARCOTE_LICENSE_KEY)
|
|
273
|
+
out("note: CLEARCOTE_LICENSE_KEY is still set in this environment and will keep being used");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (cmd === "serve") {
|
|
277
|
+
const { values } = parseArgs({
|
|
278
|
+
args: rest,
|
|
279
|
+
options: {
|
|
280
|
+
port: { type: "string" }, host: { type: "string" }, "idle-timeout": { type: "string" }, "data-dir": { type: "string" },
|
|
281
|
+
"max-browsers": { type: "string" }, "allow-origin": { type: "string", multiple: true }, "allow-host": { type: "string", multiple: true }, headed: { type: "boolean" },
|
|
282
|
+
fingerprint: { type: "string" }, platform: { type: "string" }, proxy: { type: "string" }, timezone: { type: "string" },
|
|
283
|
+
"accept-language": { type: "string" }, geoip: { type: "boolean" }, quiet: { type: "boolean" },
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
const num = (name, v) => {
|
|
287
|
+
if (v === undefined)
|
|
288
|
+
return undefined;
|
|
289
|
+
const n = Number(v);
|
|
290
|
+
if (!Number.isFinite(n) || n < 0)
|
|
291
|
+
fail(`--${name} must be a non-negative number`);
|
|
292
|
+
return n;
|
|
293
|
+
};
|
|
294
|
+
const srv = await serveMultiplex({
|
|
295
|
+
port: num("port", values.port) ?? 9222,
|
|
296
|
+
host: values.host,
|
|
297
|
+
idleTimeoutSec: num("idle-timeout", values["idle-timeout"]),
|
|
298
|
+
dataDir: values["data-dir"],
|
|
299
|
+
maxBrowsers: num("max-browsers", values["max-browsers"]),
|
|
300
|
+
allowOrigins: values["allow-origin"],
|
|
301
|
+
allowHosts: values["allow-host"],
|
|
302
|
+
headless: !values.headed,
|
|
303
|
+
quiet: values.quiet,
|
|
304
|
+
...(values.fingerprint ? { fingerprint: values.fingerprint } : {}),
|
|
305
|
+
...(values.platform ? { platform: values.platform } : {}),
|
|
306
|
+
// Split user:pass out of the URL: Chromium rejects a --proxy-server that carries credentials
|
|
307
|
+
// and goes DIRECT, so passing the URL through whole leaked the host's real IP.
|
|
308
|
+
...(values.proxy ? { proxy: proxyOption(values.proxy) } : {}),
|
|
309
|
+
...(values.timezone ? { timezone: values.timezone } : {}),
|
|
310
|
+
...(values["accept-language"] ? { acceptLanguage: values["accept-language"] } : {}),
|
|
311
|
+
...(values.geoip ? { geoip: true } : {}),
|
|
312
|
+
});
|
|
313
|
+
const stop = () => { void srv.close().then(() => process.exit(0)); };
|
|
314
|
+
process.once("SIGINT", stop);
|
|
315
|
+
process.once("SIGTERM", stop);
|
|
316
|
+
return; // keep running
|
|
317
|
+
}
|
|
318
|
+
fail(`unknown command '${cmd}'. Run \`clearcote --help\`.`, 2);
|
|
319
|
+
}
|
|
320
|
+
/** `--proxy scheme://user:pass@host:port` as a launch proxy option with the credentials split out. */
|
|
321
|
+
export function proxyOption(url) {
|
|
322
|
+
let spec;
|
|
323
|
+
try {
|
|
324
|
+
spec = toProxySpec(url);
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
spec = null;
|
|
328
|
+
}
|
|
329
|
+
if (!spec)
|
|
330
|
+
fail(`--proxy must be a URL such as http://user:pass@host:8080 or socks5://host:1080`);
|
|
331
|
+
return { server: spec.server, ...(spec.username ? { username: spec.username } : {}), ...(spec.password ? { password: spec.password } : {}) };
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=cli-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-commands.js","sourceRoot":"","sources":["../src/cli-commands.ts"],"names":[],"mappings":"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"}
|
package/dist/download.d.ts
CHANGED
|
@@ -28,6 +28,12 @@ export interface DownloadOptions {
|
|
|
28
28
|
* (or bare `"r7"`), which also requires a license. Also set via `CLEARCOTE_BROWSER_VERSION`.
|
|
29
29
|
*/
|
|
30
30
|
version?: string;
|
|
31
|
+
/**
|
|
32
|
+
* PRO release channel: `"stable"` (default) or `"preview"`. Preview selects the newest build
|
|
33
|
+
* available for this platform — a newer preview when one exists, otherwise stable. An exact
|
|
34
|
+
* version pin overrides the channel. Also set via `CLEARCOTE_RELEASE_CHANNEL`.
|
|
35
|
+
*/
|
|
36
|
+
releaseChannel?: ReleaseChannel;
|
|
31
37
|
}
|
|
32
38
|
/** A resolved release to fetch — either the pinned {@link RELEASE} or one discovered at runtime. */
|
|
33
39
|
interface ResolvedRelease extends ReleaseInfo {
|
|
@@ -38,6 +44,8 @@ interface ResolvedRelease extends ReleaseInfo {
|
|
|
38
44
|
/** URL of the public signing key (auto-update only). */
|
|
39
45
|
keyUrl?: string;
|
|
40
46
|
}
|
|
47
|
+
/** Per-OS cache root for downloaded browsers (CLEARCOTE_CACHE overrides). */
|
|
48
|
+
export declare function defaultCacheRoot(): string;
|
|
41
49
|
export declare const MANIFEST = ".manifest.json";
|
|
42
50
|
/**
|
|
43
51
|
* Snapshot every extracted file's size next to the tree, so a LATER launch can tell a healthy
|
|
@@ -108,7 +116,17 @@ export declare function ensureVersion(selector: string, opts?: {
|
|
|
108
116
|
apiBase?: string;
|
|
109
117
|
cacheDir?: string;
|
|
110
118
|
quiet?: boolean;
|
|
119
|
+
releaseChannel?: string;
|
|
111
120
|
}): Promise<string>;
|
|
121
|
+
/** Release channel for PRO builds: "stable" (default) or "preview". */
|
|
122
|
+
export type ReleaseChannel = "stable" | "preview";
|
|
123
|
+
/**
|
|
124
|
+
* Resolve the release channel: explicit option > CLEARCOTE_RELEASE_CHANNEL > "stable".
|
|
125
|
+
* Unknown values throw, so a typo never silently selects a different build.
|
|
126
|
+
*/
|
|
127
|
+
export declare function resolveReleaseChannel(explicit?: string, env?: Record<string, string | undefined>): ReleaseChannel;
|
|
128
|
+
/** The PRO download URL for a platform, version selector and channel. */
|
|
129
|
+
export declare function proDownloadUrl(baseUrl: string, plat: "windows" | "linux", version?: string, channel?: ReleaseChannel): string;
|
|
112
130
|
/** Options for {@link proEnsureBinary}. */
|
|
113
131
|
export interface ProDownloadOptions {
|
|
114
132
|
/** License API base (default: `CLEARCOTE_LICENSE_API` env or clearcotelabs.com). */
|
|
@@ -119,6 +137,8 @@ export interface ProDownloadOptions {
|
|
|
119
137
|
quiet?: boolean;
|
|
120
138
|
/** Request a specific PRO major/version; the server returns the newest match. */
|
|
121
139
|
version?: string;
|
|
140
|
+
/** "preview" gets the newest build for this platform, preview or stable (default "stable"). */
|
|
141
|
+
releaseChannel?: ReleaseChannel;
|
|
122
142
|
}
|
|
123
143
|
/**
|
|
124
144
|
* Download + verify the PRO (license-gated) browser and return its chrome path.
|
|
@@ -136,5 +156,13 @@ export declare function proEnsureBinary(licenseKey: string, opts?: ProDownloadOp
|
|
|
136
156
|
* Cached per release tag, so subsequent calls are instant.
|
|
137
157
|
*/
|
|
138
158
|
export declare function ensureBinary(opts?: DownloadOptions): Promise<string>;
|
|
159
|
+
/**
|
|
160
|
+
* Verified browser builds already in the cache, newest first (by directory mtime). Never downloads
|
|
161
|
+
* and never deletes: unlike cachedBinary(), a damaged entry is simply left out of the list.
|
|
162
|
+
*/
|
|
163
|
+
export declare function listCachedBuilds(cacheDir?: string): Array<{
|
|
164
|
+
tag: string;
|
|
165
|
+
path: string;
|
|
166
|
+
}>;
|
|
139
167
|
export {};
|
|
140
168
|
//# sourceMappingURL=download.d.ts.map
|
package/dist/download.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAkF,KAAK,WAAW,EAAmC,MAAM,cAAc,CAAC;AAEjK;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CA8B3C;AAED,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":"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"}
|