skill / adom-panel-control
!

Not installable via adompkg

This skill has no published release. adompkg install kyle/adom-panel-control will not work until a maintainer publishes a tarball with install.sh and uninstall.sh.

See the publishing docs for the package.json schema and tarball layout required to ship this skill.


name: adom-panel-control
description: Use when the user wants to open, close, add, or remove a panel; change the workspace layout; resize a split; show or hide a sensor view, camera, log, control panel, or any Adom editor panel; or asks "what panels are available". Examples: "open the 3D viewer", "add a web view tab", "close the robot log", "resize the split to 70/30", "show me the motor control panel", "what panels can I open?".
user-invokable: true

Adom Panel Control

The Adom web app displays a set of interactive panels such as the 3D layout editor and schematic designer. Panels provide live views, controls, and data for the workcell and its hardware. Manipulate the Adom editor workspace: add/remove tabs, resize splits, and query the layout.

Environment

All API calls require:

  • Base URL: https://hydrogen.adom.inc/api/workspaces/editor/{owner}/{repo}/current
  • JSON parsing: jq is not available in the container. Use python3 -m json.tool to pretty-print JSON output instead.
  • Auth: X-Api-Key header. Obtain the key by reading /var/run/adom/api-key — this file is always present in the container, is read-only, and contains the token with no leading or trailing whitespace:
    API_KEY=$(cat /var/run/adom/api-key)
    
    Fall back to env vars (ADOM_API_KEY, API_KEY, X-Api-Key) only if that file is missing. Ask the user only as a last resort.

Critical Rules — Read Before Doing Anything

  • NEVER use PUT to replace the full layout. It wipes the entire workspace and breaks node IDs. Always use granular POST /tabs, DELETE /tabs, and PATCH /splits calls — even for complex multi-step changes. Build up the desired layout one operation at a time.
  • NEVER echo or display the API key in tool output. Store it in a shell variable — never cat it on its own or log it.
  • Add before removing when swapping tabs in a leaf — the API returns 400 if you try to remove the last tab, so always add the new tab first, then remove old ones.
  • Remove tabs from highest index first when removing multiple tabs from a leaf, to avoid index shifting.
  • Re-fetch the layout before each batch of operations — state can change between calls. Always confirm current node IDs and tab indices are still valid.

Workflow

Always follow this order when making changes:

  1. Setup — resolve credentials, repo, and target user (ask once, remember for the session)
  2. GET the current layout to find leaf node IDs
  3. Identify the correct leaf id for where the user wants the tab placed
  4. Look up the panelType full ID from the catalog below
  5. POST/DELETE/PATCH to make the change
  6. Confirm success to the user

Step 0 — Setup: resolve credentials, repo, and target user

At the start of the session, if OWNER, REPO (THIS IS AN ADOM REPO NOT A GITHUB REPO), or API_KEY are not yet known, ask the user:

"What is the Adom owner (username or org) and repository name for this project?"

Remember the answers for the rest of the conversation — do not ask again.

Then read the API key and set up the base URL:

API_KEY=$(cat /var/run/adom/api-key)
BASE="https://hydrogen.adom.inc/api/workspaces/editor/$OWNER/$REPO/current"

Discover the target user. Workspaces are scoped per-user. You must discover who has an open editor:

curl -s -H "X-Api-Key: $API_KEY" "$BASE/users" | python3 -m json.tool
# → { "users": [{ "username": "kcknox" }] }
  • One user (most common): auto-detected by the server — no extra header needed. Set TARGET_HEADER="".
  • Multiple users: ask the user which person's workspace to modify. Remember the choice and set:
    TARGET_HEADER='-H "X-Target-Username: <chosen-username>"'
    
  • Zero users: the editor is not open in any browser. Tell the user to open the editor first.

Save OWNER, REPO, API_KEY, BASE, and TARGET_HEADER (if needed) in your memory file so you don't repeat this setup.

Step 1 — GET current layout

curl -s -H "X-Api-Key: $API_KEY" $TARGET_HEADER "$BASE" | python3 -m json.tool

Parse the response to find:

  • All leaf nodes and their id values (needed for adding/removing tabs)
  • All split nodes and their id values (needed for resizing)
  • The tabs array on each leaf and activeTabIndex

Step 2 — POST: Add a tab

curl -s -X POST \
  -H "X-Api-Key: $API_KEY" $TARGET_HEADER \
  -H "Content-Type: application/json" \
  -d '{"panelId":"<leaf-id>","panelType":"<full-panel-id>"}' \
  "$BASE/tabs"

Returns { "tabId": "<uuid>" } on success.

