Files
EvoScientist-Multi/EvoScientist/cli/__init__.py
T
Xi Zhang e9857dde22 fix(deps): pin openrouter below 0.11 to avoid SSE stream regressions (#373)
* fix(openrouter): address SSE stream leak by closing response iterator

* refactor(openrouter): pass through SDK args in SSE leak patch

* test(openrouter): make SSE leak tests version-agnostic across SDK generations

* fix(openrouter): remove SSE stream leak patch and update dependencies
2026-07-22 16:03:57 +02:00

95 lines
3.3 KiB
Python

"""EvoScientist CLI package.
Most re-exports are served lazily through ``__getattr__`` so that a bare
``import EvoScientist.cli`` only costs what ``main()`` actually needs. That
keeps ``evosci --help`` fast — the heavy chat-model/TUI/langgraph imports
only pay their cost when someone actually touches those names.
"""
from __future__ import annotations
from .. import deploy as _deploy_pkg # noqa: F401 — registers `deploy` @app.command
from . import commands # noqa: F401 — registers @app.command decorators
from ._app import app
__all__ = [
"DEFAULT_UI_BACKEND",
"SUPPORTED_UI_BACKENDS",
"WELCOME_SLOGANS",
"StreamState",
"SubAgentState",
"_build_todo_stats",
"_channels_is_running",
"_channels_stop",
"_deduplicate_run_name",
"_parse_todo_items",
"app",
"get_backend",
"main",
"normalize_ui_backend",
"resolve_ui_backend",
"run_streaming",
]
# Map attribute name -> (relative-module, attribute-in-module).
# Paths starting with ".." reach out of this package.
_LAZY_EXPORTS: dict[str, tuple[str, str]] = {
"StreamState": ("..stream.state", "StreamState"),
"SubAgentState": ("..stream.state", "SubAgentState"),
"_build_todo_stats": ("..stream.state", "_build_todo_stats"),
"_parse_todo_items": ("..stream.state", "_parse_todo_items"),
"WELCOME_SLOGANS": ("._constants", "WELCOME_SLOGANS"),
"_deduplicate_run_name": (".agent", "_deduplicate_run_name"),
"_channels_is_running": (".channel", "_channels_is_running"),
"_channels_stop": (".channel", "_channels_stop"),
"DEFAULT_UI_BACKEND": (".tui_runtime", "DEFAULT_UI_BACKEND"),
"SUPPORTED_UI_BACKENDS": (".tui_runtime", "SUPPORTED_UI_BACKENDS"),
"get_backend": (".tui_runtime", "get_backend"),
"normalize_ui_backend": (".tui_runtime", "normalize_ui_backend"),
"resolve_ui_backend": (".tui_runtime", "resolve_ui_backend"),
"run_streaming": (".tui_runtime", "run_streaming"),
}
def __getattr__(name: str):
target = _LAZY_EXPORTS.get(name)
if target is None:
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
from importlib import import_module
module_path, attr = target
module = import_module(module_path, package=__name__)
value = getattr(module, attr)
globals()[name] = value
return value
def main():
"""CLI entry point."""
import os
import warnings
# Keep MCP stdio subprocess spawning async on Windows (see #283). Must run
# before any event loop is created, hence at the very top of the entrypoint.
from .._winloop import ensure_proactor_event_loop_policy
ensure_proactor_event_loop_policy()
warnings.filterwarnings("ignore", message=".*not known to support tools.*")
warnings.filterwarnings(
"ignore", message=".*type is unknown and inference may fail.*"
)
# v3 streaming is a deliberate choice (#268), so its beta notice is noise.
# Matched by message, not category, to keep other beta warnings visible.
warnings.filterwarnings(
"ignore", message=".*v3 streaming protocol on Pregel is experimental.*"
)
from ..config import load_config
from .commands import _configure_logging
# Priority: env var > config file > default (WARNING)
config = load_config()
_log_level = os.environ.get("EVOSCIENTIST_LOG_LEVEL", "") or config.log_level
_configure_logging()
app()