mirror of
https://github.com/usestrix/strix.git
synced 2026-08-19 18:13:34 +02:00
perf(cli): ~10x faster startup via lazy imports (#920)
* perf(cli): fast startup — lazy heavy imports + onedir standalone build * perf(cli): drop legacy single-file compat from install/self-update * perf(cli): simplify — drop constants module and extra lazy-import refactors * refactor(update): strix --update just re-runs the install script * perf(cli): drop packaging/install/update changes; deepen lazy imports instead Reverts the onedir build, install.sh, and self-update changes so release mechanics stay untouched. Startup cost is addressed purely by deferring heavy imports (agents/openai, config.models, report state/writer, docker) until a scan actually runs; DEFAULT_MAX_TURNS moves to strix.config.settings so argparse no longer pulls the agents SDK. --------- Co-authored-by: Ahmed Allam <ahmed39652003@gmail.com>
This commit is contained in:
co-authored by
Ahmed Allam
parent
c240068c2c
commit
797b37467e
@@ -10,6 +10,8 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
ReasoningEffort = Literal["none", "minimal", "low", "medium", "high", "xhigh", "max"]
|
||||
|
||||
DEFAULT_MAX_TURNS = 500
|
||||
|
||||
_BASE_CONFIG = SettingsConfigDict(
|
||||
case_sensitive=False,
|
||||
populate_by_name=True,
|
||||
|
||||
@@ -24,9 +24,6 @@ if TYPE_CHECKING:
|
||||
from strix.config.settings import ReasoningEffort
|
||||
|
||||
|
||||
DEFAULT_MAX_TURNS = 500
|
||||
|
||||
|
||||
def _accepts_required_tool_choice(model_name: str | None) -> bool:
|
||||
name = (model_name or "").strip().lower()
|
||||
for prefix in ("litellm/", "any-llm/"):
|
||||
|
||||
@@ -23,6 +23,7 @@ from strix.config.models import (
|
||||
configure_sdk_model_defaults,
|
||||
uses_chat_completions_tool_schema,
|
||||
)
|
||||
from strix.config.settings import DEFAULT_MAX_TURNS
|
||||
from strix.core.agents import AgentCoordinator
|
||||
from strix.core.execution import (
|
||||
respawn_subagents,
|
||||
@@ -33,7 +34,6 @@ from strix.core.execution import (
|
||||
)
|
||||
from strix.core.hooks import BudgetExceededError, ReportUsageHooks, recomputed_budget_flags
|
||||
from strix.core.inputs import (
|
||||
DEFAULT_MAX_TURNS,
|
||||
build_root_task,
|
||||
build_scope_context,
|
||||
make_model_settings,
|
||||
|
||||
@@ -13,7 +13,7 @@ from rich.panel import Panel
|
||||
from rich.text import Text
|
||||
|
||||
from strix.config import load_settings
|
||||
from strix.core.inputs import DEFAULT_MAX_TURNS
|
||||
from strix.config.settings import DEFAULT_MAX_TURNS
|
||||
from strix.core.runner import run_strix_scan
|
||||
from strix.report.state import ReportState, set_global_report_state
|
||||
from strix.runtime import session_manager
|
||||
|
||||
+27
-15
@@ -11,9 +11,6 @@ import sys
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
from agents.model_settings import ModelSettings
|
||||
from agents.models.interface import ModelTracing
|
||||
from docker.errors import DockerException
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
from rich.text import Text
|
||||
@@ -24,17 +21,8 @@ from strix.config import (
|
||||
load_settings,
|
||||
persist_current,
|
||||
)
|
||||
from strix.config.models import (
|
||||
RECOMMENDED_MODEL_NAMES,
|
||||
StrixProvider,
|
||||
configure_sdk_model_defaults,
|
||||
is_known_openai_bare_model,
|
||||
is_recommended_or_frontier_model,
|
||||
)
|
||||
from strix.core.inputs import DEFAULT_MAX_TURNS, make_model_settings
|
||||
from strix.config.settings import DEFAULT_MAX_TURNS
|
||||
from strix.core.paths import run_dir_for, runtime_state_dir
|
||||
from strix.interface.cli import run_cli
|
||||
from strix.interface.tui import run_tui
|
||||
from strix.interface.update_check import (
|
||||
is_binary_install,
|
||||
notify_update,
|
||||
@@ -61,8 +49,6 @@ from strix.interface.utils import (
|
||||
rewrite_localhost_targets,
|
||||
validate_config_file,
|
||||
)
|
||||
from strix.report.state import get_global_report_state
|
||||
from strix.report.writer import read_run_record, write_run_record
|
||||
from strix.telemetry import posthog, scarf
|
||||
from strix.telemetry.logging import configure_dependency_logging
|
||||
|
||||
@@ -310,6 +296,18 @@ def _subscription_error_hint(exc: BaseException) -> str | None:
|
||||
|
||||
|
||||
async def warm_up_llm(show_model_warning: bool = True) -> None:
|
||||
from agents.model_settings import ModelSettings
|
||||
from agents.models.interface import ModelTracing
|
||||
|
||||
from strix.config.models import (
|
||||
RECOMMENDED_MODEL_NAMES,
|
||||
StrixProvider,
|
||||
configure_sdk_model_defaults,
|
||||
is_known_openai_bare_model,
|
||||
is_recommended_or_frontier_model,
|
||||
)
|
||||
from strix.core.inputs import make_model_settings
|
||||
|
||||
console = Console()
|
||||
logger.info("Warming up LLM connection")
|
||||
|
||||
@@ -794,6 +792,8 @@ Examples:
|
||||
|
||||
|
||||
def _persist_run_record(args: argparse.Namespace) -> None:
|
||||
from strix.report.writer import write_run_record
|
||||
|
||||
run_dir = run_dir_for(args.run_name)
|
||||
run_dir.mkdir(parents=True, exist_ok=True)
|
||||
run_record = {
|
||||
@@ -817,6 +817,8 @@ def _persist_run_record(args: argparse.Namespace) -> None:
|
||||
|
||||
def _load_resume_state(args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:
|
||||
"""Populate ``args.targets_info`` and friends from a prior run's run.json."""
|
||||
from strix.report.writer import read_run_record
|
||||
|
||||
run_dir = run_dir_for(args.resume)
|
||||
state_path = run_dir / "run.json"
|
||||
if not state_path.exists():
|
||||
@@ -861,6 +863,8 @@ def _load_resume_state(args: argparse.Namespace, parser: argparse.ArgumentParser
|
||||
|
||||
|
||||
def display_completion_message(args: argparse.Namespace, results_path: Path) -> None:
|
||||
from strix.report.state import get_global_report_state
|
||||
|
||||
console = Console()
|
||||
report_state = get_global_report_state()
|
||||
|
||||
@@ -940,6 +944,8 @@ def display_completion_message(args: argparse.Namespace, results_path: Path) ->
|
||||
|
||||
|
||||
def pull_docker_image() -> None:
|
||||
from docker.errors import DockerException
|
||||
|
||||
console = Console()
|
||||
client = check_docker_connection()
|
||||
|
||||
@@ -1086,11 +1092,17 @@ def main() -> None:
|
||||
posthog.start(**_telemetry_start_kwargs)
|
||||
scarf.start(**_telemetry_start_kwargs)
|
||||
|
||||
from strix.report.state import get_global_report_state
|
||||
|
||||
exit_reason = "user_exit"
|
||||
try:
|
||||
if args.non_interactive:
|
||||
from strix.interface.cli import run_cli
|
||||
|
||||
asyncio.run(run_cli(args))
|
||||
else:
|
||||
from strix.interface.tui import run_tui
|
||||
|
||||
asyncio.run(run_tui(args))
|
||||
except KeyboardInterrupt:
|
||||
exit_reason = "interrupted"
|
||||
|
||||
@@ -34,8 +34,8 @@ from textual.widgets.tree import TreeNode
|
||||
|
||||
from strix.config import load_settings
|
||||
from strix.config.models import is_recommended_or_frontier_model
|
||||
from strix.config.settings import DEFAULT_MAX_TURNS
|
||||
from strix.core.hooks import BudgetExceededError
|
||||
from strix.core.inputs import DEFAULT_MAX_TURNS
|
||||
from strix.core.runner import run_strix_scan
|
||||
from strix.interface.tui.live_view import TuiLiveView
|
||||
from strix.interface.tui.messages import send_user_message_to_agent
|
||||
|
||||
@@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
import contextlib
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from contextvars import ContextVar
|
||||
from pathlib import Path # noqa: TC003 used at runtime by ``setup_scan_logging``
|
||||
@@ -78,11 +79,10 @@ class _StdoutQuietFilter(logging.Filter):
|
||||
|
||||
def configure_dependency_logging() -> None:
|
||||
"""Quiet dependency logging/warnings that obscure Strix scan logs."""
|
||||
with contextlib.suppress(Exception):
|
||||
import litellm
|
||||
|
||||
litellm_logging = litellm._logging
|
||||
litellm_logging._disable_debugging() # type: ignore[no-untyped-call]
|
||||
litellm = sys.modules.get("litellm")
|
||||
if litellm is not None:
|
||||
with contextlib.suppress(Exception):
|
||||
litellm._logging._disable_debugging()
|
||||
|
||||
logging.getLogger("asyncio").setLevel(logging.CRITICAL)
|
||||
logging.getLogger("asyncio").propagate = False
|
||||
|
||||
Reference in New Issue
Block a user