If the user doesn't specify which panel (leaf) to add to and there is more than one leaf, ask them where they want it placed, or place it in the largest/most relevant leaf.

Step 3 — DELETE: Remove a tab

curl -s -X DELETE \
  -H "X-Api-Key: $API_KEY" $TARGET_HEADER \
  -H "Content-Type: application/json" \
  -d '{"panelId":"<leaf-id>","tabIndex":<number>}' \
  "$BASE/tabs"

tabIndex is 0-based. GET the layout first to confirm the correct index.

Finding a tab by name: When the user says "close the Robot Log", GET the layout, walk every leaf node, find the tab whose panelType matches the catalog ID (e.g. adom/a1b2c3d4-bbbb-4000-a000-00000000000b), then DELETE using that leaf's id and the tab's array index.

Cannot remove the last tab in a leaf — the API returns 400. Inform the user if this happens.

Step 4 — PATCH: Resize a split

curl -s -X PATCH \
  -H "X-Api-Key: $API_KEY" $TARGET_HEADER \
  -H "Content-Type: application/json" \
  -d '{"ratio":0.3}' \
  "$BASE/splits/<split-id>"

ratio is the fraction given to the first child (0.1–0.9). So "70/30" → ratio: 0.7.

Step 5 — PUT: PROHIBITED

DO NOT use PUT. It wipes the entire workspace. There is no valid use case for an AI agent. Use POST /tabs, DELETE /tabs, and PATCH /splits instead.

Step 6 — GET /events: SSE event stream (optional, for real-time sync)

curl -s -H "X-Api-Key: $API_KEY" "$BASE/events"

Emits { "type": "connected" } once, then { "type": "workspace_updated" } on every mutation. The container is typically the mutator, not the listener — this is mainly useful if you need to wait for another actor's change before proceeding.

Layout Structure Reference

The workspace is a binary tree:

  • SplitNode{ type: "split", id, direction: "horizontal"|"vertical", ratio: 0.1–0.9, first: PanelNode, second: PanelNode }
  • LeafNode{ type: "leaf", id, tabs: PanelTab[], activeTabIndex: number }
  • PanelTab{ id, panelType: "<full-panel-id>", panelState?: { ... } }

Singleton Panels

These may only appear once in the entire workspace. Check the current layout before adding — if already present, tell the user rather than adding a duplicate.

Full ID Name
adom/a1b2c3d4-1111-4000-a000-000000000001 3D Viewer
adom/a1b2c3d4-0012-4000-a000-000000000012 Schematic Editor

Panel Catalog

Development

Full ID Name Description
adom/a1b2c3d4-eeee-4000-a000-00000000000e Visual Studio Code Embedded VS Code editor
adom/a1b2c3d4-0012-4000-a000-000000000012 Schematic Editor Circuit schematic editor (singleton)
adom/a1b2c3d4-0014-4000-a000-000000000014 Script Runner Execute automation scripts

Control

Full ID Name Description
adom/a1b2c3d4-3333-4000-a000-000000000003 Motor Control XRP robot motor speed/direction
adom/a1b2c3d4-4444-4000-a000-000000000004 LED Control XRP robot LED color/brightness
adom/a1b2c3d4-5555-4000-a000-000000000005 Servo Control XRP robot servo angle
adom/a1b2c3d4-001b-4000-a000-00000000001b Drone Control Drone flight control and telemetry
adom/a1b2c3d4-001c-4000-a000-00000000001c ESC Control Electronic Speed Controller
adom/a1b2c3d4-0010-4000-a000-000000000010 Lights Control RGB/white LED strip with color wheel
adom/a1b2c3d4-0022-4000-a000-000000000022 Workcell Power Power supply voltage/current limits
adom/a1b2c3d4-0023-4000-a000-000000000023 Basic Control Panel GPIO pin modes and digital write

Visualization

