@lardexx/arenacode 2.7.0 → 2.9.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 CHANGED
@@ -30,7 +30,8 @@ Published as [`@lardexx/arenacode`](https://www.npmjs.com/package/@lardexx/arena
30
30
  is blocked by npm's similarity check against the existing `arena-code` package, so the scope is required. The
31
31
  command is plain `arenacode` in every case.
32
32
 
33
- Requires Node.js 18 or newer. No runtime dependencies.
33
+ Requires Node.js 18 or newer. One runtime dependency, `koffi` (prebuilt FFI bindings for Windows, macOS and Linux,
34
+ no compiler needed): it is how the client reaches `windows-use.dll` on Windows and `libX11`/`libXtst` on Linux.
34
35
 
35
36
  ## Terminal UI
36
37
 
@@ -148,11 +149,29 @@ from the same bridge request the desktop app answers:
148
149
  | `ui apps` | the Start menu (Windows), `/Applications` (macOS), `.desktop` entries (Linux) |
149
150
  | `ui multi-select`, `ui multi-edit` | built from the primitives above |
150
151
 
151
- No extra install on **Windows** (PowerShell + `user32.dll`). **macOS**: grant Accessibility to your terminal, and
152
- `brew install cliclick` for the mouse. **Linux** (X11): `sudo apt install xdotool wmctrl imagemagick`; on Wayland
153
- `xdotool` cannot inject input, so Computer Agent needs XWayland. What this client does *not* have is the desktop's UI
154
- Automation tree: `ui state` returns windows and pixels, with `interactive_elements` empty, and `--annotated`
155
- screenshots are plain screenshots.
152
+ **Windows** runs the *same* DLL the desktop client runs. `windows-use.dll` ships inside this package
153
+ (`vendor/windows-use/windows-use.dll`, extracted from `ArenaCode-x64.exe`'s resources) and is called over FFI with
154
+ [koffi](https://koffi.dev) — `wu_call_json` / `wu_free` / `wu_version` — so nothing has to be installed and nothing is
155
+ reimplemented: the UI Automation tree, `SendInput` unicode typing, extended keys for arrows/navigation, Start-menu apps,
156
+ annotated screenshots and fuzzy window matching are all the desktop's own code. The tools and argument names the client
157
+ sends are the ones in the DLL's symbol table (`click_tool`, `move_tool`, `mouse_button_tool`, `scroll_tool`, `type_tool`,
158
+ `shortcut_tool`, `wait_tool`, `app_tool`, `apps_list_tool`, `desktop_state`), and the answers are the same JSON the
159
+ desktop returns (`{"ok":true,"result":…}`, `bounding_box`, `center`, `control_type`, `interactive_elements_text`,
160
+ `screenshot_png_base64` …). `ARENACODE_WINDOWS_USE_DLL` points the client at another copy; if the file is missing it is
161
+ carved out of an installed `ArenaCode-x64.exe` (`ARENACODE_EXE`) by the client's own PE resource reader.
162
+
163
+ **Linux** talks to the X server directly: `libX11` + `libXtst` through the same FFI layer, **no external tools** — no
164
+ `xdotool`, no `wmctrl`, no `scrot`, no ImageMagick. The pointer is moved with `XTestFakeMotionEvent`, clicks and the wheel
165
+ are `XTestFakeButtonEvent` with buttons 1–5, keys are keysyms mapped to keycodes with `XGetKeyboardMapping`, characters
166
+ outside the keymap borrow an unused keycode with `XChangeKeyboardMapping` and give it back a moment later, windows come
167
+ from `XQueryTree` + `XGetGeometry` + `XTranslateCoordinates` + `_NET_WM_NAME`, focus from `XSetInputFocus`, and
168
+ screenshots are `XGetImage` + `XGetPixel` encoded to PNG by the client itself (zlib). This is what makes it testable:
169
+ `node test/native.js` runs it against a real X server (Xvfb is enough) — a window is created, the client types into it
170
+ and the X events the server delivered are compared with the requested keycodes, chords, buttons and pixels. On Wayland
171
+ the XWayland display is used. `ui app launch` still starts the program's own `.desktop` command; nothing else is spawned.
172
+
173
+ **macOS**: grant Accessibility to your terminal, and `brew install cliclick` for the mouse. On macOS/Linux the
174
+ accessibility tree is not read: `ui state` returns windows and geometry as elements.
156
175
 
157
176
  **Ask and Proceed / Proceed.** The desktop's Settings switch, `ctrl+x a` here (also `/ask`, `/proceed`,
158
177
  `--proceed`, and `arenacode config set approval proceed`). The default, **Ask and Proceed**, asks before commands,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lardexx/arenacode",
3
- "version": "2.7.0",
4
- "description": "Terminal client for ArenaCode: talks to an arena-bridge, streams the Agent Mode timeline, and runs local commands and file operations on your PC. Node port of the ArenaCode desktop client.",
3
+ "version": "2.9.0",
4
+ "description": "Terminal client for ArenaCode: talks to an arena-bridge, streams the Agent Mode timeline, and runs local commands, file operations and computer automation on your PC (windows-use.dll on Windows, Xlib/XTest on Linux, osascript on macOS). Node port of the ArenaCode desktop client.",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
7
7
  "bin": {
@@ -16,10 +16,11 @@
16
16
  "src/",
17
17
  "docs/",
18
18
  "README.md",
19
- "LICENSE"
19
+ "LICENSE",
20
+ "vendor/"
20
21
  ],
21
22
  "scripts": {
22
- "test": "node test/integration.js && node test/parity.js && node test/automation.js"
23
+ "test": "node test/integration.js && node test/parity.js && node test/automation.js && node test/native.js"
23
24
  },
24
25
  "keywords": [
25
26
  "arenacode",
@@ -30,5 +31,8 @@
30
31
  ],
31
32
  "publishConfig": {
32
33
  "access": "public"
34
+ },
35
+ "dependencies": {
36
+ "koffi": "^3.3.6"
33
37
  }
34
38
  }
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ // koffi is the only native piece: it ships prebuilt binaries for Windows, macOS and
4
+ // Linux, so the client needs no compiler and no helper executables (xdotool, cliclick,
5
+ // scrot …). Everything below talks to the OS libraries directly.
6
+
7
+ let koffi = null;
8
+ let loadError = null;
9
+ try {
10
+ // eslint-disable-next-line global-require
11
+ koffi = require('koffi');
12
+ } catch (err) {
13
+ loadError = err;
14
+ }
15
+
16
+ function available() {
17
+ return Boolean(koffi);
18
+ }
19
+
20
+ function requireFfi() {
21
+ if (!koffi) {
22
+ throw new Error(
23
+ `native bindings unavailable (koffi): ${loadError ? loadError.message : 'not installed'}`
24
+ );
25
+ }
26
+ return koffi;
27
+ }
28
+
29
+ const cache = new Map();
30
+
31
+ /** lua: loads (and caches) a shared library by name. */
32
+ function lib(name) {
33
+ if (cache.has(name)) return cache.get(name);
34
+ const k = requireFfi();
35
+ let handle = null;
36
+ try {
37
+ handle = k.load(name);
38
+ } catch (err) {
39
+ cache.set(name, null);
40
+ return null;
41
+ }
42
+ cache.set(name, handle);
43
+ return handle;
44
+ }
45
+
46
+ /** Defines a function once per library: fn(lib, 'sig', 'name') */
47
+ function fn(library, name, signature) {
48
+ const holder = lib(library);
49
+ if (!holder) return null;
50
+ const key = `${library}#${name}`;
51
+ if (cache.has(key)) return cache.get(key);
52
+ let defined = null;
53
+ try {
54
+ defined = holder.func(signature);
55
+ } catch {
56
+ defined = null;
57
+ }
58
+ cache.set(key, defined);
59
+ return defined;
60
+ }
61
+
62
+ module.exports = { available, lib, fn, requireFfi, loadError };