Skip to content

add picoclaw app#185

Merged
lxowalle merged 2 commits intosipeed:devfrom
916BGAI:dev
May 6, 2026
Merged

add picoclaw app#185
lxowalle merged 2 commits intosipeed:devfrom
916BGAI:dev

Conversation

@916BGAI
Copy link
Copy Markdown
Contributor

@916BGAI 916BGAI commented May 6, 2026

No description provided.

Copilot AI review requested due to automatic review settings May 6, 2026 06:58
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new PicoClaw MaixPy application under projects/app_picoclaw/, implementing a voice-driven interaction flow (record → ASR → stream agent response) with a custom on-device UI, plus optional on-device installation/launch of the picoclaw runtime.

Changes:

  • Introduces the PicoClaw app entrypoint and runtime orchestration (touch/key input, audio recording, ASR, streaming agent).
  • Adds UI rendering/animation utilities for home/install states and streaming text display.
  • Adds ASR backends (Qwen realtime/non-realtime, Whisper, ElevenLabs) and a picoclaw installer/launcher helper.

Reviewed changes

Copilot reviewed 14 out of 16 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
projects/app_picoclaw/main.py Main app loop: input handling, audio capture, ASR, PicoClaw streaming, lifecycle/cleanup
projects/app_picoclaw/ui.py Splash screens, install prompt UI, streaming renderer, and multiple animations
projects/app_picoclaw/picoclaw.py WebSocket client for the local PicoClaw gateway + token/model helpers
projects/app_picoclaw/install_picoclaw.py Download/install/start helpers for picoclaw (arm64/riscv64)
projects/app_picoclaw/touch.py Touchscreen polling helper (press edge detection + hit testing)
projects/app_picoclaw/key.py Key press state wrapper
projects/app_picoclaw/config.py Display/font scaling and app configuration constants
projects/app_picoclaw/asr/init.py ASR backend routing + import-time backend selection
projects/app_picoclaw/asr/config.py Loads ASR model/API key from env or .security.yml
projects/app_picoclaw/asr/qwen.py Non-realtime Qwen ASR via HTTP
projects/app_picoclaw/asr/qwen_realtime.py Realtime Qwen ASR via WebSocket
projects/app_picoclaw/asr/whisper.py Whisper transcription via HTTP
projects/app_picoclaw/asr/elevenlabs.py ElevenLabs STT via HTTP
projects/app_picoclaw/app.yaml App metadata (id/name/version/icon/files)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +82 to +84
with tarfile.open(tar_file, "r:gz") as tar:
tar.extractall(path=install_dir)

Comment on lines +78 to +84
if install_dir.exists():
shutil.rmtree(install_dir)
install_dir.mkdir(parents=True, exist_ok=True)

with tarfile.open(tar_file, "r:gz") as tar:
tar.extractall(path=install_dir)


try:
asr_session = get_asr_backend()
except ASRNotConfiguredError:

transcript = ""

async with websockets.connect(url, extra_headers=conn_headers) as ws:
Comment on lines +70 to +74
loop = asyncio.get_event_loop()
resp = await loop.run_in_executor(
None,
lambda: requests.post(url, headers=headers, files=files, data=data, timeout=120),
)
Comment on lines +65 to +70
import asyncio
loop = asyncio.get_event_loop()
resp = await loop.run_in_executor(
None,
lambda: requests.post(API_URL, json=payload, headers=headers, timeout=120),
)
Comment on lines +54 to +58
loop = asyncio.get_event_loop()
resp = await loop.run_in_executor(
None,
lambda: requests.post(API_URL, headers=headers, files=files, data=data, timeout=120),
)
Comment on lines +20 to +30
def start_anim(coro) -> None:
global _anim_task
if _anim_task and not _anim_task.done():
_anim_task.cancel()
_anim_task = asyncio.create_task(coro)


def stop_anim() -> None:
global _anim_task
if _anim_task and not _anim_task.done():
_anim_task.cancel()
Comment on lines +477 to +505
def _render_frame(question: str, window: list, tool_names: list | None = None) -> image.Image:
img = image.Image(config.DISP_W, config.DISP_H, image.Format.FMT_RGB888)
img.draw_rect(0, 0, config.DISP_W, config.DISP_H, image.Color.from_rgb(8, 8, 24), thickness=-1)

bx, by, bw, bh = get_exit_btn_rect()
content_x = max(TEXT_MARGIN, bx + bw + max(6, int(config.DISP_W * 0.02)))
content_max_w = max(1, config.DISP_W - TEXT_MARGIN - content_x)

y = 6
y += _draw_line_h(img, content_x, y, "You:", image.Color.from_rgb(120, 180, 255))

q_lines, _ = _wrap(question, 2, content_max_w)
for line in q_lines:
y += _draw_line_h(img, content_x, y, line, image.Color.from_rgb(200, 200, 200))

y += 3
img.draw_line(content_x, y, config.DISP_W - TEXT_MARGIN, y, image.Color.from_rgb(50, 50, 80), thickness=1)
y += 8

y += _draw_line_h(img, content_x, y, "PicoClaw:", image.Color.from_rgb(80, 200, 100))

for line in window:
if y + config.LINE_H > config.DISP_H:
break
y += _draw_line_h(img, content_x, y, line, image.Color.from_rgb(220, 220, 190))

_draw_exit_button(img)

return img
Comment on lines +258 to +259

if exit_task in done:
@lxowalle lxowalle merged commit db76e56 into sipeed:dev May 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants