@hupan56/wlkj 2.7.11 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/bin/cli.js +375 -78
  2. package/package.json +29 -29
  3. package/templates/.qoder/.runtime/ctx-cache-5660152f1d6dd819.md +23 -0
  4. package/templates/.qoder/.runtime/ctx-cache-afdce0dac06b25b0.md +23 -0
  5. package/templates/.qoder/.runtime/search-cache-eae7644e7b122f35.txt +1 -0
  6. package/templates/.qoder/learning/eval-history.jsonl +28 -0
  7. package/templates/data/index/wiki-index.json +8 -0
  8. package/templates/qoder/agents/insight-planning.md +1 -1
  9. package/templates/qoder/agents/insight-research.md +28 -15
  10. package/templates/qoder/commands/optional/wl-insight.md +159 -161
  11. package/templates/qoder/commands/optional/wl-report.md +4 -4
  12. package/templates/qoder/commands/optional/wl-status.md +2 -2
  13. package/templates/qoder/commands/wl-code.md +2 -2
  14. package/templates/qoder/commands/wl-design.md +2 -2
  15. package/templates/qoder/commands/wl-init.md +3 -3
  16. package/templates/qoder/commands/wl-prd.md +2 -2
  17. package/templates/qoder/commands/wl-req.md +43 -0
  18. package/templates/qoder/commands/wl-search.md +8 -8
  19. package/templates/qoder/commands/wl-task.md +17 -17
  20. package/templates/qoder/commands/wl-test.md +41 -15
  21. package/templates/qoder/config.yaml +17 -1
  22. package/templates/qoder/hooks/session-start.py +12 -22
  23. package/templates/qoder/nul +4 -0
  24. package/templates/qoder/rules/wl-pipeline.md +22 -48
  25. package/templates/qoder/scripts/README.md +139 -0
  26. package/templates/qoder/scripts/common/autotest_auth.py +109 -0
  27. package/templates/qoder/scripts/common/bootstrap.py +145 -0
  28. package/templates/qoder/scripts/common/check_publish.py +98 -0
  29. package/templates/qoder/scripts/common/cmd_registry.py +112 -0
  30. package/templates/qoder/scripts/common/config.py +187 -0
  31. package/templates/qoder/scripts/common/contract.py +317 -0
  32. package/templates/qoder/scripts/common/developer.py +2 -1
  33. package/templates/qoder/scripts/common/feishu.py +10 -9
  34. package/templates/qoder/scripts/common/guard.py +159 -0
  35. package/templates/qoder/scripts/common/identity.py +121 -2
  36. package/templates/qoder/scripts/common/kg_capabilities.py +182 -0
  37. package/templates/qoder/scripts/common/mcp_base.py +268 -0
  38. package/templates/qoder/scripts/common/paths.py +187 -1
  39. package/templates/qoder/scripts/common/result.py +223 -0
  40. package/templates/qoder/scripts/common/roles.py +60 -0
  41. package/templates/qoder/scripts/common/task_utils.py +21 -9
  42. package/templates/qoder/scripts/common/test_extract.py +115 -0
  43. package/templates/qoder/scripts/kg/__init__.py +11 -0
  44. package/templates/qoder/scripts/kg/build_entity_registry.py +196 -0
  45. package/templates/qoder/scripts/kg/build_relations.py +127 -0
  46. package/templates/qoder/scripts/{build_style_index.py → kg/build_style_index.py} +39 -10
  47. package/templates/qoder/scripts/kg/build_workflows.py +144 -0
  48. package/templates/qoder/scripts/{context_pack.py → kg/context_pack.py} +18 -11
  49. package/templates/qoder/scripts/{enrich_prompt.py → kg/enrich_prompt.py} +232 -226
  50. package/templates/qoder/scripts/{extract_api_params.py → kg/extract.py} +398 -246
  51. package/templates/qoder/scripts/{kg.py → kg/kg.py} +638 -708
  52. package/templates/qoder/scripts/{kg_build.py → kg/kg_build.py} +618 -612
  53. package/templates/qoder/scripts/{kg_build_db.py → kg/kg_build_db.py} +333 -327
  54. package/templates/qoder/scripts/{kg_duckdb.py → kg/kg_duckdb.py} +38 -37
  55. package/templates/qoder/scripts/{kg_incremental.py → kg/kg_incremental.py} +420 -393
  56. package/templates/qoder/scripts/{kg_link_db.py → kg/kg_link_db.py} +230 -224
  57. package/templates/qoder/scripts/{kg_semantic.py → kg/kg_semantic.py} +156 -150
  58. package/templates/qoder/scripts/kg/prefetch.py +359 -0
  59. package/templates/qoder/scripts/{search_index.py → kg/search_index.py} +70 -14
  60. package/templates/qoder/scripts/mcp/__init__.py +11 -0
  61. package/templates/qoder/scripts/{kg_mcp_server.py → mcp/kg_mcp_server.py} +77 -272
  62. package/templates/qoder/scripts/{lanhu_stdio_wrapper.py → mcp/lanhu_stdio_wrapper.py} +125 -119
  63. package/templates/qoder/scripts/{check_mcp.py → mcp/mcp_doctor.py} +515 -298
  64. package/templates/qoder/scripts/{mcp_launcher.py → mcp/mcp_launcher.py} +442 -414
  65. package/templates/qoder/scripts/{mysql_mcp_server.py → mcp/mysql_mcp_server.py} +347 -396
  66. package/templates/qoder/scripts/{zentao_mcp_server.py → mcp/zentao_mcp_server.py} +384 -424
  67. package/templates/qoder/scripts/report/__init__.py +11 -0
  68. package/templates/qoder/scripts/{add_session.py → report/add_session.py} +250 -244
  69. package/templates/qoder/scripts/{archive_prd.py → report/archive_prd.py} +383 -377
  70. package/templates/qoder/scripts/{eval_prd.py → report/eval_prd.py} +73 -11
  71. package/templates/qoder/scripts/{export.py → report/export.py} +63 -0
  72. package/templates/qoder/scripts/{fill_prototype.py → report/fill_prototype.py} +6 -0
  73. package/templates/qoder/scripts/{gen_design_doc.py → report/gen_design_doc.py} +400 -394
  74. package/templates/qoder/scripts/{learn.py → report/learn.py} +152 -146
  75. package/templates/qoder/scripts/{learn_aggregate.py → report/learn_aggregate.py} +207 -201
  76. package/templates/qoder/scripts/{report.py → report/report.py} +287 -281
  77. package/templates/qoder/scripts/report/req.py +222 -0
  78. package/templates/qoder/scripts/report/role.py +33 -0
  79. package/templates/qoder/scripts/{status.py → report/status.py} +634 -628
  80. package/templates/qoder/scripts/setup/__init__.py +11 -0
  81. package/templates/qoder/scripts/setup/carriers.py +662 -0
  82. package/templates/qoder/scripts/{init_doctor.py → setup/init_doctor.py} +63 -26
  83. package/templates/qoder/scripts/{install_qoderwork.py → setup/install_qoderwork.py} +36 -26
  84. package/templates/qoder/scripts/{platform_doctor.py → setup/platform_doctor.py} +265 -259
  85. package/templates/qoder/scripts/{repo_root.py → setup/repo_root.py} +112 -106
  86. package/templates/qoder/scripts/{setup.py → setup/setup.py} +147 -0
  87. package/templates/qoder/scripts/{setup_lanhu.py → setup/setup_lanhu.py} +973 -963
  88. package/templates/qoder/scripts/task/__init__.py +11 -0
  89. package/templates/qoder/scripts/{git_sync.py → task/git_sync.py} +52 -31
  90. package/templates/qoder/scripts/{syncgate.py → task/syncgate.py} +6 -0
  91. package/templates/qoder/scripts/task/task.py +221 -0
  92. package/templates/qoder/scripts/task/task_lifecycle.py +596 -0
  93. package/templates/qoder/scripts/task/task_query.py +161 -0
  94. package/templates/qoder/scripts/task/task_relations.py +424 -0
  95. package/templates/qoder/scripts/{team_sync.py → task/team_sync.py} +93 -20
  96. package/templates/qoder/scripts/test/__init__.py +11 -0
  97. package/templates/qoder/scripts/{autotest.py → test/autotest.py} +1174 -1751
  98. package/templates/qoder/scripts/{autotest_batch.py → test/autotest_batch.py} +242 -224
  99. package/templates/qoder/scripts/test/autotest_data.py +675 -0
  100. package/templates/qoder/scripts/{autotest_run.py → test/autotest_run.py} +309 -297
  101. package/templates/qoder/scripts/{benchmark.py → test/benchmark.py} +6 -0
  102. package/templates/qoder/scripts/{kg_auto_login.py → test/kg_auto_login.py} +202 -196
  103. package/templates/qoder/scripts/{kg_test_runner.py → test/kg_test_runner.py} +7 -1
  104. package/templates/qoder/scripts/{page_probe.py → test/page_probe.py} +465 -459
  105. package/templates/qoder/scripts/wlkj.py +116 -0
  106. package/templates/qoder/settings.json +1 -10
  107. package/templates/qoder/skills/design-import/SKILL.md +226 -226
  108. package/templates/qoder/skills/design-review/SKILL.md +82 -82
  109. package/templates/qoder/skills/prd-generator/SKILL.md +26 -16
  110. package/templates/qoder/skills/prd-review/SKILL.md +5 -5
  111. package/templates/qoder/skills/prototype-generator/SKILL.md +256 -256
  112. package/templates/qoder/skills/spec-coder/SKILL.md +4 -4
  113. package/templates/qoder/skills/spec-generator/SKILL.md +4 -4
  114. package/templates/qoder/skills/test-generator/SKILL.md +5 -5
  115. package/templates/qoder/skills/wl-code/SKILL.md +4 -4
  116. package/templates/qoder/skills/wl-commit/SKILL.md +4 -4
  117. package/templates/qoder/skills/wl-design/SKILL.md +3 -3
  118. package/templates/qoder/skills/wl-init/SKILL.md +8 -8
  119. package/templates/qoder/skills/wl-insight/SKILL.md +5 -5
  120. package/templates/qoder/skills/wl-prd-full/SKILL.md +6 -6
  121. package/templates/qoder/skills/wl-prd-quick/SKILL.md +6 -6
  122. package/templates/qoder/skills/wl-prd-review/SKILL.md +4 -4
  123. package/templates/qoder/skills/wl-report/SKILL.md +7 -7
  124. package/templates/qoder/skills/wl-search/SKILL.md +13 -13
  125. package/templates/qoder/skills/wl-spec/SKILL.md +5 -5
  126. package/templates/qoder/skills/wl-status/SKILL.md +5 -5
  127. package/templates/qoder/skills/wl-task/SKILL.md +6 -6
  128. package/templates/qoder/skills/wl-test/SKILL.md +102 -39
  129. package/templates/root/AGENTS.md +39 -40
  130. package/templates/qoder/hooks/inject-workflow-state.py +0 -169
  131. package/templates/qoder/scripts/__pycache__/check_mcp_launch.cpython-39.pyc +0 -0
  132. package/templates/qoder/scripts/__pycache__/install_qoderwork.cpython-39.pyc +0 -0
  133. package/templates/qoder/scripts/__pycache__/mcp_launcher.cpython-39.pyc +0 -0
  134. package/templates/qoder/scripts/__pycache__/platform_doctor.cpython-39.pyc +0 -0
  135. package/templates/qoder/scripts/check_carriers.py +0 -238
  136. package/templates/qoder/scripts/check_mcp_launch.py +0 -183
  137. package/templates/qoder/scripts/check_qoderwork_consistency.py +0 -166
  138. package/templates/qoder/scripts/collect_prds.py +0 -31
  139. package/templates/qoder/scripts/common/mentions.py +0 -134
  140. package/templates/qoder/scripts/common/utf8.py +0 -38
  141. package/templates/qoder/scripts/extract_routes.py +0 -54
  142. package/templates/qoder/scripts/extract_routes_tree.py +0 -78
  143. package/templates/qoder/scripts/handoff.py +0 -22
  144. package/templates/qoder/scripts/init_developer.py +0 -76
  145. package/templates/qoder/scripts/parse_prds.py +0 -33
  146. package/templates/qoder/scripts/role.py +0 -51
  147. package/templates/qoder/scripts/sync_carriers.py +0 -259
  148. package/templates/qoder/scripts/task.py +0 -1261
  149. package/templates/qoder/scripts/workspace_init.py +0 -102
  150. package/templates/qoder/skills/prompt-enrich/SKILL.md +0 -90
  151. package/templates/qoder/skills/prototype-generator/SKILL.md.zcode-79180-2af4721f-f9a6-412c-88db-c0af680d211b.tmp +0 -0
  152. /package/templates/qoder/scripts/{secure-ls.js → test/secure-ls.js} +0 -0
