gologin-agent-browser-cli 0.2.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 +318 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +336 -0
- package/dist/commands/back.d.ts +2 -0
- package/dist/commands/back.js +12 -0
- package/dist/commands/check.d.ts +2 -0
- package/dist/commands/check.js +17 -0
- package/dist/commands/click.d.ts +2 -0
- package/dist/commands/click.js +17 -0
- package/dist/commands/close.d.ts +2 -0
- package/dist/commands/close.js +12 -0
- package/dist/commands/cookies.d.ts +2 -0
- package/dist/commands/cookies.js +23 -0
- package/dist/commands/cookiesClear.d.ts +2 -0
- package/dist/commands/cookiesClear.js +12 -0
- package/dist/commands/cookiesImport.d.ts +2 -0
- package/dist/commands/cookiesImport.js +18 -0
- package/dist/commands/current.d.ts +2 -0
- package/dist/commands/current.js +9 -0
- package/dist/commands/dblclick.d.ts +2 -0
- package/dist/commands/dblclick.js +17 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +31 -0
- package/dist/commands/eval.d.ts +2 -0
- package/dist/commands/eval.js +30 -0
- package/dist/commands/fill.d.ts +2 -0
- package/dist/commands/fill.js +18 -0
- package/dist/commands/find.d.ts +2 -0
- package/dist/commands/find.js +86 -0
- package/dist/commands/focus.d.ts +2 -0
- package/dist/commands/focus.js +17 -0
- package/dist/commands/forward.d.ts +2 -0
- package/dist/commands/forward.js +12 -0
- package/dist/commands/get.d.ts +2 -0
- package/dist/commands/get.js +19 -0
- package/dist/commands/hover.d.ts +2 -0
- package/dist/commands/hover.js +17 -0
- package/dist/commands/open.d.ts +2 -0
- package/dist/commands/open.js +67 -0
- package/dist/commands/pdf.d.ts +2 -0
- package/dist/commands/pdf.js +18 -0
- package/dist/commands/press.d.ts +2 -0
- package/dist/commands/press.js +19 -0
- package/dist/commands/reload.d.ts +2 -0
- package/dist/commands/reload.js +12 -0
- package/dist/commands/screenshot.d.ts +2 -0
- package/dist/commands/screenshot.js +22 -0
- package/dist/commands/scroll.d.ts +2 -0
- package/dist/commands/scroll.js +25 -0
- package/dist/commands/scrollIntoView.d.ts +2 -0
- package/dist/commands/scrollIntoView.js +17 -0
- package/dist/commands/select.d.ts +2 -0
- package/dist/commands/select.js +18 -0
- package/dist/commands/sessions.d.ts +2 -0
- package/dist/commands/sessions.js +15 -0
- package/dist/commands/shared.d.ts +7 -0
- package/dist/commands/shared.js +51 -0
- package/dist/commands/snapshot.d.ts +2 -0
- package/dist/commands/snapshot.js +16 -0
- package/dist/commands/storageClear.d.ts +2 -0
- package/dist/commands/storageClear.js +13 -0
- package/dist/commands/storageExport.d.ts +2 -0
- package/dist/commands/storageExport.js +24 -0
- package/dist/commands/storageImport.d.ts +2 -0
- package/dist/commands/storageImport.js +20 -0
- package/dist/commands/tabClose.d.ts +2 -0
- package/dist/commands/tabClose.js +21 -0
- package/dist/commands/tabFocus.d.ts +2 -0
- package/dist/commands/tabFocus.js +21 -0
- package/dist/commands/tabOpen.d.ts +2 -0
- package/dist/commands/tabOpen.js +13 -0
- package/dist/commands/tabs.d.ts +2 -0
- package/dist/commands/tabs.js +17 -0
- package/dist/commands/type.d.ts +2 -0
- package/dist/commands/type.js +18 -0
- package/dist/commands/uncheck.d.ts +2 -0
- package/dist/commands/uncheck.js +17 -0
- package/dist/commands/upload.d.ts +2 -0
- package/dist/commands/upload.js +18 -0
- package/dist/commands/wait.d.ts +2 -0
- package/dist/commands/wait.js +41 -0
- package/dist/daemon/browser.d.ts +67 -0
- package/dist/daemon/browser.js +818 -0
- package/dist/daemon/refStore.d.ts +9 -0
- package/dist/daemon/refStore.js +26 -0
- package/dist/daemon/server.d.ts +1 -0
- package/dist/daemon/server.js +313 -0
- package/dist/daemon/sessionManager.d.ts +66 -0
- package/dist/daemon/sessionManager.js +684 -0
- package/dist/daemon/snapshot.d.ts +8 -0
- package/dist/daemon/snapshot.js +285 -0
- package/dist/lib/config.d.ts +3 -0
- package/dist/lib/config.js +58 -0
- package/dist/lib/daemon.d.ts +9 -0
- package/dist/lib/daemon.js +197 -0
- package/dist/lib/errors.d.ts +12 -0
- package/dist/lib/errors.js +63 -0
- package/dist/lib/types.d.ts +407 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/utils.d.ts +27 -0
- package/dist/lib/utils.js +165 -0
- package/examples/agent-flow.sh +19 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gologin
|
|
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,318 @@
|
|
|
1
|
+
# Gologin Agent Browser CLI
|
|
2
|
+
|
|
3
|
+
Gologin Agent Browser CLI is a cloud browser automation CLI built for AI agents. It turns Gologin Cloud Browser into a persistent, scriptable runtime with compact page snapshots, ref-based interaction, session memory, and shell-friendly commands.
|
|
4
|
+
|
|
5
|
+
It is designed for agent loops that need to stay simple:
|
|
6
|
+
|
|
7
|
+
- open a live browser session
|
|
8
|
+
- read the page as a compact text snapshot
|
|
9
|
+
- act on stable refs like `@e3`
|
|
10
|
+
- keep working across multiple CLI calls through a local daemon
|
|
11
|
+
- save artifacts such as screenshots and PDFs when needed
|
|
12
|
+
- inspect daemon health with `doctor`
|
|
13
|
+
- manage tabs, cookies, storage, and in-page eval without dropping to raw Playwright
|
|
14
|
+
|
|
15
|
+
Unlike local-browser automation tools, it runs on top of a cloud browser stack built around Gologin profiles, proxies, fingerprinting, and anti-detect capabilities.
|
|
16
|
+
|
|
17
|
+
## Why Cloud Browser
|
|
18
|
+
|
|
19
|
+
Local-browser automation is convenient, but it comes with hard limits for agent workflows that need to survive real-world websites:
|
|
20
|
+
|
|
21
|
+
- local browsers are easier to detect
|
|
22
|
+
- local runs usually do not carry profile-based fingerprinting
|
|
23
|
+
- local runs do not come with persistent cloud browser profiles
|
|
24
|
+
- local networking is limited unless you bolt on your own proxy layer
|
|
25
|
+
- local sessions are harder to standardize across agents and environments
|
|
26
|
+
|
|
27
|
+
Gologin Agent Browser CLI takes the opposite approach:
|
|
28
|
+
|
|
29
|
+
- cloud browser runtime instead of a local browser process
|
|
30
|
+
- Gologin profiles as the session identity layer
|
|
31
|
+
- proxy-aware browser sessions
|
|
32
|
+
- fingerprint and anti-detect capabilities inherited from Gologin
|
|
33
|
+
- a persistent daemon that keeps agent sessions alive across CLI calls
|
|
34
|
+
|
|
35
|
+
## Architecture
|
|
36
|
+
|
|
37
|
+
The system has two parts:
|
|
38
|
+
|
|
39
|
+
- `gologin-agent-browser` CLI
|
|
40
|
+
- a persistent local daemon
|
|
41
|
+
|
|
42
|
+
The CLI parses commands, auto-starts the daemon when needed, and prints compact output for agents. The daemon owns live browser sessions, connects to Gologin Cloud Browser through Playwright `connectOverCDP`, keeps the active page in memory, builds snapshots, resolves refs like `@e1`, and tracks session metadata such as proxy mode, idle timeout, and generated artifacts.
|
|
43
|
+
|
|
44
|
+
If you do not provide a profile id, the daemon creates a temporary Gologin cloud profile through the Gologin API, uses it to open the session, and attempts to delete it when the session is closed.
|
|
45
|
+
|
|
46
|
+
Transport is local only:
|
|
47
|
+
|
|
48
|
+
- Unix socket at `${TMPDIR:-/tmp}/gologin-agent-browser.sock` on Unix-like systems
|
|
49
|
+
- localhost HTTP on `127.0.0.1:${GOLOGIN_DAEMON_PORT:-44777}`
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
Node.js 18+ is required.
|
|
54
|
+
|
|
55
|
+
Install from npm:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g gologin-agent-browser-cli
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Run it directly:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
gologin-agent-browser --help
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or use it without a global install:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx gologin-agent-browser-cli --help
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Developer setup from source:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git clone https://github.com/GologinLabs/agent-browser.git
|
|
77
|
+
cd agent-browser
|
|
78
|
+
npm install
|
|
79
|
+
npm run build
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Get a Gologin Token
|
|
83
|
+
|
|
84
|
+
You need a Gologin account with API access before you can open cloud browser sessions.
|
|
85
|
+
|
|
86
|
+
1. Sign up or log in at [Gologin](https://gologin.com/).
|
|
87
|
+
2. In the Gologin dashboard, open `API & MCP`.
|
|
88
|
+
3. Open the `API` tab.
|
|
89
|
+
4. Click `New Token`.
|
|
90
|
+
5. Copy the generated access token.
|
|
91
|
+
|
|
92
|
+
Then export it in your shell:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
export GOLOGIN_TOKEN='your_gologin_token'
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
API access depends on your Gologin account and plan. If token creation is unavailable in the dashboard, check your account access before troubleshooting the CLI.
|
|
99
|
+
|
|
100
|
+
Note: the local daemon reads environment variables and config on startup. If you change `GOLOGIN_TOKEN` or `~/.gologin-agent-browser/config.json`, restart the daemon before running `open` again.
|
|
101
|
+
|
|
102
|
+
If you prefer a local config file instead of an environment variable, save the same token to `~/.gologin-agent-browser/config.json`.
|
|
103
|
+
|
|
104
|
+
## Required Environment
|
|
105
|
+
|
|
106
|
+
- `GOLOGIN_TOKEN` required for `open`
|
|
107
|
+
- `GOLOGIN_PROFILE_ID` optional default profile for `open`
|
|
108
|
+
- `GOLOGIN_DAEMON_PORT` optional, defaults to `44777`
|
|
109
|
+
- `GOLOGIN_CONNECT_BASE` optional, defaults to `https://cloudbrowser.gologin.com/connect`
|
|
110
|
+
|
|
111
|
+
Optional config file:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"token": "from-your-own-secret-store",
|
|
116
|
+
"defaultProfileId": "profile-id",
|
|
117
|
+
"daemonPort": 44777,
|
|
118
|
+
"connectBase": "https://cloudbrowser.gologin.com/connect"
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Save it as `~/.gologin-agent-browser/config.json`.
|
|
123
|
+
|
|
124
|
+
## Quickstart
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
export GOLOGIN_TOKEN='your_gologin_token'
|
|
128
|
+
|
|
129
|
+
gologin-agent-browser open https://example.com
|
|
130
|
+
gologin-agent-browser snapshot -i
|
|
131
|
+
gologin-agent-browser click @e3
|
|
132
|
+
gologin-agent-browser close
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## How Refs Work
|
|
136
|
+
|
|
137
|
+
`gologin-agent-browser snapshot` prints a compact page view and assigns refs like `@e1`, `@e2`, and `@e3`.
|
|
138
|
+
|
|
139
|
+
Example:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
- link "More information..." [ref=@e3]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
You can then act on that element with commands like:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
gologin-agent-browser click @e3
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Refs are best-effort and should be regenerated after navigation or major DOM changes.
|
|
152
|
+
|
|
153
|
+
Most mutating commands will leave the page in `snapshot=stale` state. When that happens, run `snapshot` again before using old refs.
|
|
154
|
+
|
|
155
|
+
On dynamic pages, `find ...` is usually a better fallback than stale refs because it re-resolves against the live page instead of the last snapshot.
|
|
156
|
+
|
|
157
|
+
## More Examples
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
gologin-agent-browser open https://example.com --proxy-host 1.2.3.4 --proxy-port 8080 --proxy-mode http --idle-timeout-ms 300000
|
|
161
|
+
gologin-agent-browser open https://example.com --profile your-preconfigured-gologin-profile
|
|
162
|
+
gologin-agent-browser tabs
|
|
163
|
+
gologin-agent-browser tabopen https://www.iana.org
|
|
164
|
+
gologin-agent-browser tabfocus 2
|
|
165
|
+
gologin-agent-browser tabclose 2
|
|
166
|
+
gologin-agent-browser click "a[href*='iana']"
|
|
167
|
+
gologin-agent-browser type "textarea[name='message']" "hello world"
|
|
168
|
+
gologin-agent-browser focus "input[name='email']"
|
|
169
|
+
gologin-agent-browser press Enter
|
|
170
|
+
gologin-agent-browser select "select[name='plan']" pro
|
|
171
|
+
gologin-agent-browser check "input[name='terms']"
|
|
172
|
+
gologin-agent-browser uncheck "input[name='newsletter']"
|
|
173
|
+
gologin-agent-browser scrollintoview "#submit"
|
|
174
|
+
gologin-agent-browser find label "Email" fill "test@example.com"
|
|
175
|
+
gologin-agent-browser upload "input[type='file']" /absolute/path/to/avatar.png
|
|
176
|
+
gologin-agent-browser wait --text "Welcome"
|
|
177
|
+
gologin-agent-browser cookies --json
|
|
178
|
+
gologin-agent-browser storage-export /tmp/storage.json
|
|
179
|
+
gologin-agent-browser eval "document.title" --json
|
|
180
|
+
gologin-agent-browser back
|
|
181
|
+
gologin-agent-browser forward
|
|
182
|
+
gologin-agent-browser reload
|
|
183
|
+
gologin-agent-browser screenshot page.png --annotate --press-escape
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Commands
|
|
187
|
+
|
|
188
|
+
- `doctor [--json]`
|
|
189
|
+
- `open <url> [--profile <profileId>] [--session <sessionId>] [--idle-timeout-ms <ms>]`
|
|
190
|
+
- `open <url> [--proxy-host <host> --proxy-port <port> --proxy-mode <http|socks4|socks5> --proxy-user <user> --proxy-pass <pass>]`
|
|
191
|
+
- `tabs [--session <sessionId>]`
|
|
192
|
+
- `tabopen [url] [--session <sessionId>]`
|
|
193
|
+
- `tabfocus <index> [--session <sessionId>]`
|
|
194
|
+
- `tabclose [index] [--session <sessionId>]`
|
|
195
|
+
- `cookies [--session <sessionId>] [--output <path>] [--json]`
|
|
196
|
+
- `cookies-import <cookies.json> [--session <sessionId>]`
|
|
197
|
+
- `cookies-clear [--session <sessionId>]`
|
|
198
|
+
- `storage-export [path] [--scope <local|session|both>] [--session <sessionId>] [--json]`
|
|
199
|
+
- `storage-import <storage.json> [--scope <local|session|both>] [--clear] [--session <sessionId>]`
|
|
200
|
+
- `storage-clear [--scope <local|session|both>] [--session <sessionId>]`
|
|
201
|
+
- `eval <expression> [--json] [--session <sessionId>]`
|
|
202
|
+
- `snapshot [--session <sessionId>] [--interactive]`
|
|
203
|
+
- `click <target> [--session <sessionId>]`
|
|
204
|
+
- `dblclick <target> [--session <sessionId>]`
|
|
205
|
+
- `focus <target> [--session <sessionId>]`
|
|
206
|
+
- `type <target> <text> [--session <sessionId>]`
|
|
207
|
+
- `fill <target> <text> [--session <sessionId>]`
|
|
208
|
+
- `hover <target> [--session <sessionId>]`
|
|
209
|
+
- `select <target> <value> [--session <sessionId>]`
|
|
210
|
+
- `check <target> [--session <sessionId>]`
|
|
211
|
+
- `uncheck <target> [--session <sessionId>]`
|
|
212
|
+
- `press <key> [target] [--session <sessionId>]`
|
|
213
|
+
- `scroll <up|down|left|right> [pixels] [--target <target>] [--session <sessionId>]`
|
|
214
|
+
- `scrollintoview <target> [--session <sessionId>]`
|
|
215
|
+
- `wait <target|ms> [--text <text>] [--url <pattern>] [--load <state>] [--session <sessionId>]`
|
|
216
|
+
- `get <text|value|html|title|url> [target] [--session <sessionId>]`
|
|
217
|
+
- `back [--session <sessionId>]`
|
|
218
|
+
- `forward [--session <sessionId>]`
|
|
219
|
+
- `reload [--session <sessionId>]`
|
|
220
|
+
- `find <role|text|label|placeholder|first|last|nth> ...`
|
|
221
|
+
- `upload <target> <file...> [--session <sessionId>]`
|
|
222
|
+
- `pdf <path> [--session <sessionId>]`
|
|
223
|
+
- `screenshot <path> [--annotate] [--press-escape] [--session <sessionId>]`
|
|
224
|
+
- `close [--session <sessionId>]`
|
|
225
|
+
- `sessions`
|
|
226
|
+
- `current`
|
|
227
|
+
|
|
228
|
+
## Help And Diagnostics
|
|
229
|
+
|
|
230
|
+
Subcommand help now works without a daemon round-trip:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
gologin-agent-browser open --help
|
|
234
|
+
gologin-agent-browser screenshot --help
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
When bootstrap is flaky, inspect the local setup directly:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
gologin-agent-browser doctor
|
|
241
|
+
gologin-agent-browser doctor --json
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
`doctor` reports whether a token is configured, which connect base is configured, which local transports are reachable, and where the daemon log is written.
|
|
245
|
+
|
|
246
|
+
## Example Session Flow
|
|
247
|
+
|
|
248
|
+
`snapshot` produces compact output designed for agent consumption:
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
session=s1 url=https://example.com/
|
|
252
|
+
- heading "Example Domain" [ref=@e1]
|
|
253
|
+
- paragraph "This domain is for use in illustrative examples in documents." [ref=@e2]
|
|
254
|
+
- link "More information..." [ref=@e3]
|
|
255
|
+
- checkbox "Accept terms" [checked] [ref=@e4]
|
|
256
|
+
- select "Plan" [selected=Pro] [ref=@e5]
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Agents can then use those refs:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
gologin-agent-browser click @e3
|
|
263
|
+
gologin-agent-browser check @e4
|
|
264
|
+
gologin-agent-browser fill "input[name='email']" "test@example.com"
|
|
265
|
+
gologin-agent-browser find role button click --name "Submit"
|
|
266
|
+
gologin-agent-browser screenshot page.png --annotate
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Targets can be either snapshot refs like `@e4` or raw Playwright/CSS selectors. `find` adds semantic locator flows similar to agent-browser.
|
|
270
|
+
|
|
271
|
+
If a ref stops resolving after navigation or a DOM update, prefer a fresh `snapshot` or use a semantic `find ...` command instead.
|
|
272
|
+
|
|
273
|
+
`open`, `current`, and `sessions` also expose session metadata in a shell-friendly form:
|
|
274
|
+
|
|
275
|
+
```text
|
|
276
|
+
session=s1 url=https://example.com snapshot=fresh proxy=http:1.2.3.4:8080 idleTimeoutMs=300000 shot=/tmp/page.png pdf=/tmp/page.pdf
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
When screenshots or PDFs are generated, `current` and `sessions` include the latest artifact paths as `shot=...` and `pdf=...`.
|
|
280
|
+
|
|
281
|
+
Supported aliases:
|
|
282
|
+
|
|
283
|
+
- `goto`, `navigate` -> `open`
|
|
284
|
+
- `tabnew` -> `tabopen`
|
|
285
|
+
- `tabswitch` -> `tabfocus`
|
|
286
|
+
- `js` -> `eval`
|
|
287
|
+
- `key` -> `press`
|
|
288
|
+
- `scrollinto` -> `scrollintoview`
|
|
289
|
+
- `quit`, `exit` -> `close`
|
|
290
|
+
|
|
291
|
+
## Current Scope
|
|
292
|
+
|
|
293
|
+
- Session persistence lasts as long as the local daemon is running. Restarting the daemon clears in-memory sessions and refs.
|
|
294
|
+
- Idle timeout is a local daemon policy. It does not change Gologin account-level cloud limits.
|
|
295
|
+
- Snapshot and ref resolution are best-effort. Dynamic pages can invalidate refs after heavy DOM changes or navigation.
|
|
296
|
+
- Snapshot output is compact and accessibility-informed, but it is not a full accessibility tree dump.
|
|
297
|
+
- Annotated screenshots are based on the current snapshot/ref model, so labels are also best-effort on highly dynamic pages.
|
|
298
|
+
- `screenshot` has a hard timeout and supports `--press-escape` for pages with modals, chat widgets, or overlay-driven render issues.
|
|
299
|
+
- The daemon keeps only the latest snapshot ref map for each session.
|
|
300
|
+
- Real browser sessions require a valid Gologin Cloud Browser account and token. A profile id is optional.
|
|
301
|
+
- Token-only mode works by provisioning a temporary cloud profile through the Gologin API before connecting to Cloud Browser.
|
|
302
|
+
- Proxy support is cloud-profile based. Temporary profiles can be created with a custom proxy definition, and existing Gologin profiles can be reused with `--profile` if they already have a managed proxy attached.
|
|
303
|
+
- Local Orbita is intentionally out of scope. This project targets Gologin Cloud Browser only.
|
|
304
|
+
- Gologin cloud live-view URLs are not auto-fetched by default because the current endpoint can interfere with an active CDP session.
|
|
305
|
+
- Playwright is the automation layer on top of Gologin Cloud Browser. The browser runtime itself does not expose built-in agent actions such as `click()` or `type()`.
|
|
306
|
+
|
|
307
|
+
## Test Coverage
|
|
308
|
+
|
|
309
|
+
The repository includes unit tests for config loading, snapshot formatting, arg parsing, and URL construction.
|
|
310
|
+
|
|
311
|
+
A full live browser smoke test is not shipped yet. If you want one, run a manual check with:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
export GOLOGIN_TOKEN='your_gologin_token'
|
|
315
|
+
gologin-agent-browser open https://example.com
|
|
316
|
+
gologin-agent-browser snapshot -i
|
|
317
|
+
gologin-agent-browser close
|
|
318
|
+
```
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.isHelpRequest = isHelpRequest;
|
|
5
|
+
exports.main = main;
|
|
6
|
+
const back_1 = require("./commands/back");
|
|
7
|
+
const check_1 = require("./commands/check");
|
|
8
|
+
const click_1 = require("./commands/click");
|
|
9
|
+
const close_1 = require("./commands/close");
|
|
10
|
+
const cookies_1 = require("./commands/cookies");
|
|
11
|
+
const cookiesClear_1 = require("./commands/cookiesClear");
|
|
12
|
+
const cookiesImport_1 = require("./commands/cookiesImport");
|
|
13
|
+
const current_1 = require("./commands/current");
|
|
14
|
+
const doctor_1 = require("./commands/doctor");
|
|
15
|
+
const dblclick_1 = require("./commands/dblclick");
|
|
16
|
+
const eval_1 = require("./commands/eval");
|
|
17
|
+
const fill_1 = require("./commands/fill");
|
|
18
|
+
const find_1 = require("./commands/find");
|
|
19
|
+
const focus_1 = require("./commands/focus");
|
|
20
|
+
const forward_1 = require("./commands/forward");
|
|
21
|
+
const get_1 = require("./commands/get");
|
|
22
|
+
const hover_1 = require("./commands/hover");
|
|
23
|
+
const open_1 = require("./commands/open");
|
|
24
|
+
const pdf_1 = require("./commands/pdf");
|
|
25
|
+
const press_1 = require("./commands/press");
|
|
26
|
+
const reload_1 = require("./commands/reload");
|
|
27
|
+
const screenshot_1 = require("./commands/screenshot");
|
|
28
|
+
const scroll_1 = require("./commands/scroll");
|
|
29
|
+
const scrollIntoView_1 = require("./commands/scrollIntoView");
|
|
30
|
+
const storageClear_1 = require("./commands/storageClear");
|
|
31
|
+
const storageExport_1 = require("./commands/storageExport");
|
|
32
|
+
const storageImport_1 = require("./commands/storageImport");
|
|
33
|
+
const sessions_1 = require("./commands/sessions");
|
|
34
|
+
const snapshot_1 = require("./commands/snapshot");
|
|
35
|
+
const select_1 = require("./commands/select");
|
|
36
|
+
const tabClose_1 = require("./commands/tabClose");
|
|
37
|
+
const tabFocus_1 = require("./commands/tabFocus");
|
|
38
|
+
const tabOpen_1 = require("./commands/tabOpen");
|
|
39
|
+
const tabs_1 = require("./commands/tabs");
|
|
40
|
+
const type_1 = require("./commands/type");
|
|
41
|
+
const uncheck_1 = require("./commands/uncheck");
|
|
42
|
+
const upload_1 = require("./commands/upload");
|
|
43
|
+
const wait_1 = require("./commands/wait");
|
|
44
|
+
const daemon_1 = require("./lib/daemon");
|
|
45
|
+
const config_1 = require("./lib/config");
|
|
46
|
+
const errors_1 = require("./lib/errors");
|
|
47
|
+
const commandUsage = {
|
|
48
|
+
open: "open <url> [--profile <profileId>] [--session <sessionId>] [--idle-timeout-ms <ms>] [--proxy-host <host> --proxy-port <port> --proxy-mode <http|socks4|socks5>] (aliases: goto, navigate)",
|
|
49
|
+
doctor: "doctor [--json]",
|
|
50
|
+
tabs: "tabs [--session <sessionId>]",
|
|
51
|
+
tabopen: "tabopen [url] [--session <sessionId>] (alias: tabnew)",
|
|
52
|
+
tabfocus: "tabfocus <index> [--session <sessionId>] (alias: tabswitch)",
|
|
53
|
+
tabclose: "tabclose [index] [--session <sessionId>]",
|
|
54
|
+
cookies: "cookies [--session <sessionId>] [--output <path>] [--json]",
|
|
55
|
+
"cookies-import": "cookies-import <cookies.json> [--session <sessionId>]",
|
|
56
|
+
"cookies-clear": "cookies-clear [--session <sessionId>]",
|
|
57
|
+
"storage-export": "storage-export [path] [--scope <local|session|both>] [--session <sessionId>] [--json]",
|
|
58
|
+
"storage-import": "storage-import <storage.json> [--scope <local|session|both>] [--clear] [--session <sessionId>]",
|
|
59
|
+
"storage-clear": "storage-clear [--scope <local|session|both>] [--session <sessionId>]",
|
|
60
|
+
eval: "eval <expression> [--json] [--session <sessionId>] (alias: js)",
|
|
61
|
+
snapshot: "snapshot [--session <sessionId>] [--interactive|-i]",
|
|
62
|
+
click: "click <target> [--session <sessionId>]",
|
|
63
|
+
dblclick: "dblclick <target> [--session <sessionId>]",
|
|
64
|
+
focus: "focus <target> [--session <sessionId>]",
|
|
65
|
+
type: "type <target> <text> [--session <sessionId>]",
|
|
66
|
+
fill: "fill <target> <text> [--session <sessionId>]",
|
|
67
|
+
hover: "hover <target> [--session <sessionId>]",
|
|
68
|
+
select: "select <target> <value> [--session <sessionId>]",
|
|
69
|
+
check: "check <target> [--session <sessionId>]",
|
|
70
|
+
uncheck: "uncheck <target> [--session <sessionId>]",
|
|
71
|
+
press: "press <key> [target] [--session <sessionId>] (alias: key)",
|
|
72
|
+
scroll: "scroll <up|down|left|right> [pixels] [--target <target>] [--session <sessionId>]",
|
|
73
|
+
scrollintoview: "scrollintoview <target> [--session <sessionId>] (alias: scrollinto)",
|
|
74
|
+
wait: "wait <target|ms> [--text <text>] [--url <pattern>] [--load <state>] [--session <sessionId>]",
|
|
75
|
+
get: "get <text|value|html|title|url> [target] [--session <sessionId>]",
|
|
76
|
+
back: "back [--session <sessionId>]",
|
|
77
|
+
forward: "forward [--session <sessionId>]",
|
|
78
|
+
reload: "reload [--session <sessionId>]",
|
|
79
|
+
find: "find <role|text|label|placeholder|first|last|nth> ... [--exact]",
|
|
80
|
+
upload: "upload <target> <file...> [--session <sessionId>]",
|
|
81
|
+
pdf: "pdf <path> [--session <sessionId>]",
|
|
82
|
+
screenshot: "screenshot <path> [--annotate] [--press-escape] [--session <sessionId>]",
|
|
83
|
+
close: "close [--session <sessionId>] (aliases: quit, exit)",
|
|
84
|
+
sessions: "sessions",
|
|
85
|
+
current: "current"
|
|
86
|
+
};
|
|
87
|
+
function printUsage() {
|
|
88
|
+
process.stderr.write([
|
|
89
|
+
"Gologin Agent CLI",
|
|
90
|
+
"",
|
|
91
|
+
"Usage:",
|
|
92
|
+
" gologin-agent-browser <command> [args] [options]",
|
|
93
|
+
"",
|
|
94
|
+
"Commands:",
|
|
95
|
+
...Object.values(commandUsage).map((usage) => ` ${usage}`),
|
|
96
|
+
"",
|
|
97
|
+
"Environment:",
|
|
98
|
+
" GOLOGIN_TOKEN",
|
|
99
|
+
" GOLOGIN_PROFILE_ID",
|
|
100
|
+
" GOLOGIN_DAEMON_PORT",
|
|
101
|
+
" GOLOGIN_CONNECT_BASE"
|
|
102
|
+
].join("\n") + "\n");
|
|
103
|
+
}
|
|
104
|
+
function printCommandUsage(command) {
|
|
105
|
+
process.stderr.write([
|
|
106
|
+
"Usage:",
|
|
107
|
+
` gologin-agent-browser ${commandUsage[command]}`,
|
|
108
|
+
"",
|
|
109
|
+
"Tip:",
|
|
110
|
+
" Use --json when you want machine-readable output."
|
|
111
|
+
].join("\n") + "\n");
|
|
112
|
+
}
|
|
113
|
+
function commandRequiresDaemon(command) {
|
|
114
|
+
return command !== "doctor";
|
|
115
|
+
}
|
|
116
|
+
function isHelpRequest(argv) {
|
|
117
|
+
return argv.includes("--help") || argv.includes("-h");
|
|
118
|
+
}
|
|
119
|
+
async function runCommand(command, context, args) {
|
|
120
|
+
switch (command) {
|
|
121
|
+
case "open":
|
|
122
|
+
await (0, open_1.runOpenCommand)(context, args);
|
|
123
|
+
return;
|
|
124
|
+
case "doctor":
|
|
125
|
+
await (0, doctor_1.runDoctorCommand)(context, args);
|
|
126
|
+
return;
|
|
127
|
+
case "tabs":
|
|
128
|
+
await (0, tabs_1.runTabsCommand)(context, args);
|
|
129
|
+
return;
|
|
130
|
+
case "tabopen":
|
|
131
|
+
await (0, tabOpen_1.runTabOpenCommand)(context, args);
|
|
132
|
+
return;
|
|
133
|
+
case "tabfocus":
|
|
134
|
+
await (0, tabFocus_1.runTabFocusCommand)(context, args);
|
|
135
|
+
return;
|
|
136
|
+
case "tabclose":
|
|
137
|
+
await (0, tabClose_1.runTabCloseCommand)(context, args);
|
|
138
|
+
return;
|
|
139
|
+
case "cookies":
|
|
140
|
+
await (0, cookies_1.runCookiesCommand)(context, args);
|
|
141
|
+
return;
|
|
142
|
+
case "cookies-import":
|
|
143
|
+
await (0, cookiesImport_1.runCookiesImportCommand)(context, args);
|
|
144
|
+
return;
|
|
145
|
+
case "cookies-clear":
|
|
146
|
+
await (0, cookiesClear_1.runCookiesClearCommand)(context, args);
|
|
147
|
+
return;
|
|
148
|
+
case "storage-export":
|
|
149
|
+
await (0, storageExport_1.runStorageExportCommand)(context, args);
|
|
150
|
+
return;
|
|
151
|
+
case "storage-import":
|
|
152
|
+
await (0, storageImport_1.runStorageImportCommand)(context, args);
|
|
153
|
+
return;
|
|
154
|
+
case "storage-clear":
|
|
155
|
+
await (0, storageClear_1.runStorageClearCommand)(context, args);
|
|
156
|
+
return;
|
|
157
|
+
case "eval":
|
|
158
|
+
await (0, eval_1.runEvalCommand)(context, args);
|
|
159
|
+
return;
|
|
160
|
+
case "snapshot":
|
|
161
|
+
await (0, snapshot_1.runSnapshotCommand)(context, args);
|
|
162
|
+
return;
|
|
163
|
+
case "click":
|
|
164
|
+
await (0, click_1.runClickCommand)(context, args);
|
|
165
|
+
return;
|
|
166
|
+
case "dblclick":
|
|
167
|
+
await (0, dblclick_1.runDoubleClickCommand)(context, args);
|
|
168
|
+
return;
|
|
169
|
+
case "focus":
|
|
170
|
+
await (0, focus_1.runFocusCommand)(context, args);
|
|
171
|
+
return;
|
|
172
|
+
case "type":
|
|
173
|
+
await (0, type_1.runTypeCommand)(context, args);
|
|
174
|
+
return;
|
|
175
|
+
case "fill":
|
|
176
|
+
await (0, fill_1.runFillCommand)(context, args);
|
|
177
|
+
return;
|
|
178
|
+
case "hover":
|
|
179
|
+
await (0, hover_1.runHoverCommand)(context, args);
|
|
180
|
+
return;
|
|
181
|
+
case "select":
|
|
182
|
+
await (0, select_1.runSelectCommand)(context, args);
|
|
183
|
+
return;
|
|
184
|
+
case "check":
|
|
185
|
+
await (0, check_1.runCheckCommand)(context, args);
|
|
186
|
+
return;
|
|
187
|
+
case "uncheck":
|
|
188
|
+
await (0, uncheck_1.runUncheckCommand)(context, args);
|
|
189
|
+
return;
|
|
190
|
+
case "press":
|
|
191
|
+
await (0, press_1.runPressCommand)(context, args);
|
|
192
|
+
return;
|
|
193
|
+
case "scroll":
|
|
194
|
+
await (0, scroll_1.runScrollCommand)(context, args);
|
|
195
|
+
return;
|
|
196
|
+
case "scrollintoview":
|
|
197
|
+
await (0, scrollIntoView_1.runScrollIntoViewCommand)(context, args);
|
|
198
|
+
return;
|
|
199
|
+
case "wait":
|
|
200
|
+
await (0, wait_1.runWaitCommand)(context, args);
|
|
201
|
+
return;
|
|
202
|
+
case "get":
|
|
203
|
+
await (0, get_1.runGetCommand)(context, args);
|
|
204
|
+
return;
|
|
205
|
+
case "back":
|
|
206
|
+
await (0, back_1.runBackCommand)(context, args);
|
|
207
|
+
return;
|
|
208
|
+
case "forward":
|
|
209
|
+
await (0, forward_1.runForwardCommand)(context, args);
|
|
210
|
+
return;
|
|
211
|
+
case "reload":
|
|
212
|
+
await (0, reload_1.runReloadCommand)(context, args);
|
|
213
|
+
return;
|
|
214
|
+
case "find":
|
|
215
|
+
await (0, find_1.runFindCommand)(context, args);
|
|
216
|
+
return;
|
|
217
|
+
case "upload":
|
|
218
|
+
await (0, upload_1.runUploadCommand)(context, args);
|
|
219
|
+
return;
|
|
220
|
+
case "pdf":
|
|
221
|
+
await (0, pdf_1.runPdfCommand)(context, args);
|
|
222
|
+
return;
|
|
223
|
+
case "screenshot":
|
|
224
|
+
await (0, screenshot_1.runScreenshotCommand)(context, args);
|
|
225
|
+
return;
|
|
226
|
+
case "close":
|
|
227
|
+
await (0, close_1.runCloseCommand)(context, args);
|
|
228
|
+
return;
|
|
229
|
+
case "sessions":
|
|
230
|
+
await (0, sessions_1.runSessionsCommand)(context, args);
|
|
231
|
+
return;
|
|
232
|
+
case "current":
|
|
233
|
+
await (0, current_1.runCurrentCommand)(context, args);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function normalizeCommand(commandArg) {
|
|
238
|
+
const aliases = {
|
|
239
|
+
goto: "open",
|
|
240
|
+
navigate: "open",
|
|
241
|
+
tabnew: "tabopen",
|
|
242
|
+
tabswitch: "tabfocus",
|
|
243
|
+
js: "eval",
|
|
244
|
+
key: "press",
|
|
245
|
+
scrollinto: "scrollintoview",
|
|
246
|
+
quit: "close",
|
|
247
|
+
exit: "close"
|
|
248
|
+
};
|
|
249
|
+
if (aliases[commandArg]) {
|
|
250
|
+
return aliases[commandArg];
|
|
251
|
+
}
|
|
252
|
+
const directCommands = new Set([
|
|
253
|
+
"open",
|
|
254
|
+
"doctor",
|
|
255
|
+
"tabs",
|
|
256
|
+
"tabopen",
|
|
257
|
+
"tabfocus",
|
|
258
|
+
"tabclose",
|
|
259
|
+
"cookies",
|
|
260
|
+
"cookies-import",
|
|
261
|
+
"cookies-clear",
|
|
262
|
+
"storage-export",
|
|
263
|
+
"storage-import",
|
|
264
|
+
"storage-clear",
|
|
265
|
+
"eval",
|
|
266
|
+
"snapshot",
|
|
267
|
+
"click",
|
|
268
|
+
"dblclick",
|
|
269
|
+
"focus",
|
|
270
|
+
"type",
|
|
271
|
+
"fill",
|
|
272
|
+
"hover",
|
|
273
|
+
"select",
|
|
274
|
+
"check",
|
|
275
|
+
"uncheck",
|
|
276
|
+
"press",
|
|
277
|
+
"scroll",
|
|
278
|
+
"scrollintoview",
|
|
279
|
+
"wait",
|
|
280
|
+
"get",
|
|
281
|
+
"back",
|
|
282
|
+
"forward",
|
|
283
|
+
"reload",
|
|
284
|
+
"find",
|
|
285
|
+
"upload",
|
|
286
|
+
"pdf",
|
|
287
|
+
"screenshot",
|
|
288
|
+
"close",
|
|
289
|
+
"sessions",
|
|
290
|
+
"current"
|
|
291
|
+
]);
|
|
292
|
+
return directCommands.has(commandArg) ? commandArg : undefined;
|
|
293
|
+
}
|
|
294
|
+
async function main() {
|
|
295
|
+
const argv = process.argv.slice(2);
|
|
296
|
+
const commandArg = argv[0];
|
|
297
|
+
if (!commandArg || commandArg === "--help" || commandArg === "-h") {
|
|
298
|
+
printUsage();
|
|
299
|
+
process.exit(commandArg ? 0 : 1);
|
|
300
|
+
}
|
|
301
|
+
const command = normalizeCommand(commandArg);
|
|
302
|
+
if (!command) {
|
|
303
|
+
throw new errors_1.AppError("BAD_REQUEST", `Unknown command: ${commandArg}`, 400);
|
|
304
|
+
}
|
|
305
|
+
if (isHelpRequest(argv.slice(1))) {
|
|
306
|
+
printCommandUsage(command);
|
|
307
|
+
process.exit(0);
|
|
308
|
+
}
|
|
309
|
+
const config = (0, config_1.loadConfig)();
|
|
310
|
+
const client = commandRequiresDaemon(command)
|
|
311
|
+
? await (0, daemon_1.createHealthyDaemonClient)(config)
|
|
312
|
+
: {
|
|
313
|
+
transport: {
|
|
314
|
+
kind: "http",
|
|
315
|
+
host: config.daemonHost,
|
|
316
|
+
port: config.daemonPort
|
|
317
|
+
},
|
|
318
|
+
async request() {
|
|
319
|
+
throw new errors_1.AppError("DAEMON_UNREACHABLE", "This command should not call the daemon client", 500);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const context = {
|
|
323
|
+
config,
|
|
324
|
+
client,
|
|
325
|
+
stdout: process.stdout,
|
|
326
|
+
stderr: process.stderr,
|
|
327
|
+
cwd: process.cwd()
|
|
328
|
+
};
|
|
329
|
+
await runCommand(command, context, argv.slice(1));
|
|
330
|
+
}
|
|
331
|
+
if (require.main === module) {
|
|
332
|
+
main().catch((error) => {
|
|
333
|
+
process.stderr.write(`${(0, errors_1.formatErrorLine)(error)}\n`);
|
|
334
|
+
process.exit(error instanceof errors_1.AppError ? 1 : 1);
|
|
335
|
+
});
|
|
336
|
+
}
|