mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-18 10:00:40 +08:00
feat(cli): add real-time log streaming in non-interactive mode
- Non-interactive mode now streams logs to stdout with color-coded levels - Add proper async cleanup when shutting down - Fix type annotations in coze and deerflow agent runners
This commit is contained in:
@@ -323,12 +323,69 @@ def run(
|
||||
)
|
||||
)
|
||||
else:
|
||||
click.echo("AstrBot is running...")
|
||||
if backend_only:
|
||||
click.echo("Visit the dashboard at : https://dash.astrbot.men/")
|
||||
click.echo("Backend Requests : localhost or based on https")
|
||||
# Non-interactive mode: run with stdout log streaming
|
||||
async def run_with_logging() -> None:
|
||||
from astrbot.core import LogBroker, LogManager, db_helper, logger
|
||||
from astrbot.core.initial_loader import InitialLoader
|
||||
|
||||
asyncio.run(run_astrbot(astrbot_root))
|
||||
if (
|
||||
os.environ.get("ASTRBOT_DASHBOARD_ENABLE", os.environ.get("DASHBOARD_ENABLE"))
|
||||
== "True"
|
||||
):
|
||||
await DashboardManager().ensure_installed(astrbot_root)
|
||||
|
||||
log_broker = LogBroker()
|
||||
LogManager.set_queue_handler(logger, log_broker)
|
||||
|
||||
# Register a stdout subscriber for real-time log streaming
|
||||
log_queue = log_broker.register()
|
||||
|
||||
db = db_helper
|
||||
initial_loader = InitialLoader(db, log_broker)
|
||||
|
||||
# Start a task to stream logs to stdout
|
||||
async def stream_logs() -> None:
|
||||
"""Stream logs from LogBroker to stdout."""
|
||||
import logging
|
||||
while True:
|
||||
try:
|
||||
log_entry = await asyncio.wait_for(log_queue.get(), timeout=0.5)
|
||||
# Format: [LEVEL] message
|
||||
level = log_entry.get("level_name", "INFO")
|
||||
message = log_entry.get("message", "")
|
||||
if message:
|
||||
level_color = {
|
||||
"DEBUG": "cyan",
|
||||
"INFO": "green",
|
||||
"WARNING": "yellow",
|
||||
"ERROR": "red",
|
||||
"CRITICAL": "red",
|
||||
}.get(level, "white")
|
||||
click.secho(f"[{level}]", fg=level_color, bold=False, nl=False)
|
||||
click.echo(f" {message}")
|
||||
except asyncio.TimeoutError:
|
||||
continue
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
|
||||
# Start streaming task
|
||||
stream_task = asyncio.create_task(stream_logs())
|
||||
|
||||
try:
|
||||
await initial_loader.start()
|
||||
finally:
|
||||
stream_task.cancel()
|
||||
try:
|
||||
await stream_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
click.echo("AstrBot is running... (streaming logs)")
|
||||
if backend_only:
|
||||
click.echo("Dashboard: https://dash.astrbot.men/")
|
||||
click.echo("Backend: localhost or based on https")
|
||||
|
||||
asyncio.run(run_with_logging())
|
||||
except KeyboardInterrupt:
|
||||
click.echo("AstrBot has been shut down.")
|
||||
except Timeout:
|
||||
|
||||
@@ -86,7 +86,7 @@ class CozeAgentRunner(BaseAgentRunner[TContext]):
|
||||
self.file_id_cache: dict[str, dict[str, str]] = {}
|
||||
|
||||
@override
|
||||
async def step(self):
|
||||
async def step(self) -> AsyncGenerator[AgentResponse, None]:
|
||||
"""
|
||||
执行 Coze Agent 的一个步骤
|
||||
"""
|
||||
|
||||
@@ -23,8 +23,8 @@ from astrbot.core.utils.config_number import coerce_int_config
|
||||
from ...hooks import BaseAgentRunHooks
|
||||
from ...response import AgentResponseData
|
||||
from ...run_context import ContextWrapper, TContext
|
||||
from ...tool_executor import BaseFunctionToolExecutor
|
||||
from ..base import AgentResponse, AgentState, BaseAgentRunner
|
||||
from ..tool_executor import BaseFunctionToolExecutor
|
||||
from .constants import DEERFLOW_SESSION_PREFIX, DEERFLOW_THREAD_ID_KEY
|
||||
from .deerflow_api_client import DeerFlowAPIClient
|
||||
from .deerflow_content_mapper import (
|
||||
|
||||
@@ -70,7 +70,7 @@ class BrowserExecTool(FunctionTool):
|
||||
async def call(
|
||||
self,
|
||||
context: ContextWrapper[AstrAgentContext],
|
||||
cmd: str,
|
||||
cmd: str = "",
|
||||
timeout: int = 30,
|
||||
description: str | None = None,
|
||||
tags: str | None = None,
|
||||
@@ -133,7 +133,7 @@ class BrowserBatchExecTool(FunctionTool):
|
||||
async def call(
|
||||
self,
|
||||
context: ContextWrapper[AstrAgentContext],
|
||||
commands: list[str],
|
||||
commands: list[str] | None = None,
|
||||
timeout: int = 60,
|
||||
stop_on_error: bool = True,
|
||||
description: str | None = None,
|
||||
@@ -182,7 +182,7 @@ class RunBrowserSkillTool(FunctionTool):
|
||||
async def call(
|
||||
self,
|
||||
context: ContextWrapper[AstrAgentContext],
|
||||
skill_key: str,
|
||||
skill_key: str = "",
|
||||
timeout: int = 60,
|
||||
stop_on_error: bool = True,
|
||||
include_trace: bool = False,
|
||||
|
||||
Reference in New Issue
Block a user