@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 +25 -6
- package/package.json +8 -4
- package/src/automation/ffi.js +62 -0
- package/src/automation/linux.js +809 -0
- package/src/automation/win-dll.js +493 -0
- package/src/automation.js +430 -92
- package/src/local.js +6 -17
- package/vendor/windows-use/windows-use.dll +0 -0
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.
|
|
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
|
-
|
|
152
|
-
`
|
|
153
|
-
`
|
|
154
|
-
Automation tree
|
|
155
|
-
screenshots are
|
|
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.
|
|
4
|
-
"description": "Terminal client for ArenaCode: talks to an arena-bridge, streams the Agent Mode timeline, and runs local commands
|
|
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 };
|