Full ID Name Description
adom/a1b2c3d4-1111-4000-a000-000000000001 3D Viewer Workcell/robot 3D view (singleton)
adom/a1b2c3d4-001a-4000-a000-00000000001a Babylon OTB Babylon.js 3D viewer with OTB support
adom/a1b2c3d4-6666-4000-a000-000000000006 IMU Sensor Accelerometer, gyroscope, orientation
adom/a1b2c3d4-8888-4000-a000-000000000008 Time of Flight Sensor ToF distance readings
adom/a1b2c3d4-9999-4000-a000-000000000009 Ultrasonic Sensor Ultrasonic distance / obstacle detection
adom/a1b2c3d4-aaaa-4000-a000-00000000000a Line Follower Line following sensor array
adom/a1b2c3d4-0015-4000-a000-000000000015 Temperature Graph Real-time temperature graphing
adom/a1b2c3d4-0016-4000-a000-000000000016 Chip Data Microchip data monitoring
adom/a1b2c3d4-0017-4000-a000-000000000017 Chip Statistics Microchip performance metrics
adom/a1b2c3d4-0018-4000-a000-000000000018 Oven Data Oven temperature/control monitoring
adom/a1b2c3d4-0019-4000-a000-000000000019 ToF Sensor Time-of-Flight data visualization
adom/a1b2c3d4-001d-4000-a000-00000000001d Bosch Sensors Bosch sensor suite monitoring
adom/a1b2c3d4-001e-4000-a000-00000000001e BMP Sensor Bosch BMP pressure/temperature
adom/a1b2c3d4-0020-4000-a000-000000000020 BMV Sensor Bosch BMV sensor visualization
adom/a1b2c3d4-0021-4000-a000-000000000021 UWB Sensor Ultra-Wideband positioning

Media

Full ID Name Description
adom/a1b2c3d4-ffff-4000-a000-00000000000f Live Stream Live camera: static/free-moving or XY zoom
adom/a1b2c3d4-ffff-4000-a000-000000000100 WebRTC Player Single WebRTC video stream
adom/a1b2c3d4-2660-4a00-a000-000000000266 XY Zoom Camera Dual WebRTC streams with minimap

Utility

Full ID Name Description
adom/a1b2c3d4-0011-4000-a000-000000000011 System Log Real-time system log with filtering
adom/a1b2c3d4-bbbb-4000-a000-00000000000b Robot Log XRP robot console output
adom/a1b2c3d4-7777-4000-a000-000000000007 Battery Charger Battery charging status and power
adom/a1b2c3d4-cccc-4000-a000-00000000000c Curriculum XRP robot educational content
adom/a1b2c3d4-0031-4000-a000-000000000031 Web View Embedded browser — load any URL

Panel Details

XY Zoom Camera

Available on all workcells (included with the base $500/mo subscription).

Shows two simultaneous live video feeds:

  1. Wide view — A 120° FOV camera providing a constant birds-eye view of the entire workcell. This feed always shows the full workcell regardless of where the camera gantry is positioned. Use it for spatial awareness and general monitoring.
  2. Zoom view — A zoomable camera that can magnify down to a 10 mm x 10 mm area filling the entire feed. Use it for close-up inspection of components, solder joints, traces, wire connections, and fine details.

Controls: X/Y click-to-move or drag, zoom slider/scroll, preset position save/recall.

Upgrade — xyPanTiltZoom (+$100/mo): Adds pan (horizontal rotation), tilt (90° straight-down to angled perspectives), and 3D viewer linking — locks the physical camera to the user's 3D layout editor viewpoint so the real camera moves as they orbit/pan/zoom.

3D Viewer

Interactive 3D view of the workcell. Shows all molecules, scaffolds, wires, and the base scaffold in physical positions. Users can orbit, pan, and zoom. When xyPanTiltZoom 3D linking is enabled, navigating this viewer controls the physical camera.

Schematic Editor

Displays the project's scaffold schematic pages. Users can browse pages, inspect component pins, trace nets, and see how molecules are electrically connected.

User Plugins (Custom Panels)

Users can create custom panels via plugins in plugin-content/. Each plugin subfolder contains code and an HTML interface that appears as a panel in the web app. The front-end panel communicates with a mini web server on the Docker container, which can interact with hardware via USB, Ethernet, GPIO, or the Adom API.

Examples: motor control, sensor dashboard, firmware manager, test runner.

Relationship to Docker API

Panels and the Docker API are bidirectional:

  • Panels → API: Panel actions (e.g. camera moves) update the Docker container via WebSocket.
  • API → Panels: REST commands (e.g. scripted camera moves) update panels in real time.
  • Messaging: Scripts can send notifications via POST /message/send.
  • Viewer count: GET /viewers/count returns how many users are viewing the project.

See the adom-api guide for the full API reference.

Troubleshooting

Symptom Cause Fix
409 Conflict Editor is not open in the browser, or multiple users and no X-Target-Username Check GET .../current/users first. If zero users, ask user to open the editor. If multiple, specify the target username.
404 on panelId The leaf ID is stale or wrong Re-GET the layout and use fresh IDs
400 on tab remove Tried to remove the last tab in a leaf Tell the user — a leaf must always have at least one tab
400 on add tab Missing panelId or panelType Verify both fields are present and non-empty
401 Unauthorized Missing or invalid API key Read /var/run/adom/api-key; if missing, check env vars or ask the user
Singleton already present Adding a panel that only allows one instance Inform the user it's already open; offer to navigate to it instead