- harness/es.py: append-only event store + проекции (образец — кооп-портал) - harness/levels.py: уровни 1с/1м/1ч/1д, контекст ∝ масштабу - harness/scheduler.py: уровневые потоки, идемпотентные тики, absorbed-стабы - harness/isolated_runner.py + _llm_worker.py: LLM-тик в сабпроцессе (глобальный asyncio-рантайм Strands не переживает 2+ create_harness) - cli.py: init/task/tasks/status/events + requeue (написан самим минутным агентом) - 9router: отдельный ключ sk-simbiot, модель auto (glm-5.3 первым)
176 lines
5.9 KiB
Python
176 lines
5.9 KiB
Python
from __future__ import annotations
|
|
|
|
__all__ = (
|
|
"fix_package_names",
|
|
"install_lazy_importer",
|
|
"set_deprecated_aliases",
|
|
)
|
|
|
|
import ast
|
|
import inspect
|
|
import sys
|
|
import warnings
|
|
from importlib import import_module
|
|
from types import ModuleType
|
|
from typing import Any
|
|
|
|
|
|
def install_lazy_importer() -> bool:
|
|
module_globals = sys._getframe(1).f_globals
|
|
module_name = module_globals["__name__"]
|
|
module_prefix = module_name + "."
|
|
module = sys.modules[module_name]
|
|
lazy_map, deprecated_aliases, submodule_names = _build_lazy_map(module)
|
|
names = sorted(lazy_map)
|
|
|
|
# Delete symbols that are not part of the API
|
|
del module_globals["TYPE_CHECKING"]
|
|
del module_globals["install_lazy_importer"]
|
|
|
|
if not lazy_map and not deprecated_aliases:
|
|
return False
|
|
|
|
def __getattr__(name: str) -> Any:
|
|
if new_name := deprecated_aliases.get(name):
|
|
emit_deprecation_warning(module_name, name, new_name)
|
|
target_mod, target_attr = new_name.rsplit(".", 1)
|
|
elif name in submodule_names:
|
|
target_mod, target_attr = "." + name, ""
|
|
else:
|
|
try:
|
|
target_mod, target_attr = lazy_map[name]
|
|
except KeyError:
|
|
raise AttributeError(
|
|
f"module {module_name!r} has no attribute {name!r}"
|
|
) from None
|
|
|
|
imported = import_module(target_mod, module_name)
|
|
value = getattr(imported, target_attr) if target_attr else imported
|
|
|
|
# patch the module name to match
|
|
if (
|
|
getattr(value, "__module__", "").startswith(module_prefix)
|
|
and name not in deprecated_aliases
|
|
):
|
|
value.__module__ = module_name
|
|
|
|
module_globals[name] = value
|
|
return value
|
|
|
|
def __dir__() -> list[str]:
|
|
return names
|
|
|
|
module_globals["__dir__"] = __dir__
|
|
module_globals["__getattr__"] = __getattr__
|
|
module_globals.pop("fix_package_names", None)
|
|
module_globals.pop("set_deprecated_aliases", None)
|
|
return True
|
|
|
|
|
|
def fix_package_names() -> None:
|
|
module_globals = sys._getframe(1).f_globals
|
|
module_prefix = module_globals["__name__"] + "."
|
|
del module_globals[fix_package_names.__name__]
|
|
for value in module_globals.values():
|
|
if modname := getattr(value, "__module__", ""):
|
|
if modname.startswith(module_prefix):
|
|
parts = modname.split(".")
|
|
value.__module__ = ".".join(
|
|
part for part in parts if not part.startswith("_")
|
|
)
|
|
|
|
|
|
def emit_deprecation_warning(module_name: str, name: str, target: str) -> None:
|
|
warnings.warn(
|
|
f"The {module_name}.{name} alias is deprecated, use {target} instead.",
|
|
DeprecationWarning,
|
|
stacklevel=3,
|
|
)
|
|
|
|
|
|
def set_deprecated_aliases(aliases: dict[str, str]) -> None:
|
|
module_globals = sys._getframe(1).f_globals
|
|
module_name = module_globals["__name__"]
|
|
del module_globals[set_deprecated_aliases.__name__]
|
|
|
|
def __getattr__(name: str) -> Any:
|
|
try:
|
|
target = aliases[name]
|
|
except KeyError:
|
|
raise AttributeError(
|
|
f"module {module_name!r} has no attribute {name!r}"
|
|
) from None
|
|
|
|
emit_deprecation_warning(module_name, name, target)
|
|
target_modname, attrname = target.rsplit(".", 1)
|
|
module = import_module(target_modname)
|
|
return getattr(module, attrname)
|
|
|
|
sys.modules[module_name].__dict__["__getattr__"] = __getattr__
|
|
|
|
|
|
def _build_lazy_map(
|
|
module: ModuleType,
|
|
) -> tuple[dict[str, tuple[str, str]], dict[str, str], list[str]]:
|
|
try:
|
|
source = inspect.getsource(module)
|
|
except OSError:
|
|
return {}, {}, []
|
|
|
|
tree = compile(source, module.__file__ or "", "exec", ast.PyCF_ONLY_AST)
|
|
assert isinstance(tree, ast.Module)
|
|
out: dict[str, tuple[str, str]] = {}
|
|
deprecated_aliases: dict[str, str] = {}
|
|
submodule_names: list[str] = []
|
|
|
|
for node in tree.body:
|
|
if not isinstance(node, ast.If) or not _is_type_checking_block(node.test):
|
|
continue
|
|
|
|
for stmt in node.body:
|
|
match stmt:
|
|
case ast.ImportFrom():
|
|
if stmt.module is None:
|
|
submodule_names.extend(alias.name for alias in stmt.names)
|
|
else:
|
|
base = "." * stmt.level + (stmt.module or "")
|
|
for alias in stmt.names:
|
|
if alias.name == "*":
|
|
raise RuntimeError("star imports not supported")
|
|
|
|
exported = alias.asname or alias.name
|
|
out[exported] = (base, alias.name)
|
|
case ast.Expr() if isinstance(stmt.value, ast.Call):
|
|
call = stmt.value
|
|
if (
|
|
isinstance(call.func, ast.Name)
|
|
and call.func.id == "set_deprecated_aliases"
|
|
):
|
|
arg0 = call.args[0]
|
|
assert isinstance(arg0, ast.Dict)
|
|
for key, value in zip(arg0.keys, arg0.values, strict=True):
|
|
assert isinstance(key, ast.Constant)
|
|
assert isinstance(key.value, str)
|
|
assert isinstance(value, ast.Constant)
|
|
assert isinstance(value.value, str)
|
|
deprecated_aliases[key.value] = value.value
|
|
|
|
return out, deprecated_aliases, submodule_names
|
|
|
|
|
|
def _is_type_checking_block(test: ast.AST) -> bool:
|
|
if not isinstance(test, ast.BoolOp):
|
|
return False
|
|
|
|
subtest = test.values[0]
|
|
match subtest:
|
|
case ast.Name():
|
|
return subtest.id == "TYPE_CHECKING"
|
|
case ast.Attribute():
|
|
return (
|
|
isinstance(subtest.value, ast.Name)
|
|
and subtest.value.id == "typing"
|
|
and subtest.attr == "TYPE_CHECKING"
|
|
)
|
|
case _:
|
|
return False
|