e9857dde22
* 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
95 lines
3.3 KiB
Python
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()
|