This project is a complete rewrite of the ASUS Zenbo dialog system. It replaces the stock face/home UI with a modern, web‑based assistant powered by OpenAI agents, running inside GeckoView on the robot itself.
At a high level:
- A Vue 3 single‑page app provides the conversational UI, tools, and agent logic.
- GeckoView embeds that SPA as the robot’s primary UI (KIRA can be set as the device launcher).
- A foreground Android
Serviceexposes the Zenbo nativeRobotAPIvia a lightweight HTTP + WebSocket API. - The web app uses that API to remote‑control the robot (speech, expressions, tracking, etc.) and to react to real‑time robot events.
The goal is to decouple the dialog/agent logic from the native UI and implement it in JavaScript, while still having full access to the robot’s capabilities through a clean Android bridge.
- The web UI lives under
src/:App.vuebootstraps the page and wires up the core modules.src/composables/contains reusable hooks:useAgent.js– builds an OpenAI agent using@openai/agents, auto‑discovering<tool>and<context>elements from the DOM.useVoiceAgent.js– orchestrates transcription (VAD + Whisper), agent turns, and TTS for a voice‑first experience.useRobotAPI.js– provides a typed wrapper around the robot HTTP API (dialog, face, utility endpoints).useRobotEvents.js– subscribes to robot events over WebSocket (ws://<host>:8790/events) and exposesonEvent/onEventType.useSleepMode.js– global sleep/wake state used to mute/unmute the VAD microphone.
src/modules/defines feature modules:modules/robot/Robot.vue– robot‑specific tools and context (e.g. follow user, expression presets).modules/misc/*.vue– domain tools likeAssist,Finance,Weather,ImageGen,Search, plusSleep(agent sleep tool).modules/event/EventDisplay.vue– debug view for incoming robot events.modules/event/SleepWake.vue– listens foronVoiceDetectevents to wake the agent from sleep.
The agent itself is described declaratively:
<context name="...">blocks give the agent additional contextual instructions (current time, robot persona, etc.).<tool name="...">elements define callable tools with<prop>children describing parameters.useAgentscans the DOM for these tags and turns them into real tools for the OpenAI agent.
The Android portion lives under android/KiraZenbo/ and consists of:
-
MainActivity:- Hosts a
GeckoViewand loads the SPA fromhttp://127.0.0.1:8787/. - Implements
GeckoSession.PermissionDelegateto grant microphone access for in‑browser audio capture. - Declares both a standard launcher intent and a
HOMEintent:- KIRA can be set as the default home screen / launcher on the device.
- When selected, the GeckoView UI effectively replaces the default Zenbo home view.
- Hosts a
-
RobotApiService(foregroundService):- Owns a
RobotAPIinstance and registers callbacks for:- Robot state changes, tracking, face/gesture detection…
- Dialog events such as
onVoiceDetect,onEventUserUtterance,onSpeakComplete, etc.
- Starts and manages two servers:
AsyncRobotApiServer(HTTP) onhttp://127.0.0.1:8787:- Serves the SPA (
assets/app/index.html) at/. - Exposes REST endpoints under
/api/...for:- Dialog actions (
/api/dialog/speak,/api/dialog/start_speak_animation,/api/dialog/voice_trigger, …). - Face actions (
/api/face/expression,/api/face/expression_and_speak). - Utility actions (
/api/utility/follow_face,/follow_object,/track_face,/look_at_user,/play_action,/play_emotional_action, blue‑light filter controls).
- Dialog actions (
- This is what
useRobotAPIcalls from the web app.
- Serves the SPA (
AndroidAsyncEventServer(WebSocket) onws://127.0.0.1:8790/events:- Broadcasts JSON event messages
{ "type": "<eventName>", "data": { ... } }to all connected clients. - This is what
useRobotEventsconnects to.
- Broadcasts JSON event messages
- Bridges native events into the WebSocket:
- Each
RobotAPIcallback builds a JSON payload and callssendEvent("onVoiceDetect", data),sendEvent("onStateChange", data), etc. - The web UI can subscribe to these (e.g.
onEventType('onVoiceDetect', ...)) to update expressions, show debug info, or wake the sleep mode.
- Each
- Brings the UI to the foreground when needed:
- On
onVoiceDetect,RobotApiServicecalls a helper that launchesMainActivity(in the HOME task) so the GeckoView UI is visible when the user starts speaking to the robot.
- On
- Owns a
The project implements an explicit “sleep mode” for the agent:
Sleep.vuedefines<tool name="go_to_sleep">:- When the agent calls this tool,
handleGoToSleepsets the globalsleepingflag and returns{ ok: true, sleeping: true }.
- When the agent calls this tool,
useSleepModeexposes a sharedsleepingref andgoToSleep/wakeUphelpers.useVoiceAgentwatchessleepingand controls the VAD mic mute:- When
sleepingistrue:- Calls
muteMic()inuseTranscriptionso VAD segments are discarded and never sent to Whisper or the agent.
- Calls
- When
sleepingisfalseand TTS is idle:- Calls
unmuteMic()so the agent can hear the user again.
- Calls
- TTS always mutes the mic while speaking and only un‑mutes it when not in sleep mode, to avoid feedback loops.
- When
SleepWake.vuelistens on the robot event stream:- When an
onVoiceDetectevent is received andsleepingistrue, it callswakeUp()so the agent wakes, unmutes the mic, and can handle the next utterance.
- When an
This gives the agent an explicit “go to sleep” tool and a natural wake‑up trigger based on the robot’s native voice detection.
KIRA is designed to replace the default Zenbo home view:
MainActivitydeclares an intent filter withACTION_MAIN+CATEGORY_HOME+CATEGORY_DEFAULT.- When the app is installed, pressing Home or finishing boot may prompt the user to choose a default HOME app.
- If “Kira” is selected and set to “Always”, then:
- KIRA’s GeckoView UI becomes the robot’s home screen.
- After boot,
RobotApiServicestarts in the background andMainActivityis the visible front‑end. - The system “face” activity can be hidden or replaced by the Vue UI as needed (e.g. via robot expressions such as hiding the face).
To revert back to the original launcher, clear KIRA’s default HOME association in Android’s “Home app” / “Default apps” settings and choose the original Zenbo launcher again.
- Install dependencies:
npm install - Run dev server:
npm run dev- This serves the SPA for browser‑based development (without GeckoView).
- Build/watch for Android/WebView:
npm run android- Runs
vite build --watch --outDir android/KiraZenbo/src/main/assets/app. - On each change, Vite rebuilds the SPA and writes a new
index.htmlbundle directly into the Android assets folder used by GeckoView.
- Runs
- Open the
android/directory in Android Studio. - Let Gradle sync, then run the
KiraZenboapp on the device. - While
npm run androidis running, any changes to the Vue app will rebuild and updateandroid/KiraZenbo/src/main/assets/app/index.htmlautomatically.- To see updated UI in GeckoView, rebuild/relaunch the Android app from Android Studio (or use “Apply Changes” if available).
- Once installed and set as the HOME/launcher, KIRA will start as the main UI;
RobotApiServicestarts automatically to provide the HTTP and WebSocket APIs.