"""Play a YouTube video on the shared screen (browser/screen-share mode). Only meaningful when ``STREAM_BROWSER`` is true: it drives the on-screen Chrome (via the Node CDP helper) to search YouTube and play the first result, which is visible on the Go-Live broadcast. In voice-only mode (false) there is nothing to show, so the tool reports that and does nothing. """ from __future__ import annotations import json import os import subprocess from typing import Dict, Any, Optional from ..base import Tool, ToolContext from ..types import ToolExecutionResult from ...debug import debug_log from .realtime_search import _NODE_SCRIPT class BrowseAndPlayTool(Tool): """Play a YouTube video on the shared screen.""" @property def name(self) -> str: return "browseAndPlay" @property def description(self) -> str: return ( "Play a song / music video / clip on the shared screen by searching YouTube " "and playing the first result. Use when the user asks you to play or watch " "something. Only available in screen-share mode." ) @property def inputSchema(self) -> Dict[str, Any]: return { "type": "object", "properties": { "query": { "type": "string", "description": "What to play, e.g. 'IU Good Day' or 'lofi hip hop'.", } }, "required": ["query"], } def run(self, args: Optional[Dict[str, Any]], context: ToolContext) -> ToolExecutionResult: cfg = context.cfg if not getattr(cfg, "stream_browser", True): return ToolExecutionResult( success=False, reply_text="화면 공유 모드(STREAM_BROWSER=true)에서만 영상을 재생할 수 있습니다.", ) query = "" if args and isinstance(args, dict): query = str(args.get("query", "")).strip() if not query: return ToolExecutionResult(success=False, reply_text="재생할 내용을 알려주세요.") if not _NODE_SCRIPT.exists(): return ToolExecutionResult(success=False, reply_text="브라우저 재생 도구를 찾을 수 없습니다.") context.user_print(f"▶️ 화면에서 '{query}' 재생 중…") debug_log(f" ▶️ browseAndPlay '{query}'", "tools") try: proc = subprocess.run( ["node", str(_NODE_SCRIPT), query, "youtube"], capture_output=True, text=True, timeout=40, env={**os.environ, "CDP_PORT": os.environ.get("CDP_PORT", "9222")}, ) data = json.loads((proc.stdout or "").strip() or "{}") except Exception as e: return ToolExecutionResult(success=False, reply_text=f"재생에 실패했습니다: {e}") if not data.get("ok"): return ToolExecutionResult( success=False, reply_text=f"재생에 실패했습니다: {data.get('error', 'unknown')}" ) title = data.get("title") or query return ToolExecutionResult(success=True, reply_text=f"화면에서 '{title}' 재생을 시작했습니다.")