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.
Files changed (3) hide show
  1. package/README.md +57 -3
  2. package/bin/jev-ra.js +87 -2
  3. package/package.json +12 -7
package/README.md CHANGED
@@ -1,5 +1,59 @@
1
- # jev-ra
1
+ # jev-ra (npm launcher)
2
2
 
3
- Browser use for coding agents (Claude Code, Codex, any MCP client), driven by TypeSafe Jev decisions.
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 version only reserves the name. The first working release is in progress at https://github.com/brnyxx/jev-ra.
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
- console.error("jev-ra 0.0.1 only reserves the package name. The first release is in progress: https://github.com/brnyxx/jev-ra");
3
- process.exit(2);
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.1",
4
- "description": "Browser use for coding agents, driven by TypeSafe Jev decisions. Name reserved; first release coming soon.",
5
- "bin": { "jev-ra": "bin/jev-ra.js" },
6
- "files": ["bin", "README.md"],
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
- "engines": { "node": ">=20" }
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
  }