jev-ra 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -3
- package/bin/jev-ra.js +87 -2
- package/package.json +12 -7
package/README.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
|
-
# jev-ra
|
|
1
|
+
# jev-ra (npm launcher)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A fast browser-use layer for CLI coding agents. Claude Code, Codex, or any MCP client hands jev-ra a
|
|
4
|
+
goal; TypeSafe Jev picks the operation and the target element for every step in one round trip, in
|
|
5
|
+
about 300 ms. Measured 3-5x faster than browser-use on the same tasks, same Chrome, same key.
|
|
4
6
|
|
|
5
|
-
This
|
|
7
|
+
**This package contains no jev-ra code.** It is a launcher: it finds [uv](https://docs.astral.sh/uv/),
|
|
8
|
+
offers to install it the first time, and then runs the Python package from PyPI through `uvx`,
|
|
9
|
+
pinned to this package's own version. Use it when you do not want to set Python up yourself.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
export OPENROUTER_API_KEY=sk-or-...
|
|
13
|
+
npx -y jev-ra install claude # or: install codex
|
|
14
|
+
npx -y jev-ra doctor
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`install` registers `uvx jev-ra mcp` as an MCP server in Claude Code or Codex and forwards the key
|
|
18
|
+
from your environment without printing it. `doctor` ends with one live decision and its latency:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
decision: DONE in 314 ms via typesafe/jev-1.13
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
From the shell, every subcommand of [the CLI](https://github.com/brnyxx/jev-ra/blob/main/docs/USAGE.md)
|
|
25
|
+
works the same way:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npx -y jev-ra run https://en.wikipedia.org/wiki/Main_Page "Open the Godel incompleteness article." \
|
|
29
|
+
--value "search_query=Godel incompleteness theorems"
|
|
30
|
+
npx -y jev-ra search "python 3.12 release date" "the exact release date, with source"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Any other MCP client
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{ "mcpServers": { "jev-ra": { "command": "npx", "args": ["-y", "jev-ra", "mcp"] } } }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The server inherits the environment it is started in, so the key can come from there. `uvx` in place
|
|
40
|
+
of `npx -y` does the same thing without Node.
|
|
41
|
+
|
|
42
|
+
## Flags this launcher understands
|
|
43
|
+
|
|
44
|
+
| flag | effect |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `--yes` | install uv without asking, when it is missing |
|
|
47
|
+
| `--no-install` | never install uv; print how to do it and exit 2 |
|
|
48
|
+
|
|
49
|
+
Neither reaches the Python side. `JEV_RA_FROM` overrides the pinned package specifier, for a local
|
|
50
|
+
wheel or a fork: `JEV_RA_FROM=./jev_ra-0.1.0-py3-none-any.whl npx jev-ra --version`.
|
|
51
|
+
|
|
52
|
+
## Requirements
|
|
53
|
+
|
|
54
|
+
Node 20 or newer, and a Chrome, Chromium or Edge installed. jev-ra launches its own Chrome on a
|
|
55
|
+
dedicated profile, or attaches to `BU_CDP_URL` if you set it; `JEV_RA_CHROME` names a binary it
|
|
56
|
+
would not find on its own. You need an API key in the environment: `OPENROUTER_API_KEY` (no
|
|
57
|
+
TypeSafe account needed) or `TYPESAFE_API_KEY`.
|
|
58
|
+
|
|
59
|
+
MIT licensed. Source, docs, benchmarks and the real-site corpus: https://github.com/brnyxx/jev-ra
|
package/bin/jev-ra.js
CHANGED
|
@@ -1,3 +1,88 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
// A launcher, not a reimplementation: every argument goes to `uvx jev-ra@<pinned>`.
|
|
3
|
+
// uv builds and caches the Python environment, so there is nothing to install first.
|
|
4
|
+
|
|
5
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
6
|
+
import { createInterface } from "node:readline";
|
|
7
|
+
import process from "node:process";
|
|
8
|
+
|
|
9
|
+
export const PINNED = "0.1.0";
|
|
10
|
+
export const INSTALL_HINT = [
|
|
11
|
+
"jev-ra runs on uv, which is not on PATH.",
|
|
12
|
+
"Install it with one of:",
|
|
13
|
+
" curl -LsSf https://astral.sh/uv/install.sh | sh (macOS, Linux)",
|
|
14
|
+
" powershell -c \"irm https://astral.sh/uv/install.ps1 | iex\" (Windows)",
|
|
15
|
+
" brew install uv",
|
|
16
|
+
"then run this command again.",
|
|
17
|
+
].join("\n");
|
|
18
|
+
|
|
19
|
+
export function findUv(which = whichSync) {
|
|
20
|
+
return which("uv");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function whichSync(command) {
|
|
24
|
+
const finder = process.platform === "win32" ? "where" : "which";
|
|
25
|
+
const found = spawnSync(finder, [command], { encoding: "utf8" });
|
|
26
|
+
if (found.status !== 0) return null;
|
|
27
|
+
const first = (found.stdout || "").split(/\r?\n/).find(Boolean);
|
|
28
|
+
return first ? first.trim() : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function splitArgs(argv) {
|
|
32
|
+
const passthrough = argv.filter((item) => item !== "--yes" && item !== "--no-install");
|
|
33
|
+
return {
|
|
34
|
+
args: passthrough,
|
|
35
|
+
assumeYes: argv.includes("--yes"),
|
|
36
|
+
allowInstall: !argv.includes("--no-install"),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// JEV_RA_FROM lets CI and anyone pinning a fork point uvx at a wheel or a git ref instead.
|
|
41
|
+
export function uvxArgs(args, pinned = PINNED, from = process.env.JEV_RA_FROM) {
|
|
42
|
+
return ["--from", from || `jev-ra==${pinned}`, "jev-ra", ...args];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function confirm(question) {
|
|
46
|
+
if (!process.stdin.isTTY) return false;
|
|
47
|
+
const reader = createInterface({ input: process.stdin, output: process.stderr });
|
|
48
|
+
try {
|
|
49
|
+
const answer = await new Promise((resolve) => reader.question(`${question} [y/N] `, resolve));
|
|
50
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
51
|
+
} finally {
|
|
52
|
+
reader.close();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function installUv() {
|
|
57
|
+
const command =
|
|
58
|
+
process.platform === "win32"
|
|
59
|
+
? ["powershell", ["-c", "irm https://astral.sh/uv/install.ps1 | iex"]]
|
|
60
|
+
: ["sh", ["-c", "curl -LsSf https://astral.sh/uv/install.sh | sh"]];
|
|
61
|
+
execFileSync(command[0], command[1], { stdio: "inherit" });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
65
|
+
const { args, assumeYes, allowInstall } = splitArgs(argv);
|
|
66
|
+
let uv = findUv();
|
|
67
|
+
if (!uv && allowInstall) {
|
|
68
|
+
const agreed = assumeYes || (await confirm("Install uv now?"));
|
|
69
|
+
if (agreed) {
|
|
70
|
+
installUv();
|
|
71
|
+
uv = findUv();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!uv) {
|
|
75
|
+
process.stderr.write(`${INSTALL_HINT}\n`);
|
|
76
|
+
return 2;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
execFileSync("uvx", uvxArgs(args), { stdio: "inherit" });
|
|
80
|
+
return 0;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
return typeof error.status === "number" ? error.status : 1;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
87
|
+
process.exitCode = await main();
|
|
88
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jev-ra",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"repository": { "type": "git", "url": "https://github.com/brnyxx/jev-ra" },
|
|
8
|
-
"homepage": "https://github.com/brnyxx/jev-ra",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A fast browser-use layer for CLI coding agents: MCP server, CLI and Python API. This package is a launcher; it runs the Python tool through uv.",
|
|
5
|
+
"keywords": ["browser", "browser-automation", "mcp", "mcp-server", "agent", "ai-agent", "cdp",
|
|
6
|
+
"chrome", "automation", "claude-code", "codex", "cursor", "typesafe", "jev", "web-agent"],
|
|
9
7
|
"license": "MIT",
|
|
10
8
|
"author": "Brian Kim",
|
|
11
|
-
"
|
|
9
|
+
"homepage": "https://github.com/brnyxx/jev-ra",
|
|
10
|
+
"repository": { "type": "git", "url": "git+https://github.com/brnyxx/jev-ra.git", "directory": "npm" },
|
|
11
|
+
"bugs": { "url": "https://github.com/brnyxx/jev-ra/issues" },
|
|
12
|
+
"bin": { "jev-ra": "bin/jev-ra.js" },
|
|
13
|
+
"type": "module",
|
|
14
|
+
"engines": { "node": ">=20" },
|
|
15
|
+
"files": ["bin/", "README.md"],
|
|
16
|
+
"scripts": { "test": "node --test test/*.test.mjs" }
|
|
12
17
|
}
|