Build an API 2 pet
Goal: render a status orb with a complete local module and no external images, network or build step. Download the importable ZIP and import it in the device-interaction pet settings.
Open
manifest.json
config.toml
scripts/main.jsManifest and configuration
{
"apiVersion": 2,
"id": "lyra.docs.status-orb",
"name": "Status Orb",
"version": "1.0.0",
"author": "Lyra Code documentation",
"entry": "scripts/main.js",
"config": "config.toml",
"controls": [
{ "key": "color", "label": "Color / 颜色", "type": "color", "default": "#5b7cfa" }
]
}apiVersion, id, name, version, author and a .js entry are required. Include exactly one manifest. Paths are relative to the package root without absolute paths or ...
[pet]
size = 96
autoDock = true
soundEnabled = false
[controls]
color = "#5b7cfa"Configuration uses the host's TOML scalar subset. The manifest declares the custom color control. Values resolve from defaults, package configuration and locally saved personal settings.
Lifecycle module
let orb;
let state = 'idle';
let color = '#5b7cfa';
const labels = {
idle: 'Ready', thinking: 'Thinking', executing: 'Working',
approval: 'Waiting', completed: 'Done', error: 'Error', paused: 'Paused'
};
function render() {
if (!orb) return;
orb.textContent = labels[state] || 'Ready';
orb.style.background = state === 'error' ? '#c23743' : color;
}
export default {
mount(api) {
orb = document.createElement('div');
orb.style.cssText = 'width:88%;height:88%;margin:6%;border-radius:50%;display:grid;place-items:center;color:white;font:600 13px system-ui;box-shadow:inset 0 -8px 16px #0002;user-select:none;';
api.root.append(orb);
color = api.config?.color || color;
render();
},
onEvent(type, data) {
if (type === 'state') state = data.state;
if (type === 'config') color = data.color || color;
if (type === 'tap') orb?.animate(
[{ transform: 'scale(1)' }, { transform: 'scale(.9)' }, { transform: 'scale(1)' }],
{ duration: 220 }
);
render();
},
unmount() {
orb?.getAnimations().forEach(animation => animation.cancel());
orb?.remove();
orb = undefined;
state = 'idle';
color = '#5b7cfa';
}
};mount creates a node, onEvent handles config/state/tap and unmount cancels animation and removes the node. The host owns taps, long-press and dragging; DOM clicks are not a way to perform system operations.
Device acceptance
- Import the ZIP and confirm a
Readyorb; long-press should open settings. - Change its color and confirm the update and saved personal preference.
- Run a task and inspect states such as Thinking, Working, Waiting or Done.
- Tapping should briefly scale the orb. Switch away and back without duplicate nodes.
- Remove the example if no longer needed. On failure, retain the error and check unique manifest, entry and syntax.
Scripts cannot arbitrarily access the network or execute Shell. Load packaged animation assets with api.asset() or sprite helpers and clean up timers/audio on unmount. See the application's API 2 guide for the full protocol.
