Download src/agentcade/application.py from left0ver/WatcherRobot-com.left0ver.agentcade: direct link, hf CLI and curl.
- Browser
- Download file 3.93 kB
-
https://huggingface.co/spaces/left0ver/WatcherRobot-com.left0ver.agentcade/resolve/main/src/agentcade/application.py
- Command line
-
hf download hf://spaces/left0ver/WatcherRobot-com.left0ver.agentcade/src/agentcade/application.py
-
curl -L -o application.py https://huggingface.co/spaces/left0ver/WatcherRobot-com.left0ver.agentcade/resolve/main/src/agentcade/application.py
3.93 kB
| import asyncio | |
| import logging | |
| from agentcade import settings_page | |
| from agentcade.game_client import connect_games | |
| from agentcade.main_agent import MainAgent | |
| from agentcade.microphone import MicrophoneInput | |
| from agentcade.output import OutputCoordinator | |
| from agentcade.speech_input import SpeechInput | |
| from observability.server import serve | |
| class RobotApplication: | |
| def __init__(self, app, settings, games, microphone, output): | |
| self.app, self.settings = app, settings | |
| self.input = microphone | |
| self.agent = MainAgent(settings, games) | |
| self.output = output | |
| self.listener = None | |
| async def listen(self, ready): | |
| self.listener = SpeechInput(self.settings, self.agent, self.input, self.app.logger) | |
| await self.listener.run(ready) | |
| async def run(self): | |
| required = {"expression.runtime.v3", "microphone", "audio.stream"} | |
| for game in self.agent.games.values(): | |
| required.update(game.descriptor.required_capabilities) | |
| try: | |
| missing = [name for name in required if not self.app.robot.supports(name)] | |
| if missing: | |
| raise RuntimeError("机器人未连接或缺少能力:" + ", ".join(sorted(missing))) | |
| await self.output.clear() | |
| async with asyncio.TaskGroup() as group: | |
| tasks = [ | |
| group.create_task(self.input.capture()), | |
| group.create_task(self.output.run(self.agent)), | |
| ] | |
| ready = asyncio.Event() | |
| tasks.append(group.create_task(self.listen(ready))) | |
| await ready.wait() | |
| game_names = "、".join(game.descriptor.name for game in self.agent.games.values()) | |
| greeting = ( | |
| f"你好呀,我是小懒!现在可以玩{game_names}。想玩哪个?也可以和我聊聊天。" | |
| if game_names else "你好呀,我是小懒!现在还没有可玩的游戏,我们可以聊聊天。" | |
| ) | |
| await self.agent.reply(greeting) | |
| while not self.app.shutdown_requested: | |
| # 麦克风、识别和播报出错时各自恢复;通道断开后设备指令全部失效,只能退出。 | |
| if self.app.connection_lost: | |
| raise RuntimeError("与机器人守护进程的连接已经断开,无法继续运行") | |
| if (not self.output.speaking and not self.listener.busy | |
| and not self.listener.input_speaking): | |
| await self.agent.tick() | |
| await self.output.progress.check() | |
| await asyncio.sleep(0.1) | |
| for task in tasks: | |
| task.cancel() | |
| finally: | |
| try: | |
| await self.agent.close() | |
| finally: | |
| await self.output.close() | |
| def route_logs(app): | |
| """各模块的告警和错误写入应用日志,和运行记录出现在同一个地方。""" | |
| for name in ("agentcade", "games", "observability"): | |
| target = logging.getLogger(name) | |
| target.setLevel(logging.INFO) | |
| target.propagate = False | |
| target.handlers = list(app.logger.handlers) | |
| async def run_application(app): | |
| route_logs(app) | |
| # 页面先启动:服务配置还没填好时,用户要在它的设置页面里填写。 | |
| async with serve(settings_page.port(), routes=settings_page.routes()) as url: | |
| app.logger.info("对话页面:%s", url) | |
| settings = await settings_page.ready(app, url) | |
| if settings is None: | |
| return | |
| microphone = MicrophoneInput(app.robot) | |
| output = OutputCoordinator(app, settings, microphone) | |
| async with connect_games(settings.game_catalog, output.execute) as games: | |
| await RobotApplication(app, settings, games, microphone, output).run() | |