- 新增 server/headless_app.py:仅挂 gateway/tasks/status/approval/usage 五件蓝图, 无 web 站点路由面(/login、会话管理、静态页全砍),根路径返回 HTML 告知页; 供 CLI 探测无服务时 spawn(同 RuntimeService 单例/数据目录/端口 8091, 与 full 形态互斥不并存) - server/chat/approval.py 拆出 approval_bp(tool/plan/question 6 条路由 URL 不变), 解除对 chat_bp 的 import 循环,full/headless 双形态共用 - cli/src/gateway.ts:spawn 切 server.headless_app;python 解释器改 pickPython 依赖探测(import yaml/flask 逐个试 .venv → homebrew 3.12/3.11 → python3), 修本机 .venv 缺 pyyaml 导致的自启动即崩 - 修复 socket 移除残留雷:make_terminal_callback 定义随 broadcast.py 被删, workflow_runtime_api 模块级 import 即炸;resources.py 补兼容空操作(恒返 None) - AGENTS.md §2 补 headless 启动命令、§12.5 补兼容空操作与 headless 形态说明 验证:tsc ✅ py_compile ✅ 冒烟 6/6 ✅ headless 装配 47 路由 ✅ 8093 真实冒烟(health/Bearer/404 面/告知页)✅ Co-authored-by: Astrion powered by Kimi-K3 <astrion-agent@users.noreply.github.com>
72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
# server/context/__init__.py - 兼容入口(原 server/context.py 拆分为子包)
|
||
# 所有历史导入路径 `from server.context import X` 不变。
|
||
#
|
||
# 2026-09-08(G4 拆解):改为 PEP 562 模块级 __getattr__ 懒加载——
|
||
# 符号首次被引用时才加载对应子模块,避免任务核心层(server.tasks)
|
||
# import 单个符号就连带拉起全部子模块(含 Web 适配层的 flask 依赖链)。
|
||
from importlib import import_module as _import_module
|
||
|
||
_SYMBOL_MODULE = {
|
||
# identity
|
||
"NoWorkspaceError": "server.context.identity",
|
||
"RuntimeIdentity": "server.context.identity",
|
||
"_resolve_user_role": "server.context.identity",
|
||
# broadcast
|
||
# personalization
|
||
"_apply_workspace_personalization_preferences": "server.context.personalization",
|
||
# usage
|
||
"get_or_create_usage_tracker": "server.context.usage",
|
||
# upload
|
||
"get_gui_manager": "server.context.upload",
|
||
"get_upload_guard": "server.context.upload",
|
||
"build_upload_error_response": "server.context.upload",
|
||
# conversation
|
||
"ensure_conversation_loaded": "server.context.conversation",
|
||
"apply_conversation_overrides": "server.context.conversation",
|
||
# resources
|
||
"get_user_resources": "server.context.resources",
|
||
"make_terminal_callback": "server.context.resources",
|
||
"_make_terminal_key": "server.context.resources",
|
||
"_touch_terminal_activity": "server.context.resources",
|
||
"_set_terminal_workspace_label": "server.context.resources",
|
||
"_ensure_workspace_skills_synced": "server.context.resources",
|
||
# decorators
|
||
"with_terminal": "server.context.decorators",
|
||
"get_terminal_for_sid": "server.context.decorators",
|
||
# reaper
|
||
"reset_system_state": "server.context.reaper",
|
||
"reap_idle_conversation_terminals": "server.context.reaper",
|
||
"start_conversation_terminal_reaper": "server.context.reaper",
|
||
}
|
||
|
||
__all__ = [
|
||
"NoWorkspaceError",
|
||
"RuntimeIdentity",
|
||
"get_user_resources",
|
||
"make_terminal_callback",
|
||
"with_terminal",
|
||
"get_terminal_for_sid",
|
||
"get_gui_manager",
|
||
"get_upload_guard",
|
||
"build_upload_error_response",
|
||
"ensure_conversation_loaded",
|
||
"apply_conversation_overrides",
|
||
"reset_system_state",
|
||
"get_or_create_usage_tracker",
|
||
"reap_idle_conversation_terminals",
|
||
"start_conversation_terminal_reaper",
|
||
]
|
||
|
||
|
||
def __getattr__(name):
|
||
module_name = _SYMBOL_MODULE.get(name)
|
||
if module_name is None:
|
||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||
value = getattr(_import_module(module_name), name)
|
||
globals()[name] = value # 缓存,后续访问直接命中
|
||
return value
|
||
|
||
|
||
def __dir__():
|
||
return sorted(set(list(globals()) + list(_SYMBOL_MODULE)))
|