Skip to content

fix: defer core.compat imports in parallel.py to break config<->runtime<->compat cycle - #289

Open
raymondginger2018-sudo wants to merge 1 commit into
HKUDS:mainfrom
raymondginger2018-sudo:fix/compat-parallel-type-checking-import
Open

raymondginger2018-sudo wants to merge 1 commit into
HKUDS:mainfrom
raymondginger2018-sudo:fix/compat-parallel-type-checking-import

Conversation

@raymondginger2018-sudo

Copy link
Copy Markdown
Contributor

What

Break the core.config ↔ core.agent_runtime ↔ core.compat circular import by deferring core.compat imports in core/compat/parallel.py to TYPE_CHECKING, and extract a thin core/agent_runtime/parallel.py module with a single public entry point run_parallel_llm.

Why

The module-level import graph contains a 3-way cycle:

core.config → core.agent_runtime.tools.mcp → core.agent_runtime/__init__ 
  → core.compat.parallel → core.compat.agent → core.compat.runtime → core.config

Today the cycle doesn't detonate (import order happens to work), but it's fragile: any future module that imports core.compat.parallel before core.config is fully initialised will hit a PartiallyImported error. This PR makes the dependency direction safe and adds a guard test to prevent regression.

Changes

  • core/compat/parallel.py — move core.compat.agent / core.compat.request_params imports under if TYPE_CHECKING: (already uses from __future__ import annotations, so all usages are annotation-only).
  • core/agent_runtime/parallel.py (new) — thin public module with run_parallel_llm; imports ParallelLLM lazily inside the function body.
  • core/agent_runtime/__init__.py — re-export run_parallel_llm.
  • tests/test_import_layering.py (new) — guard test: 3 fresh-interpreter import checks + AST scan asserting no module-level core.compat imports under core/agent_runtime/**.

Verification

  • Guard test: 4/4 pass (-p no:cacheprovider needed on Windows due to pytest cache plugin + subprocess interaction).
  • AST scan: 0 module-level offenders.
  • Bidirectional falsification: planted a module-level core.compat import in core/agent_runtime/helpers.py → guard correctly went RED → removed → GREEN.
  • Pre-commit: ruff + ruff format + trailing-whitespace all pass.

Notes

  • No runtime behaviour change; purely import-order hardening.
  • Local preflight on Windows shows environment-specific failures (pytest timeout at 2400s, clippy/cargo in desktop/src-tauri) unrelated to this change.

…untime<->compat cycle

core/compat/parallel.py imported core.compat.agent and core.compat.request_params
at module level. Because core.compat.__init__ imports core.compat.parallel, and
core.compat.agent imports core.compat.runtime which imports core.config (which
imports core.agent_runtime.tools.mcp), a module-level import here closes the
cycle and can turn 'import core.config' into an ImportError depending on which
entrypoint is loaded first.

Move both imports under TYPE_CHECKING (the module already has
from __future__ import annotations, so all uses are annotation-only).

Add core/agent_runtime/parallel.py as the public run_parallel_llm entry point
(docstring already referenced it) with its core.compat.parallel import deferred
into the function body, and re-export it from core.agent_runtime.__init__.

Add tests/test_import_layering.py as a regression guard: three entrypoints
must import in a fresh interpreter, and no module-level core.compat import
may appear anywhere under core/agent_runtime/ (AST-scanned with parent
pointer tracking so TYPE_CHECKING and function-body imports are allowed).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant