feat(uno-q): wire the native matrix_count path (relay + allowlist + skill)

Adds the `count N` command to the host matrix-relay, allowlists + auto-approves
matrix_count for the default agent, and steers the led-matrix skill to use
matrix_count for "count to N once a second" instead of flashing a sketch (which
fails in the App Lab container). Pairs with the zeroclaw sketch/tool changes.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-22 19:04:34 -07:00
co-authored by Claude Opus 4.8
parent 8ea9c256b4
commit 909b9a7671
4 changed files with 14 additions and 5 deletions
+2 -2
View File
@@ -82,8 +82,8 @@ prompt_injection_mode = "compact"
# without a human approver (the webhook path is non-interactive). # without a human approver (the webhook path is non-interactive).
[risk_profiles.default] [risk_profiles.default]
level = "supervised" level = "supervised"
allowed_tools = ["matrix_pattern", "matrix_text", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search"] allowed_tools = ["matrix_pattern", "matrix_text", "matrix_count", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search"]
auto_approve = ["matrix_pattern", "matrix_text", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search"] auto_approve = ["matrix_pattern", "matrix_text", "matrix_count", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search"]
[runtime_profiles.unoq] [runtime_profiles.unoq]
agentic = true agentic = true
+3
View File
@@ -34,6 +34,9 @@ def handle(conn):
elif cmd == "text" and len(parts) >= 2: elif cmd == "text" and len(parts) >= 2:
Bridge.call("matrix_text", " ".join(parts[1:])) Bridge.call("matrix_text", " ".join(parts[1:]))
conn.sendall(b"ok\n") conn.sendall(b"ok\n")
elif cmd == "count" and len(parts) >= 2:
Bridge.call("matrix_count", int(parts[1]))
conn.sendall(b"ok\n")
elif cmd == "i2c": elif cmd == "i2c":
r = Bridge.call("i2c_scan") r = Bridge.call("i2c_scan")
conn.sendall(f"{r}\n".encode()) conn.sendall(f"{r}\n".encode())
+2 -2
View File
@@ -203,8 +203,8 @@ prompt_injection_mode = "compact"
[risk_profiles.default] [risk_profiles.default]
level = "supervised" level = "supervised"
allowed_tools = ["matrix_pattern", "matrix_text", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search"] allowed_tools = ["matrix_pattern", "matrix_text", "matrix_count", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search"]
auto_approve = ["matrix_pattern", "matrix_text", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search", "memory_recall", "web_search_tool", "web_fetch", "calculator", "glob_search", "image_info", "weather", "tool_search", "browser", "browser_open"] auto_approve = ["matrix_pattern", "matrix_text", "matrix_count", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search", "memory_recall", "web_search_tool", "web_fetch", "calculator", "glob_search", "image_info", "weather", "tool_search", "browser", "browser_open"]
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep", "find", "echo", "pwd", "wc", "head", "tail", "date", "df", "du", "uname", "uptime", "hostname", "python", "python3", "pip", "node", "free"] allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep", "find", "echo", "pwd", "wc", "head", "tail", "date", "df", "du", "uname", "uptime", "hostname", "python", "python3", "pip", "node", "free"]
allowed_roots = [] allowed_roots = []
always_ask = [] always_ask = []
+7 -1
View File
@@ -18,8 +18,14 @@ compile, no flash:
/ print `<text>`" request (e.g. `text="GO CLAWS"`). / print `<text>`" request (e.g. `text="GO CLAWS"`).
- **`matrix_pattern`** — switch to a preset animation: `off, rain, heart, wave, - **`matrix_pattern`** — switch to a preset animation: `off, rain, heart, wave,
sparkle, checker, solid, blink`. sparkle, checker, solid, blink`.
- **`matrix_count`** — count `0..N` on the matrix, **one number per second**. Use
for ANY "count to N / count up / print the numbers 0..N once a second" request
(e.g. `n=100`). The MCU runs the timed loop itself, so this is a single instant
call — do **NOT** write and flash a counting sketch. Flashing a timed loop is the
wrong tool: it takes ~90s, it fails inside the App Lab container, and it
overwrites the resident responder.
**Always reach for these tools first** for text or a preset animation. They take **Always reach for these tools first** for text, a preset animation, or a count. They take
effect in under a second. Do **NOT** write and flash a sketch for these — flashing effect in under a second. Do **NOT** write and flash a sketch for these — flashing
takes ~90s **and overwrites the resident responder, breaking `matrix_text` / takes ~90s **and overwrites the resident responder, breaking `matrix_text` /
`matrix_pattern` until it's re-flashed.** Only write + flash a sketch (below) for a `matrix_pattern` until it's re-flashed.** Only write + flash a sketch (below) for a