@@ -1,119 +1,125 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- lanhu_stdio_wrapper.py - 蓝湖 MCP STDIO 启动包装(角色隔离 + QoderWork 自动开关)
5
-
6
- 被谁调用:
7
- QoderWork ~/.qoderwork/mcp.json lanhu.command 拉起本脚本。
8
- QoderWork 管本进程的生死 (开 QoderWork 自动拉起, 关 QoderWork 自动杀)。
9
-
10
- 做什么:
11
- 1. 定位仓库根
12
- 2. 读 .qoder/.developer → 当前角色 (UI设计师/PM/开发...)
13
- 3. workspace/members/{角色}/.secrets/lanhu.env 该角色的蓝湖 cookie
14
- 4. 注入环境变量 (LANHU_COOKIE + MCP_TRANSPORT=stdio + LANHU_USER_NAME)
15
- 5. os.execv() 拉起 lanhu_mcp_server.py (用 venv 的 3.10+ python)
16
-
17
- 为什么用 wrapper 而不是直接在 mcp.json 写 cookie:
18
- 蓝湖权限按角色分 (UI 能改稿, PM/开发只读)
19
- cookie 必须按角色隔离, .developer 时跟着换。
20
- wrapper 每次启动读当前角色 用对应 cookie 权限正确。
21
- cookie 不进 mcp.json (那是机器级全局, 不按人), 仍按角色存 .secrets/。
22
-
23
- 为什么用 os.execv 而非 subprocess:
24
- execv lanhu server 直接替换 wrapper 进程。
25
- QoderWork 杀的就是 lanhu server 本身, 不留孤儿 wrapper 进程。
26
-
27
- 跨平台:
28
- 纯 Python, os.execv + venv python 路径跨平台 (win Scripts/python.exe, mac bin/python)。
29
- """
30
-
31
- import os
32
- import sys
33
- from pathlib import Path
34
-
35
- try:
36
- sys.stderr.reconfigure(encoding='utf-8', errors='replace')
37
- except (AttributeError, TypeError, OSError):
38
- pass
39
-
40
- # 定位仓库根: 本文件在 <repo>/.qoder/scripts/ → 上三级
41
- SCRIPT_DIR = Path(__file__).resolve().parent
42
- BASE = SCRIPT_DIR.parent.parent # repo root
43
-
44
-
45
- def _find_repo_root():
46
- """定位仓库根。本文件在 .qoder/scripts/, 上三级即根。
47
- 兜底: 上溯找 .qoder/ 目录。"""
48
- if (BASE / '.qoder').is_dir():
49
- return BASE
50
- # 兜底: 上溯 10 级找 .qoder/
51
- cur = SCRIPT_DIR
52
- for _ in range(10):
53
- if (cur / '.qoder').is_dir():
54
- return cur
55
- parent = cur.parent
56
- if parent == cur:
57
- break
58
- cur = parent
59
- return BASE # 找不到回退默认
60
-
61
-
62
- def main():
63
- repo = _find_repo_root()
64
-
65
- # 复用 setup_lanhu.py 的角色探测 + cookie 读取 (单一事实源)
66
- sys.path.insert(0, str(repo / '.qoder' / 'scripts'))
67
- try:
68
- from setup_lanhu import (_current_developer, lanhu_env_file,
69
- _read_env_cookie, _venv_python,
70
- LANHU_VENV, LANHU_SERVER_SCRIPT, COOKIE_PLACEHOLDER)
71
- except ImportError as e:
72
- sys.stderr.write(f'[lanhu-wrapper] 无法导入 setup_lanhu: {e}\n')
73
- sys.stderr.write(f'[lanhu-wrapper] 检查 {repo}/.qoder/scripts/setup_lanhu.py 是否存在\n')
74
- sys.exit(1)
75
-
76
- # 1. 当前角色
77
- dev = _current_developer()
78
- if not dev:
79
- sys.stderr.write('[lanhu-wrapper] 未初始化开发者 (.qoder/.developer 不存在)。\n')
80
- sys.stderr.write(' 跑 /wl-init 或 python .qoder/scripts/setup.py 初始化。\n')
81
- sys.exit(1)
82
-
83
- # 2. 该角色的 cookie
84
- cookie = _read_env_cookie(dev)
85
- if not cookie or cookie == COOKIE_PLACEHOLDER:
86
- env_file = lanhu_env_file(dev)
87
- sys.stderr.write(f'[lanhu-wrapper] 角色 {dev} 的蓝湖 cookie 未配置 (占位/缺失)。\n')
88
- sys.stderr.write(f' 编辑 {env_file}, 把 {COOKIE_PLACEHOLDER} 换成真 cookie。\n')
89
- sys.stderr.write(' 获取: lanhuapp.com 登录 → F12 → Network → Cookie 头整行复制\n')
90
- sys.stderr.write(' (蓝湖工具将不可用, 但工作流其他功能不受影响)\n')
91
- sys.exit(1)
92
-
93
- # 3. venv python (lanhu 依赖要求 3.10+)
94
- venv_py = _venv_python(LANHU_VENV)
95
- if not venv_py.is_file():
96
- sys.stderr.write(f'[lanhu-wrapper] 蓝湖 venv 不存在: {venv_py}\n')
97
- sys.stderr.write(' 跑 python .qoder/scripts/setup_lanhu.py 安装蓝湖依赖\n')
98
- sys.exit(1)
99
-
100
- if not LANHU_SERVER_SCRIPT.is_file():
101
- sys.stderr.write(f'[lanhu-wrapper] 蓝湖服务脚本不存在: {LANHU_SERVER_SCRIPT}\n')
102
- sys.stderr.write(' python .qoder/scripts/setup_lanhu.py clone 蓝湖源码\n')
103
- sys.exit(1)
104
-
105
- # 4. 注入环境变量 (角色隔离的核心: cookie + 用户名都是当前角色的)
106
- os.environ['LANHU_COOKIE'] = cookie
107
- os.environ['MCP_TRANSPORT'] = 'stdio'
108
- os.environ['LANHU_USER_NAME'] = dev
109
- os.environ['LANHU_USER_ROLE'] = 'Developer'
110
-
111
- # 调试日志打到 stderr (MCP stdio 协议用 stdout, 不能污染)
112
- sys.stderr.write(f'[lanhu-wrapper] 启动蓝湖 MCP (STDIO, 角色: {dev})\n')
113
-
114
- # 5. execv 拉起 lanhu server (接管进程, QoderWork 直接管它生死)
115
- os.execv(str(venv_py), [str(venv_py), str(LANHU_SERVER_SCRIPT)])
116
-
117
-
118
- if __name__ == '__main__':
119
- main()
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
4
+ import os as _o, sys as _s
5
+ _cp = _o.path.join(_o.path.dirname(_o.path.dirname(_o.path.abspath(__file__))), 'common')
6
+ if _cp not in _s.path: _s.path.insert(0, _cp)
7
+ from bootstrap import setup; setup()
8
+
9
+ """
10
+ lanhu_stdio_wrapper.py - 蓝湖 MCP STDIO 启动包装(角色隔离 + QoderWork 自动开关)
11
+
12
+ 被谁调用:
13
+ QoderWork ~/.qoderwork/mcp.json lanhu.command 拉起本脚本。
14
+ QoderWork 管本进程的生死 ( QoderWork 自动拉起, QoderWork 自动杀)
15
+
16
+ 做什么:
17
+ 1. 定位仓库根
18
+ 2. 读 .qoder/.developer → 当前角色 (UI设计师/PM/开发...)
19
+ 3. workspace/members/{角色}/.secrets/lanhu.env → 该角色的蓝湖 cookie
20
+ 4. 注入环境变量 (LANHU_COOKIE + MCP_TRANSPORT=stdio + LANHU_USER_NAME)
21
+ 5. os.execv() 拉起 lanhu_mcp_server.py ( venv 3.10+ python)
22
+
23
+ 为什么用 wrapper 而不是直接在 mcp.json cookie:
24
+ 蓝湖权限按角色分 (UI 能改稿, PM/开发只读)。
25
+ cookie 必须按角色隔离, .developer 时跟着换。
26
+ wrapper 每次启动读当前角色 → 用对应 cookie → 权限正确。
27
+ cookie 不进 mcp.json (那是机器级全局, 不按人), 仍按角色存 .secrets/。
28
+
29
+ 为什么用 os.execv 而非 subprocess:
30
+ execv 让 lanhu server 直接替换 wrapper 进程。
31
+ QoderWork 杀的就是 lanhu server 本身, 不留孤儿 wrapper 进程。
32
+
33
+ 跨平台:
34
+ 纯 Python, os.execv + venv python 路径跨平台 (win Scripts/python.exe, mac bin/python)。
35
+ """
36
+
37
+ import os
38
+ import sys
39
+ from pathlib import Path
40
+
41
+ try:
42
+ sys.stderr.reconfigure(encoding='utf-8', errors='replace')
43
+ except (AttributeError, TypeError, OSError):
44
+ pass
45
+
46
+ # 定位仓库根: 本文件在 <repo>/.qoder/scripts/ → 上三级
47
+ SCRIPT_DIR = Path(__file__).resolve().parent
48
+ BASE = SCRIPT_DIR.parent.parent # repo root
49
+
50
+
51
+ def _find_repo_root():
52
+ """定位仓库根。本文件在 .qoder/scripts/, 上三级即根。
53
+ 兜底: 上溯找 .qoder/ 目录。"""
54
+ if (BASE / '.qoder').is_dir():
55
+ return BASE
56
+ # 兜底: 上溯 10 级找 .qoder/
57
+ cur = SCRIPT_DIR
58
+ for _ in range(10):
59
+ if (cur / '.qoder').is_dir():
60
+ return cur
61
+ parent = cur.parent
62
+ if parent == cur:
63
+ break
64
+ cur = parent
65
+ return BASE # 找不到回退默认
66
+
67
+
68
+ def main():
69
+ repo = _find_repo_root()
70
+
71
+ # 复用 setup_lanhu.py 的角色探测 + cookie 读取 (单一事实源)
72
+ sys.path.insert(0, str(repo / '.qoder' / 'scripts'))
73
+ try:
74
+ from setup_lanhu import (_current_developer, lanhu_env_file,
75
+ _read_env_cookie, _venv_python,
76
+ LANHU_VENV, LANHU_SERVER_SCRIPT, COOKIE_PLACEHOLDER)
77
+ except ImportError as e:
78
+ sys.stderr.write(f'[lanhu-wrapper] 无法导入 setup_lanhu: {e}\n')
79
+ sys.stderr.write(f'[lanhu-wrapper] 检查 {repo}/.qoder/scripts/setup_lanhu.py 是否存在\n')
80
+ sys.exit(1)
81
+
82
+ # 1. 当前角色
83
+ dev = _current_developer()
84
+ if not dev:
85
+ sys.stderr.write('[lanhu-wrapper] 未初始化开发者 (.qoder/.developer 不存在)。\n')
86
+ sys.stderr.write(' 跑 /wl-init 或 python .qoder/scripts/setup.py 初始化。\n')
87
+ sys.exit(1)
88
+
89
+ # 2. 该角色的 cookie
90
+ cookie = _read_env_cookie(dev)
91
+ if not cookie or cookie == COOKIE_PLACEHOLDER:
92
+ env_file = lanhu_env_file(dev)
93
+ sys.stderr.write(f'[lanhu-wrapper] 角色 {dev} 的蓝湖 cookie 未配置 (占位/缺失)。\n')
94
+ sys.stderr.write(f' 编辑 {env_file}, 把 {COOKIE_PLACEHOLDER} 换成真 cookie。\n')
95
+ sys.stderr.write(' 获取: lanhuapp.com 登录 → F12 → Network → Cookie 头整行复制\n')
96
+ sys.stderr.write(' (蓝湖工具将不可用, 但工作流其他功能不受影响)\n')
97
+ sys.exit(1)
98
+
99
+ # 3. venv python (lanhu 依赖要求 3.10+)
100
+ venv_py = _venv_python(LANHU_VENV)
101
+ if not venv_py.is_file():
102
+ sys.stderr.write(f'[lanhu-wrapper] 蓝湖 venv 不存在: {venv_py}\n')
103
+ sys.stderr.write(' 跑 python .qoder/scripts/setup_lanhu.py 安装蓝湖依赖\n')
104
+ sys.exit(1)
105
+
106
+ if not LANHU_SERVER_SCRIPT.is_file():
107
+ sys.stderr.write(f'[lanhu-wrapper] 蓝湖服务脚本不存在: {LANHU_SERVER_SCRIPT}\n')
108
+ sys.stderr.write(' python .qoder/scripts/setup_lanhu.py clone 蓝湖源码\n')
109
+ sys.exit(1)
110
+
111
+ # 4. 注入环境变量 (角色隔离的核心: cookie + 用户名都是当前角色的)
112
+ os.environ['LANHU_COOKIE'] = cookie
113
+ os.environ['MCP_TRANSPORT'] = 'stdio'
114
+ os.environ['LANHU_USER_NAME'] = dev
115
+ os.environ['LANHU_USER_ROLE'] = 'Developer'
116
+
117
+ # 调试日志打到 stderr (MCP stdio 协议用 stdout, 不能污染)
118
+ sys.stderr.write(f'[lanhu-wrapper] 启动蓝湖 MCP (STDIO, 角色: {dev})\n')
119
+
120
+ # 5. execv 拉起 lanhu server (接管进程, QoderWork 直接管它生死)
121
+ os.execv(str(venv_py), [str(venv_py), str(LANHU_SERVER_SCRIPT)])
122
+
123
+
124
+ if __name__ == '__main__':
125
+ main()