opera-browser-cli 0.1.45 → 0.1.47
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 +106 -16
- package/SKILL.md +34 -2
- package/dist/src/bridge.d.ts +69 -1
- package/dist/src/bridge.js +260 -23
- package/dist/src/bridge.js.map +1 -1
- package/dist/src/browser-target.d.ts +84 -0
- package/dist/src/browser-target.js +161 -0
- package/dist/src/browser-target.js.map +1 -0
- package/dist/src/cli.d.ts +72 -2
- package/dist/src/cli.js +1134 -214
- package/dist/src/cli.js.map +1 -1
- package/dist/src/client.d.ts +75 -8
- package/dist/src/client.js +689 -119
- package/dist/src/client.js.map +1 -1
- package/dist/src/config.d.ts +58 -0
- package/dist/src/config.js +171 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/detect.d.ts +21 -0
- package/dist/src/detect.js +76 -0
- package/dist/src/detect.js.map +1 -0
- package/dist/src/identity.d.ts +61 -0
- package/dist/src/identity.js +87 -0
- package/dist/src/identity.js.map +1 -0
- package/dist/src/profile.d.ts +80 -0
- package/dist/src/profile.js +187 -0
- package/dist/src/profile.js.map +1 -0
- package/dist/src/version.d.ts +10 -0
- package/dist/src/version.js +34 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +1 -1
- package/dist/bin/opera-cli-bridge.d.ts +0 -2
- package/dist/bin/opera-cli-bridge.js +0 -7
- package/dist/bin/opera-cli-bridge.js.map +0 -1
- package/dist/bin/opera-cli.d.ts +0 -2
- package/dist/bin/opera-cli.js +0 -4
- package/dist/bin/opera-cli.js.map +0 -1
- package/openclaw/.claude/settings.local.json +0 -8
package/README.md
CHANGED
|
@@ -13,10 +13,13 @@ It wraps [opera-devtools-mcp](https://github.com/operasoftware/opera-devtools-mc
|
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
15
|
npm install -g opera-browser-cli
|
|
16
|
-
opera-browser-cli setup # interactive wizard — run in a terminal where you can answer prompts
|
|
17
16
|
opera-browser-cli open https://example.com
|
|
18
17
|
```
|
|
19
18
|
|
|
19
|
+
That is the whole setup. The first command detects your Opera installation,
|
|
20
|
+
writes `~/.opera-browser-cli/config`, and gets on with it. Run
|
|
21
|
+
`opera-browser-cli setup` only when you want to change what it chose.
|
|
22
|
+
|
|
20
23
|
Once installed, `open` navigates to a URL and returns a structured snapshot you can act on:
|
|
21
24
|
|
|
22
25
|
```sh
|
|
@@ -64,21 +67,30 @@ Prerequisites: **Node.js >= 20**, **Opera** browser ([Opera Neon](https://www.op
|
|
|
64
67
|
npm install -g opera-browser-cli
|
|
65
68
|
```
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
No setup step is required. The first command you run detects your Opera
|
|
71
|
+
installation, writes `~/.opera-browser-cli/config`, and continues:
|
|
68
72
|
|
|
69
73
|
```sh
|
|
70
|
-
opera-browser-cli
|
|
74
|
+
opera-browser-cli --version
|
|
75
|
+
opera-browser-cli open https://example.com
|
|
71
76
|
```
|
|
72
77
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
Verify:
|
|
78
|
+
`setup` exists for when you want to change that choice — pick a different
|
|
79
|
+
browser or profile, or install the agent skill files:
|
|
76
80
|
|
|
77
81
|
```sh
|
|
78
|
-
opera-browser-cli
|
|
79
|
-
opera-browser-cli
|
|
82
|
+
opera-browser-cli setup # interactive wizard
|
|
83
|
+
opera-browser-cli setup -y # detect and accept, no prompts
|
|
84
|
+
opera-browser-cli setup --executable "/Applications/Opera Neon.app/Contents/MacOS/Opera" \
|
|
85
|
+
--profile skip --headless
|
|
80
86
|
```
|
|
81
87
|
|
|
88
|
+
It saves to `~/.opera-browser-cli/config` and installs the skill to
|
|
89
|
+
`~/.claude/skills/opera-browser-cli/SKILL.md` (Claude Code) and
|
|
90
|
+
`~/.agents/skills/opera-browser-cli/SKILL.md` (generic cross-agent path used by
|
|
91
|
+
Codex and other agents). The non-interactive form needs no terminal, so agents
|
|
92
|
+
and provisioning scripts can run it too.
|
|
93
|
+
|
|
82
94
|
### From source
|
|
83
95
|
|
|
84
96
|
```sh
|
|
@@ -86,7 +98,7 @@ opera-browser-cli open https://example.com
|
|
|
86
98
|
npm install && npm run build && npm link
|
|
87
99
|
```
|
|
88
100
|
|
|
89
|
-
Then run
|
|
101
|
+
Then just run a command — configuration happens on first use.
|
|
90
102
|
|
|
91
103
|
### Usage examples
|
|
92
104
|
|
|
@@ -127,7 +139,7 @@ OPERA_CLI_BROWSER_URL=http://127.0.0.1:9222 opera-browser-cli open https://examp
|
|
|
127
139
|
```
|
|
128
140
|
|
|
129
141
|
- **Persistent bridge** — a detached process keeps the MCP session alive across commands, so Chrome doesn't restart every invocation
|
|
130
|
-
- **Auto-lifecycle** — the bridge starts on first command
|
|
142
|
+
- **Auto-lifecycle** — the bridge starts on first command, writes a PID file to `~/.opera-browser-cli/bridge.pid`, and restarts itself on version skew or a dropped connection
|
|
131
143
|
- **Snapshot parsing** — accessibility tree snapshots are extracted and analyzed for interactive elements (`uid=` refs)
|
|
132
144
|
- **TOON encoding** — structured metadata uses [TOON format](https://www.npmjs.com/package/@toon-format/toon) for compact, token-efficient output
|
|
133
145
|
|
|
@@ -202,6 +214,14 @@ opera-browser-cli eval "(() => { const rows = [...document.querySelectorAll('tr'
|
|
|
202
214
|
| `perf-insight <set> <name>` | Analyze a performance insight |
|
|
203
215
|
| `heap <path>` | Capture a heap snapshot |
|
|
204
216
|
|
|
217
|
+
### MCP Hub
|
|
218
|
+
|
|
219
|
+
| Command | Description | Requires |
|
|
220
|
+
|-----------------------------------------------|-------------------------------------------------------|------------------|
|
|
221
|
+
| `mcp-servers` | List MCP servers registered in the browser | Opera Neon |
|
|
222
|
+
| `mcp-tools --server <name>` | List tools exposed by a specific MCP server | Opera Neon |
|
|
223
|
+
| `mcp-call --server <name> --tool <name>` | Execute a tool on an MCP server | Opera Neon |
|
|
224
|
+
|
|
205
225
|
### Opera AI
|
|
206
226
|
|
|
207
227
|
| Command | Description | Requires |
|
|
@@ -219,14 +239,83 @@ opera-browser-cli eval "(() => { const rows = [...document.querySelectorAll('tr'
|
|
|
219
239
|
|----------|--------------------------------------------------|
|
|
220
240
|
| `setup` | Interactive first-time setup (browser path, etc) |
|
|
221
241
|
| `doctor` | Check configuration and environment |
|
|
242
|
+
| `doctor --fix` | Repair what can be repaired mechanically |
|
|
243
|
+
| `login` | Sign in to your Opera account (needed for AI) |
|
|
222
244
|
| `logs` | Show bridge server logs |
|
|
223
245
|
|
|
246
|
+
### Using your real Opera profile
|
|
247
|
+
|
|
248
|
+
By default the CLI launches its own browser. To drive **your** Opera — with your
|
|
249
|
+
logins, your session — the browser has to have been started with a debugging
|
|
250
|
+
port. That flag cannot be added to a browser that is already open, so there are
|
|
251
|
+
two ways in:
|
|
252
|
+
|
|
253
|
+
```sh
|
|
254
|
+
opera-browser-cli launch-args # prints the command to start Opera with a port
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Start Opera that way once, and every later command finds it automatically — the
|
|
258
|
+
port is recorded in `DevToolsActivePort` inside the profile, so nothing needs
|
|
259
|
+
configuring. Or let the CLI do it for you:
|
|
260
|
+
|
|
261
|
+
```sh
|
|
262
|
+
opera-browser-cli open example.com # detects the conflict, offers to restart Opera
|
|
263
|
+
opera-browser-cli open example.com --takeover # skip the prompt (scripts, agents)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
If Opera is already running on the configured profile and has no debugging port,
|
|
267
|
+
the CLI asks whether to restart it (tabs are restored). Without a terminal to ask
|
|
268
|
+
in, it quietly uses a separate profile instead — an agent will never quit your
|
|
269
|
+
browser on its own. Restarting is always SIGTERM, never SIGKILL: a forced kill
|
|
270
|
+
risks a corrupted profile.
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
opera-browser-cli attach --port 9222 # connect to a specific endpoint
|
|
274
|
+
opera-browser-cli attach --clear # go back to a CLI-launched browser
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
> **Note:** a debugging port has no authentication of its own — the CLI's bearer
|
|
278
|
+
> token protects the bridge, not the browser. Any local process can drive a
|
|
279
|
+
> browser with an open port, and this one is signed into everything you are. The
|
|
280
|
+
> CLI lets the browser pick a random port rather than a predictable 9222, binds
|
|
281
|
+
> it to loopback, and never passes `--remote-allow-origins`, which is what stops
|
|
282
|
+
> a web page from driving it. Close the browser when you are done.
|
|
283
|
+
|
|
224
284
|
### Bridge
|
|
225
285
|
|
|
226
|
-
| Command
|
|
227
|
-
|
|
228
|
-
| `start`
|
|
229
|
-
| `stop`
|
|
286
|
+
| Command | Description |
|
|
287
|
+
|-----------|--------------------------------------------------------------------|
|
|
288
|
+
| `start` | Start the bridge server |
|
|
289
|
+
| `stop` | Stop the bridge server (escalates to SIGKILL; clears a stale PID) |
|
|
290
|
+
| `restart` | Stop and start again — forces a clean state |
|
|
291
|
+
| `status` | Report bridge pid, port, and running version without starting one |
|
|
292
|
+
|
|
293
|
+
You should rarely need any of these. The bridge starts on first use, and repairs
|
|
294
|
+
itself without being asked:
|
|
295
|
+
|
|
296
|
+
- **Upgraded package** — a bridge running pre-upgrade code is detected by version
|
|
297
|
+
and replaced on the next command.
|
|
298
|
+
- **Crashed or killed bridge** — the next command restarts it and retries. Opera AI
|
|
299
|
+
commands are the exception: they are never silently re-run, since they may already
|
|
300
|
+
have acted on the page.
|
|
301
|
+
- **Port in use** — the next port in the range is used instead of failing.
|
|
302
|
+
- **Several commands at once** — a start lock means exactly one bridge comes up.
|
|
303
|
+
- **Stale PID file** — cleared automatically, and never signalled if the PID could
|
|
304
|
+
belong to an unrelated process from before a reboot.
|
|
305
|
+
|
|
306
|
+
### Exit codes
|
|
307
|
+
|
|
308
|
+
Scripts and agents can branch on why a command failed without parsing messages:
|
|
309
|
+
|
|
310
|
+
| Code | Meaning | Caller action |
|
|
311
|
+
|---|---|---|
|
|
312
|
+
| 0 | Success | — |
|
|
313
|
+
| 1 | Unknown / internal | Report |
|
|
314
|
+
| 2 | Bad arguments, or unsupported on this browser | Fix the command |
|
|
315
|
+
| 3 | Environment not ready after auto-recovery | Run `doctor` |
|
|
316
|
+
| 4 | Sign-in, subscription, or consent required | Ask the user |
|
|
317
|
+
| 5 | Timed out | Retry |
|
|
318
|
+
| 6 | Stale element ref or closed page | Re-snapshot, then retry |
|
|
230
319
|
|
|
231
320
|
Running with no command shows the CLI home view. It prepends `bin` and
|
|
232
321
|
`description` metadata, then includes the current snapshot when a browser
|
|
@@ -265,14 +354,15 @@ session is active or the no-session status/help block when one is not.
|
|
|
265
354
|
|
|
266
355
|
| Variable | Default | Purpose |
|
|
267
356
|
|-----------------------------|----------------------------------|------------------------------------------------------------------|
|
|
268
|
-
| `OPERA_CLI_PORT` | `9225` |
|
|
357
|
+
| `OPERA_CLI_PORT` | `9225` | Base bridge port; the next 9 are tried if it is occupied |
|
|
269
358
|
| `OPERA_CLI_MCP_BIN` | _(bundled `opera-devtools-mcp`)_ | Override the MCP server binary |
|
|
270
359
|
| `OPERA_CLI_EXECUTABLE_PATH` | _(system Chrome)_ | Custom browser binary |
|
|
271
360
|
| `OPERA_CLI_BROWSER_URL` | — | Connect to an existing browser instance instead of launching one |
|
|
272
361
|
| `OPERA_CLI_USER_DATA_DIR` | — | Persistent Chrome profile directory (skips isolated mode) |
|
|
273
|
-
| `OPERA_CLI_HEADED` |
|
|
362
|
+
| `OPERA_CLI_HEADED` | `1` when an Opera binary is configured | `1` headed, `0` headless. Opera AI needs a window to sign in |
|
|
274
363
|
| `OPERA_CLI_CHROME_ARGS` | — | Extra Chrome flags, space-separated |
|
|
275
364
|
| `OPERA_CLI_ENABLE_HOOKS` | — | Set to `1` to auto-install session hooks on startup |
|
|
365
|
+
| `OPERA_CLI_TAKEOVER` | — | Set to `1` to restart a running Opera without asking |
|
|
276
366
|
|
|
277
367
|
State is stored in `~/.opera-browser-cli/`:
|
|
278
368
|
|
package/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opera-browser-cli
|
|
3
|
-
description: Browser automation and web interaction using the opera-browser-cli tool. Use for navigating pages, clicking elements, filling forms, taking screenshots, inspecting console/network, running performance audits, and Opera AI features (chat available on any Opera browser; invoke-do, make, research require Opera Neon).
|
|
3
|
+
description: Browser automation and web interaction using the opera-browser-cli tool. Use for navigating pages, clicking elements, filling forms, taking screenshots, inspecting console/network, running performance audits, and Opera AI features (chat available on any Opera browser; invoke-do, make, research require Opera Neon). When a browser is already running without automation enabled, this tool can restart it with a debug port (takeover) or use a separate profile — ask the user which they prefer.
|
|
4
4
|
metadata: {"openclaw": {"requires": {"bins": ["opera-browser-cli"]}}}
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -12,6 +12,9 @@ metadata: {"openclaw": {"requires": {"bins": ["opera-browser-cli"]}}}
|
|
|
12
12
|
- **`chat`** — available on any Opera browser. Use `--model <id>` to select an AI model.
|
|
13
13
|
- **`models`** — list available AI models for chat (shows IDs and which is the default).
|
|
14
14
|
- **`invoke-do`, `make`, `research`** — require **Opera Neon** with an active sign-in.
|
|
15
|
+
- **`mcp-servers`** — list MCP servers registered in the browser (requires Opera Neon).
|
|
16
|
+
- **`mcp-tools --server <name>`** — list tools exposed by a specific MCP server (requires Opera Neon).
|
|
17
|
+
- **`mcp-call --server <name> --tool <name> [--params '{...}']`** — execute a tool on an MCP server (requires Opera Neon).
|
|
15
18
|
|
|
16
19
|
Run `opera-browser-cli --help` for the full command list, or `opera-browser-cli <command> --help` for per-command flags and examples.
|
|
17
20
|
|
|
@@ -47,6 +50,35 @@ Commands that accept these flags: `open`, `snapshot`, `click`, `fill`, `type`, `
|
|
|
47
50
|
|
|
48
51
|
To wire this CLI into a Docker-based OpenClaw setup (Chromium sidecar, shared netns, config bootstrap), see [`openclaw/README.md`](openclaw/README.md).
|
|
49
52
|
|
|
53
|
+
## Exit codes
|
|
54
|
+
|
|
55
|
+
Branch on the exit code rather than parsing messages:
|
|
56
|
+
|
|
57
|
+
| Code | Meaning | What to do |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| 0 | Success | — |
|
|
60
|
+
| 2 | Bad arguments, or the browser cannot do this | Fix the command; do not retry as-is |
|
|
61
|
+
| 3 | Environment not ready after auto-recovery | Run `opera-browser-cli doctor` |
|
|
62
|
+
| 4 | Sign-in, subscription, or consent needed | Ask the user — you cannot fix this |
|
|
63
|
+
| 5 | Timed out | Retry |
|
|
64
|
+
| 6 | Stale element ref or closed page | Re-run `snapshot`, then retry with fresh refs |
|
|
65
|
+
| 1 | Anything else | Report it |
|
|
66
|
+
|
|
67
|
+
## Recovery is automatic
|
|
68
|
+
|
|
69
|
+
The bridge restarts itself on version skew, a crash, or a dropped connection, and falls back to another port if one is taken. Do not run `stop`/`restart` speculatively — just re-run the command. The exception is the Opera AI tools (`invoke-do`, `make`, `research`, `chat`): if one reports the connection dropped mid-call, it was **not** retried, because it may already have acted. Ask before re-running it.
|
|
70
|
+
|
|
71
|
+
## When the browser can't be automated
|
|
72
|
+
|
|
73
|
+
The CLI only drives a browser started with a debug port. If the user's Opera is already open **without** one, the CLI can't attach to that window — `open`/AI then fail with **"Could not connect to Chrome"**. Run `opera-browser-cli doctor` (it reports the profile state); the bridge self-heals, so don't restart it blindly.
|
|
74
|
+
|
|
75
|
+
**Always ask the user** — restarting their browser is their call, not a judgement you infer:
|
|
76
|
+
> "Your Opera is open but wasn't started with automation. May I restart it with a debug port (tabs restored)? Or should I use a separate profile (you'd sign in there)?"
|
|
77
|
+
|
|
78
|
+
- **They approve restart** → run with `--takeover` (or `OPERA_CLI_TAKEOVER=1`). Restarts with a debug port, restores tabs, attaches — drives the real browser thereafter.
|
|
79
|
+
- **They decline** → no flag → separate profile at `~/.opera-browser-cli/profile` (they sign in there; AI may then return exit `4` — surface it).
|
|
80
|
+
- `opera-browser-cli launch-args` prints the flags to start Opera attachable so a restart is never needed later.
|
|
81
|
+
|
|
50
82
|
## Sign-in errors
|
|
51
83
|
|
|
52
|
-
If
|
|
84
|
+
If an AI command fails with `AUTH_REQUIRED` (exit code 4) — not signed in, no subscription, or consent pending — tell the user to run `opera-browser-cli login`, which opens the Opera account page in a visible window. `opera-browser-cli login --check` verifies the current state. Run `opera-browser-cli doctor` to diagnose anything else.
|
package/dist/src/bridge.d.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
14
14
|
import type { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
15
15
|
import { type IncomingMessage, type Server, type ServerResponse } from "node:http";
|
|
16
|
+
import { type BridgeHealth } from "./identity.js";
|
|
16
17
|
export interface LastSnapshotCache {
|
|
17
18
|
raw: string;
|
|
18
19
|
pageUrl: string | null;
|
|
@@ -44,10 +45,38 @@ export interface BridgeClient {
|
|
|
44
45
|
close(): Promise<void>;
|
|
45
46
|
}
|
|
46
47
|
export declare function isBridgeClientConnected(client: BridgeClient): Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* "Usable" health for the bridge: the MCP server is up AND, when the bridge is
|
|
50
|
+
* in attach mode, the browser at the attach URL is actually reachable.
|
|
51
|
+
*
|
|
52
|
+
* In attach mode devtools-mcp stays connected over stdio even when the browser
|
|
53
|
+
* it points at is gone (it reaches for the browser lazily on a tool call), so
|
|
54
|
+
* MCP liveness alone cannot tell that a bridge is wedged on a dead URL. Probing
|
|
55
|
+
* the attach endpoint directly keeps `/health` honest, which lets the CLI stop
|
|
56
|
+
* reusing a wedged bridge and rebuild it against the current target.
|
|
57
|
+
*/
|
|
58
|
+
export declare function isBridgeHealthConnected(client: BridgeClient): Promise<boolean>;
|
|
47
59
|
export declare function getErrorMessage(error: unknown): string;
|
|
48
60
|
export declare function extractToolText(content: BridgeContentBlock[]): string;
|
|
49
61
|
export declare function parseBridgeCallPayload(body: string): BridgeCallPayload;
|
|
50
62
|
export declare function resolveBridgeScript(importMetaDir: string): string;
|
|
63
|
+
export type BridgeLauncher = {
|
|
64
|
+
ok: true;
|
|
65
|
+
command: string;
|
|
66
|
+
args: string[];
|
|
67
|
+
} | {
|
|
68
|
+
ok: false;
|
|
69
|
+
reason: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Decide how to launch the bridge process.
|
|
73
|
+
*
|
|
74
|
+
* Prefers the built JavaScript. The TypeScript entrypoint is used only in a
|
|
75
|
+
* source checkout (or under OPERA_CLI_DEV=1), and only when tsx is already
|
|
76
|
+
* installed — never via `npx`, which blocks on an install prompt when the
|
|
77
|
+
* package is uncached and would hang invisibly behind a redirected stdio.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolveBridgeLauncher(importMetaDir: string, execPath?: string): BridgeLauncher;
|
|
51
80
|
/** True when a Host/Origin host component (with optional port) is loopback. */
|
|
52
81
|
export declare function isLoopbackHost(hostHeader: string | undefined): boolean;
|
|
53
82
|
/** Browsers always attach Origin; the CLI never does. Absent = trusted; present = must be loopback. */
|
|
@@ -65,9 +94,48 @@ export interface BridgeAccessResult {
|
|
|
65
94
|
*/
|
|
66
95
|
export declare function checkRequestAccess(req: IncomingMessage, token: string | null, requireToken: boolean): BridgeAccessResult;
|
|
67
96
|
export declare function generateBridgeToken(): string;
|
|
97
|
+
export declare function buildHealth(connected: boolean): BridgeHealth;
|
|
68
98
|
export declare function handleBridgeRequest(client: BridgeClient, req: IncomingMessage, res: ServerResponse, captureNextId?: () => Promise<string>, token?: string | null): Promise<void>;
|
|
69
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Build the HTTP server.
|
|
101
|
+
*
|
|
102
|
+
* `resolve` is called per request rather than the client being captured up
|
|
103
|
+
* front, so the port can be bound before the MCP connection exists. Until it
|
|
104
|
+
* returns a client every route answers 503 with a well-formed health body —
|
|
105
|
+
* which is exactly what a caller probing /health during startup should see.
|
|
106
|
+
*/
|
|
107
|
+
export declare function createBridgeServer(resolve: () => {
|
|
108
|
+
client: BridgeClient | null;
|
|
109
|
+
captureNextId?: () => Promise<string>;
|
|
110
|
+
}, token?: string | null): Server;
|
|
111
|
+
/** Exit code signalling "port taken, try the next one" (EX_TEMPFAIL). */
|
|
112
|
+
export declare const EXIT_PORT_IN_USE = 75;
|
|
113
|
+
/**
|
|
114
|
+
* Whether to launch a visible browser.
|
|
115
|
+
*
|
|
116
|
+
* Headless is the safe default for a tool — it is the only thing that works on
|
|
117
|
+
* a server with no display. But a configured Opera binary means the user wants
|
|
118
|
+
* *their* browser, and every Opera AI feature needs a window: sign-in and
|
|
119
|
+
* consent cannot be completed headlessly, so a headless AI command fails on a
|
|
120
|
+
* state the user has no way to fix.
|
|
121
|
+
*
|
|
122
|
+
* So: headed when an Opera executable is configured, headless otherwise, and
|
|
123
|
+
* OPERA_CLI_HEADED=0 or =1 overrides either way. A machine with no Opera
|
|
124
|
+
* installed — CI, Docker, a plain-Chrome setup — keeps the old behaviour.
|
|
125
|
+
*/
|
|
126
|
+
export declare function shouldRunHeaded(): boolean;
|
|
70
127
|
export declare function buildTransportArgs(): string[];
|
|
128
|
+
export interface McpBinStatus {
|
|
129
|
+
bin: string;
|
|
130
|
+
found: boolean;
|
|
131
|
+
source: "env" | "dependency" | "path";
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Where opera-devtools-mcp is coming from, and whether it is actually there.
|
|
135
|
+
* Used by `doctor` so a missing MCP server is named before it costs a failed
|
|
136
|
+
* bridge start.
|
|
137
|
+
*/
|
|
138
|
+
export declare function resolveMcpBinStatus(): McpBinStatus;
|
|
71
139
|
/**
|
|
72
140
|
* Wraps transport.send to intercept outgoing JSON-RPC request IDs so each
|
|
73
141
|
* streaming callTool call can register its own log writer before the first
|