Repository navigation
v1.0.4 — 360-true ElfPad, audit hardening, on PyPI
Everything since v1.0.1 — two external-audit fix packs, one hardware-verified gamepad fix, and PyPI.
Install
pip install elfdeckaiElfDeckAI is now on PyPI. The git route keeps working too.
ElfPad: analog-only triggers (hardware-verified)
ElfPad no longer declares digital BTN_TL2/BTN_TR2 bits. A real Xbox 360 pad
doesn't have them, and declaring them shifted Select/Start/Guide/L3/R3 two
button indices off the stock layout for index-based consumers (SDL's 360
mapping, joydev). press / down / up on l2/r2 now drive the analog
trigger axes, exactly like the real pad. Confirmed with evtest against a
real 360 pad on a Steam Deck, then fixed and re-verified on the same Deck.
A unit test pins the button set to the real pad's codes.
MCP server: strict validation (1.0.2)
Tool arguments are validated against the advertised schemas before anything
touches a daemon — unknown or missing arguments, wrong types (a bool is not
an int), out-of-range values and non-object params are rejected with proper
JSON-RPC errors. Request lines are bounded at 1 MiB with draining, and
NaN/Infinity literals are refused.
Audit fix pack (1.0.3)
- Each command now emits as a single atomic evdev frame (one SYN per
command) in all three daemons. - Held state is tracked before events are emitted, so cleanup can never
miss a stuck key or button. - Single-instance lock per daemon, and a clear error when /dev/uinput
can't be opened instead of a traceback. - Daemons log accepted commands to stderr (journalctl / your service log).
- A tools/call sent as a notification is executed but never answered, per
the JSON-RPC spec. - The udev rule is now 70-elfdeckai-uinput.rules — uaccess tags are
consumed earlier in boot than the old 99- name ran. - ElfMouse has its own USB product ID instead of sharing ElfKey's.
Notes
148 tests pass. ElfKey, ElfPad and ElfMouse have all run on a real Steam
Deck; the Pokémon story in the README was driven by ElfKey before Pad and
Mouse existed.