@hupan56/wlkj 3.0.0 → 3.1.2
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.
- package/bin/cli.js +1435 -1373
- package/package.json +1 -1
- package/templates/qoder/commands/optional/wl-insight.md +6 -4
- package/templates/qoder/commands/optional/wl-report.md +20 -39
- package/templates/qoder/commands/optional/wl-status.md +4 -4
- package/templates/qoder/commands/wl-code.md +2 -2
- package/templates/qoder/commands/wl-design.md +5 -5
- package/templates/qoder/commands/wl-init.md +3 -3
- package/templates/qoder/commands/wl-prd.md +26 -13
- package/templates/qoder/commands/wl-req.md +3 -3
- package/templates/qoder/commands/wl-search.md +78 -47
- package/templates/qoder/commands/wl-task.md +343 -40
- package/templates/qoder/commands/wl-test.md +10 -10
- package/templates/qoder/config.yaml +35 -13
- package/templates/qoder/hooks/post-tool-use.py +181 -0
- package/templates/qoder/hooks/session-start.py +82 -1
- package/templates/qoder/hooks/stop-eval.py +207 -0
- package/templates/qoder/hooks/user-prompt-submit.py +139 -0
- package/templates/qoder/rules/wl-pipeline.md +70 -8
- package/templates/qoder/scripts/README.md +78 -115
- package/templates/qoder/scripts/capability/__init__.py +26 -0
- package/templates/qoder/scripts/capability/__main__.py +72 -0
- package/templates/qoder/scripts/capability/adapters/__init__.py +29 -0
- package/templates/qoder/scripts/capability/adapters/cli.py +316 -0
- package/templates/qoder/scripts/capability/adapters/mcp.py +334 -0
- package/templates/qoder/scripts/capability/adapters/qw.py +271 -0
- package/templates/qoder/scripts/capability/caps/__init__.py +27 -0
- package/templates/qoder/scripts/capability/caps/context.py +36 -0
- package/templates/qoder/scripts/capability/caps/cron.py +50 -0
- package/templates/qoder/scripts/capability/caps/identity.py +43 -0
- package/templates/qoder/scripts/capability/caps/memory.py +71 -0
- package/templates/qoder/scripts/capability/caps/notify.py +41 -0
- package/templates/qoder/scripts/capability/caps/present.py +48 -0
- package/templates/qoder/scripts/capability/caps/repo.py +31 -0
- package/templates/qoder/scripts/capability/caps/sandbox.py +43 -0
- package/templates/qoder/scripts/capability/chain.py +92 -0
- package/templates/qoder/scripts/capability/memory_chain.py +41 -0
- package/templates/qoder/scripts/capability/registry.py +246 -0
- package/templates/qoder/scripts/capability/registry_mcp.py +250 -0
- package/templates/qoder/scripts/capability/smoke_test.py +211 -0
- package/templates/qoder/scripts/capability/smoke_test_report.json +94 -0
- package/templates/qoder/scripts/{report → deployment/setup}/__init__.py +11 -11
- package/templates/qoder/scripts/{setup → deployment/setup}/carriers.py +33 -26
- package/templates/qoder/scripts/deployment/setup/carriers_verify.py +148 -0
- package/templates/qoder/scripts/{setup → deployment/setup}/init_doctor.py +40 -16
- package/templates/qoder/scripts/{setup → deployment/setup}/install_qoderwork.py +20 -12
- package/templates/qoder/scripts/{setup → deployment/setup}/platform_doctor.py +8 -2
- package/templates/qoder/scripts/{setup → deployment/setup}/repo_root.py +113 -112
- package/templates/qoder/scripts/{setup → deployment/setup}/setup.py +31 -11
- package/templates/qoder/scripts/{setup → deployment/setup}/setup_lanhu.py +13 -7
- package/templates/qoder/scripts/domain/__init__.py +0 -0
- package/templates/qoder/scripts/domain/design/__init__.py +0 -0
- package/templates/qoder/scripts/{report → domain/design}/fill_prototype.py +12 -6
- package/templates/qoder/scripts/{report → domain/design}/gen_design_doc.py +8 -2
- package/templates/qoder/scripts/{setup → domain/kg}/__init__.py +11 -11
- package/templates/qoder/scripts/domain/kg/build/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_entity_registry.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_relations.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_style_index.py +13 -7
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_workflows.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_build.py +76 -9
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_build_db.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_incremental.py +11 -6
- package/templates/qoder/scripts/{report → domain/kg/build}/learn_aggregate.py +9 -4
- package/templates/qoder/scripts/domain/kg/extract/__init__.py +0 -0
- package/templates/qoder/scripts/{common → domain/kg/extract}/extract.py +430 -419
- package/templates/qoder/scripts/{common → domain/kg/extract}/test_extract.py +115 -115
- package/templates/qoder/scripts/{common → domain/kg/extract}/ts_extract.py +614 -536
- package/templates/qoder/scripts/domain/kg/graph/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/graph}/kg_link_db.py +7 -2
- package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +683 -0
- package/templates/qoder/scripts/{kg → domain/kg}/kg.py +263 -30
- package/templates/qoder/scripts/{common → domain/kg}/kg_capabilities.py +182 -182
- package/templates/qoder/scripts/domain/kg/search/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/search}/context_pack.py +30 -9
- package/templates/qoder/scripts/{kg → domain/kg/search}/enrich_prompt.py +10 -4
- package/templates/qoder/scripts/{kg → domain/kg/search}/prefetch.py +33 -8
- package/templates/qoder/scripts/{common → domain/kg/search}/search_engine.py +207 -205
- package/templates/qoder/scripts/{kg → domain/kg/search}/search_index.py +143 -77
- package/templates/qoder/scripts/domain/kg/server/__init__.py +0 -0
- package/templates/qoder/scripts/domain/kg/server/kgd.py +549 -0
- package/templates/qoder/scripts/domain/kg/server/perf_bench.py +197 -0
- package/templates/qoder/scripts/domain/kg/storage/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/storage}/kg_duckdb.py +38 -14
- package/templates/qoder/scripts/domain/learning/__init__.py +0 -0
- package/templates/qoder/scripts/{report → domain/learning}/learn.py +8 -3
- package/templates/qoder/scripts/{mcp → domain/report}/__init__.py +11 -11
- package/templates/qoder/scripts/{report → domain/report}/add_session.py +9 -3
- package/templates/qoder/scripts/{report → domain/report}/export.py +10 -5
- package/templates/qoder/scripts/{report → domain/report}/report.py +9 -4
- package/templates/qoder/scripts/domain/report/report_snapshot.py +261 -0
- package/templates/qoder/scripts/{report → domain/report}/role.py +10 -4
- package/templates/qoder/scripts/{report → domain/report}/status.py +112 -9
- package/templates/qoder/scripts/domain/report/status_snapshot.py +191 -0
- package/templates/qoder/scripts/domain/requirement/__init__.py +0 -0
- package/templates/qoder/scripts/{report → domain/requirement}/archive_prd.py +8 -2
- package/templates/qoder/scripts/{report → domain/requirement}/req.py +228 -222
- package/templates/qoder/scripts/{kg → domain/task}/__init__.py +11 -11
- package/templates/qoder/scripts/{task → domain/task}/git_sync.py +40 -21
- package/templates/qoder/scripts/{task → domain/task}/syncgate.py +13 -8
- package/templates/qoder/scripts/{task → domain/task}/task.py +13 -5
- package/templates/qoder/scripts/{task → domain/task}/task_lifecycle.py +606 -596
- package/templates/qoder/scripts/{task → domain/task}/task_query.py +162 -161
- package/templates/qoder/scripts/{task → domain/task}/task_relations.py +425 -424
- package/templates/qoder/scripts/{task → domain/task}/team_sync.py +9 -4
- package/templates/qoder/scripts/domain/task/zentao_sync.py +370 -0
- package/templates/qoder/scripts/foundation/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation}/bootstrap.py +10 -10
- package/templates/qoder/scripts/foundation/core/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/core}/cmd_registry.py +1 -1
- package/templates/qoder/scripts/{common → foundation/core}/config.py +1 -1
- package/templates/qoder/scripts/{common → foundation/core}/paths.py +706 -586
- package/templates/qoder/scripts/foundation/data/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/data}/contract.py +2 -2
- package/templates/qoder/scripts/{common → foundation/data}/events.py +2 -2
- package/templates/qoder/scripts/{common → foundation/data}/result.py +1 -1
- package/templates/qoder/scripts/{common → foundation/data}/task_utils.py +427 -404
- package/templates/qoder/scripts/foundation/identity/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/identity}/check_publish.py +103 -98
- package/templates/qoder/scripts/{common → foundation/identity}/developer.py +239 -239
- package/templates/qoder/scripts/{common → foundation/identity}/guard.py +2 -2
- package/templates/qoder/scripts/{common → foundation/identity}/identity.py +14 -10
- package/templates/qoder/scripts/{common → foundation/identity}/roles.py +1 -1
- package/templates/qoder/scripts/foundation/integrations/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/integrations}/active_task.py +30 -15
- package/templates/qoder/scripts/{common → foundation/integrations}/feishu.py +2 -2
- package/templates/qoder/scripts/{common → foundation/integrations}/terms.py +3 -3
- package/templates/qoder/scripts/foundation/integrations/zentao_client.py +220 -0
- package/templates/qoder/scripts/foundation/io/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/io}/filelock.py +1 -1
- package/templates/qoder/scripts/{common → foundation/io}/reqid.py +1 -1
- package/templates/qoder/scripts/foundation/protocol/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/protocol/duckdb_conn.py +39 -0
- package/templates/qoder/scripts/{common → foundation/protocol}/mcp_base.py +1 -1
- package/templates/qoder/scripts/foundation/utils/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/utils}/eval_api.py +12 -1
- package/templates/qoder/scripts/{common → foundation/utils}/pip_install.py +23 -6
- package/templates/qoder/scripts/{common → foundation/utils}/platform_guard.py +1 -1
- package/templates/qoder/scripts/orchestration/__init__.py +0 -0
- package/templates/qoder/scripts/orchestration/wlkj.py +185 -0
- package/templates/qoder/scripts/protocol/__init__.py +0 -0
- package/templates/qoder/scripts/protocol/browser/README.md +207 -0
- package/templates/qoder/scripts/protocol/browser/SKILL.md +265 -0
- package/templates/qoder/scripts/protocol/browser/config.env +9 -0
- package/templates/qoder/scripts/protocol/browser/references/cdp-api.md +110 -0
- package/templates/qoder/scripts/protocol/browser/references/migration-2.5.3.md +72 -0
- package/templates/qoder/scripts/protocol/browser/references/site-patterns/.gitkeep +0 -0
- package/templates/qoder/scripts/protocol/browser/scripts/browser-discovery.mjs +138 -0
- package/templates/qoder/scripts/protocol/browser/scripts/cdp-proxy.mjs +672 -0
- package/templates/qoder/scripts/protocol/browser/scripts/check-deps.mjs +206 -0
- package/templates/qoder/scripts/protocol/browser/scripts/find-url.mjs +253 -0
- package/templates/qoder/scripts/protocol/browser/scripts/match-site.mjs +46 -0
- package/templates/qoder/scripts/protocol/browser/templates/config.env.template +9 -0
- package/templates/qoder/scripts/protocol/mcp/__init__.py +11 -0
- package/templates/qoder/scripts/protocol/mcp/kg_mcp_server.py +478 -0
- package/templates/qoder/scripts/{mcp → protocol/mcp}/lanhu_stdio_wrapper.py +11 -5
- package/templates/qoder/scripts/{mcp → protocol/mcp}/mcp_doctor.py +47 -14
- package/templates/qoder/scripts/protocol/mcp/mcp_launcher.py +600 -0
- package/templates/qoder/scripts/{mcp → protocol/mcp}/mysql_mcp_server.py +181 -67
- package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +1920 -0
- package/templates/qoder/scripts/protocol/transports/__init__.py +56 -0
- package/templates/qoder/scripts/protocol/transports/base.py +87 -0
- package/templates/qoder/scripts/protocol/transports/cli.py +132 -0
- package/templates/qoder/scripts/protocol/transports/http.py +141 -0
- package/templates/qoder/scripts/protocol/transports/stdio.py +293 -0
- package/templates/qoder/scripts/run_weekly_update.bat +27 -18
- package/templates/qoder/scripts/run_weekly_update.sh +22 -13
- package/templates/qoder/scripts/validation/__init__.py +0 -0
- package/templates/qoder/scripts/validation/eval/__init__.py +0 -0
- package/templates/qoder/scripts/validation/eval/perf-report-2026-06-24.md +139 -0
- package/templates/qoder/scripts/validation/eval/qwork_harness.py +617 -0
- package/templates/qoder/scripts/validation/eval/report-commands.md +220 -0
- package/templates/qoder/scripts/validation/eval/transcript_timing.py +386 -0
- package/templates/qoder/scripts/validation/metrics/__init__.py +0 -0
- package/templates/qoder/scripts/{report → validation/metrics}/eval_prd.py +17 -10
- package/templates/qoder/scripts/validation/metrics/usability_score.py +750 -0
- package/templates/qoder/scripts/validation/test/__init__.py +11 -0
- package/templates/qoder/scripts/validation/test/assertion_gen.py +551 -0
- package/templates/qoder/scripts/{test → validation/test}/autotest.py +64 -4
- package/templates/qoder/scripts/{common → validation/test}/autotest_auth.py +1 -1
- package/templates/qoder/scripts/{test → validation/test}/autotest_batch.py +16 -3
- package/templates/qoder/scripts/{test → validation/test}/autotest_data.py +17 -12
- package/templates/qoder/scripts/validation/test/autotest_opencli.py +646 -0
- package/templates/qoder/scripts/{test → validation/test}/autotest_run.py +17 -3
- package/templates/qoder/scripts/validation/test/autotest_webaccess.py +571 -0
- package/templates/qoder/scripts/{test → validation/test}/benchmark.py +12 -6
- package/templates/qoder/scripts/{test → validation/test}/kg_auto_login.py +8 -2
- package/templates/qoder/scripts/{test → validation/test}/kg_test_runner.py +7 -2
- package/templates/qoder/scripts/{test → validation/test}/page_probe.py +8 -3
- package/templates/qoder/scripts/validation/test/smoke_all_commands.py +170 -0
- package/templates/qoder/settings.json +30 -0
- package/templates/qoder/skills/design-import/SKILL.md +22 -13
- package/templates/qoder/skills/design-review/SKILL.md +19 -10
- package/templates/qoder/skills/prd-generator/SKILL.md +22 -18
- package/templates/qoder/skills/prd-review/SKILL.md +6 -4
- package/templates/qoder/skills/prototype-generator/SKILL.md +63 -14
- package/templates/qoder/skills/spec-coder/SKILL.md +22 -13
- package/templates/qoder/skills/spec-generator/SKILL.md +22 -10
- package/templates/qoder/skills/test-generator/SKILL.md +7 -5
- package/templates/qoder/skills/wl-code/SKILL.md +23 -11
- package/templates/qoder/skills/wl-commit/SKILL.md +9 -8
- package/templates/qoder/skills/wl-design/SKILL.md +5 -3
- package/templates/qoder/skills/wl-init/SKILL.md +6 -6
- package/templates/qoder/skills/wl-insight/SKILL.md +23 -10
- package/templates/qoder/skills/wl-prd-full/SKILL.md +57 -6
- package/templates/qoder/skills/wl-prd-quick/SKILL.md +3 -3
- package/templates/qoder/skills/wl-prd-review/SKILL.md +16 -4
- package/templates/qoder/skills/wl-report/SKILL.md +25 -23
- package/templates/qoder/skills/wl-search/SKILL.md +149 -78
- package/templates/qoder/skills/wl-spec/SKILL.md +7 -5
- package/templates/qoder/skills/wl-status/SKILL.md +48 -16
- package/templates/qoder/skills/wl-task/SKILL.md +92 -10
- package/templates/qoder/skills/wl-test/SKILL.md +75 -29
- package/templates/qoder/templates/prd-full-template.md +7 -0
- package/templates/root/AGENTS.md +275 -236
- package/templates/root/requirements.txt +3 -0
- package/templates/root//344/275/277/347/224/250/350/257/264/346/230/216.md +3 -3
- package/templates/root//346/226/260/346/211/213/346/214/207/345/215/227.md +2 -2
- package/templates/.qoder/.runtime/ctx-cache-5660152f1d6dd819.md +0 -23
- package/templates/.qoder/.runtime/ctx-cache-afdce0dac06b25b0.md +0 -23
- package/templates/.qoder/.runtime/search-cache-eae7644e7b122f35.txt +0 -1
- package/templates/.qoder/learning/eval-history.jsonl +0 -28
- package/templates/data/index/wiki-index.json +0 -8
- package/templates/qoder/nul +0 -4
- package/templates/qoder/scripts/kg/extract.py +0 -398
- package/templates/qoder/scripts/kg/kg_semantic.py +0 -156
- package/templates/qoder/scripts/mcp/kg_mcp_server.py +0 -606
- package/templates/qoder/scripts/mcp/mcp_launcher.py +0 -442
- package/templates/qoder/scripts/mcp/zentao_mcp_server.py +0 -384
- package/templates/qoder/scripts/task/__init__.py +0 -11
- package/templates/qoder/scripts/test/__init__.py +0 -11
- package/templates/qoder/scripts/wlkj.py +0 -116
- /package/templates/qoder/scripts/{common → deployment}/__init__.py +0 -0
- /package/templates/qoder/scripts/{common → domain/kg/graph}/graph_traverse.py +0 -0
- /package/templates/qoder/scripts/{common → domain/kg/server}/repowiki.py +0 -0
- /package/templates/qoder/scripts/{common → foundation/io}/atomicio.py +0 -0
- /package/templates/qoder/scripts/{test → validation/test}/secure-ls.js +0 -0
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
4
4
|
import os as _o, sys as _s
|
|
5
|
-
|
|
5
|
+
_f = _o.path.abspath(__file__)
|
|
6
|
+
for _ in range(10):
|
|
7
|
+
_f = _o.path.dirname(_f)
|
|
8
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
9
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
10
|
+
break
|
|
6
11
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
7
12
|
from bootstrap import setup; setup()
|
|
8
13
|
|
|
@@ -50,12 +55,12 @@ except (AttributeError, TypeError, OSError, IOError):
|
|
|
50
55
|
except Exception:
|
|
51
56
|
pass
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
sys.path.insert(0, SCRIPTS_DIR)
|
|
58
|
+
from foundation.core.paths import get_repo_root, get_developer, get_developer_info
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
SCRIPTS_DIR = str(get_repo_root())
|
|
61
|
+
sys.path.insert(0, SCRIPTS_DIR)
|
|
57
62
|
|
|
58
|
-
BASE =
|
|
63
|
+
BASE = SCRIPTS_DIR
|
|
59
64
|
CODE_DIR = os.path.join(BASE, 'data', 'code')
|
|
60
65
|
INDEX_DIR = os.path.join(BASE, 'data', 'index')
|
|
61
66
|
TPL_DIR = os.path.join(BASE, '.qoder', 'templates')
|
|
@@ -101,7 +106,7 @@ def run_script(script, *args, timeout=1800):
|
|
|
101
106
|
def load_config():
|
|
102
107
|
"""v3.0: 转发到 Config 单例 (带 mtime 缓存)。"""
|
|
103
108
|
try:
|
|
104
|
-
from
|
|
109
|
+
from foundation.core.config import Config
|
|
105
110
|
return Config.load().raw
|
|
106
111
|
except Exception:
|
|
107
112
|
cfg = os.path.join(BASE, '.qoder', 'config.yaml')
|
|
@@ -185,11 +190,29 @@ def check_dependencies(fix=False):
|
|
|
185
190
|
req = os.path.join(BASE, 'requirements.txt')
|
|
186
191
|
if os.path.isfile(req):
|
|
187
192
|
# 用镜像兜底安装: 默认源失败 → 自动切清华/阿里/腾讯
|
|
188
|
-
|
|
193
|
+
# 注意: install_with_fallback 在 Anaconda 3.9+ Windows 上, pip 长时间编译
|
|
194
|
+
# 退出时偶发 GIL 崩溃 (Python 进程死)。这里 try 兜住: 崩了就用 os.system
|
|
195
|
+
# 跑裸 pip (独立进程, 无 GIL 问题) 兜底, 绝不让 doctor --fix 卡死。
|
|
189
196
|
print(' → 安装: pip install -r requirements.txt (失败自动切国内镜像)')
|
|
190
|
-
result =
|
|
197
|
+
result = None
|
|
198
|
+
try:
|
|
199
|
+
from foundation.utils.pip_install import install_with_fallback
|
|
200
|
+
result = install_with_fallback(['-r', req])
|
|
201
|
+
except Exception as _e:
|
|
202
|
+
print(' [WARN] 镜像安装工具异常 (%s), 改用直装' % str(_e)[:60])
|
|
203
|
+
# 工具崩了或返回失败 → 用 os.system 直装 (清华镜像, 独立进程无 GIL 风险)
|
|
204
|
+
if not result or not result.get('ok'):
|
|
205
|
+
print(' → 直装: pip install -r requirements.txt (清华镜像)')
|
|
206
|
+
import subprocess as _sp
|
|
207
|
+
_rc = _sp.call([sys.executable, '-m', 'pip', 'install', '--no-input',
|
|
208
|
+
'--progress-bar', 'off', '-i',
|
|
209
|
+
'https://pypi.tuna.tsinghua.edu.cn/simple',
|
|
210
|
+
'--trusted-host', 'pypi.tuna.tsinghua.edu.cn',
|
|
211
|
+
'-r', req])
|
|
212
|
+
result = {'ok': _rc == 0, 'source': '清华' if _rc == 0 else None,
|
|
213
|
+
'missing': [], 'hint': None}
|
|
191
214
|
if result['ok']:
|
|
192
|
-
src = result
|
|
215
|
+
src = result.get('source')
|
|
193
216
|
say(FIX, '依赖安装成功' + ('' if src == 'default' else ' (镜像源: %s)' % src))
|
|
194
217
|
# 装完后重新验证 (旧版装完不复查, 会把装失败误报为已装)
|
|
195
218
|
missing_core = []
|
|
@@ -200,7 +223,8 @@ def check_dependencies(fix=False):
|
|
|
200
223
|
except ImportError:
|
|
201
224
|
missing_core.append(pkg)
|
|
202
225
|
else:
|
|
203
|
-
print(' [MISS]
|
|
226
|
+
print(' [MISS] 依赖仍未装齐, 手动: pip install -r requirements.txt '
|
|
227
|
+
'-i https://pypi.tuna.tsinghua.edu.cn/simple')
|
|
204
228
|
# 重新验证, 看哪些真的还缺
|
|
205
229
|
missing_core = []
|
|
206
230
|
for mod, pkg, usage, is_core in PIP_DEPS:
|
|
@@ -246,7 +270,7 @@ def check_developer(fix, name=None, role=None):
|
|
|
246
270
|
return None
|
|
247
271
|
if name and (not current or current != name):
|
|
248
272
|
if fix:
|
|
249
|
-
from
|
|
273
|
+
from foundation.identity.developer import init_developer
|
|
250
274
|
if init_developer(name, role):
|
|
251
275
|
actions.append('注册/切换开发者: ' + name)
|
|
252
276
|
return name
|
|
@@ -430,11 +454,11 @@ def print_degraded_status():
|
|
|
430
454
|
print('=' * 56)
|
|
431
455
|
print(' 以下功能需要源码, 当前不可用:')
|
|
432
456
|
print(' /wl-search 搜代码 (无源码 = 搜不到)')
|
|
433
|
-
print(' /wl-prd
|
|
457
|
+
print(' /wl-prd 完整 PRD 的字段/API 锚定 (会跳过, 原型可用)')
|
|
434
458
|
print(' 知识图谱 MCP search_code/api 等工具 (启动但返回空)')
|
|
435
459
|
print()
|
|
436
460
|
print(' 以下功能不依赖源码, 当前可用:')
|
|
437
|
-
print(' /wl-prd
|
|
461
|
+
print(' /wl-prd 零星需求模式 (纯文案/小改动)')
|
|
438
462
|
print(' /wl-task 任务管理')
|
|
439
463
|
print(' /wl-report 日报周报')
|
|
440
464
|
print(' /wl-commit 代码提交 (提交的是工作流本身的改动)')
|
|
@@ -730,7 +754,7 @@ def check_lanhu():
|
|
|
730
754
|
mcp_file = os.path.join(home, '.qoderwork', 'mcp.json')
|
|
731
755
|
if not os.path.isfile(mcp_file):
|
|
732
756
|
say(WARN, '未配置蓝湖 MCP (团队不用蓝湖可忽略)')
|
|
733
|
-
print(' 用的话跑: python .qoder/scripts/setup
|
|
757
|
+
print(' 用的话跑: python .qoder/scripts/deployment/setup/setup_lanhu.py')
|
|
734
758
|
return
|
|
735
759
|
|
|
736
760
|
try:
|
|
@@ -742,7 +766,7 @@ def check_lanhu():
|
|
|
742
766
|
|
|
743
767
|
if 'lanhu' not in servers:
|
|
744
768
|
say(WARN, '未配置蓝湖 MCP (团队不用蓝湖可忽略)')
|
|
745
|
-
print(' 用的话跑: python .qoder/scripts/setup
|
|
769
|
+
print(' 用的话跑: python .qoder/scripts/deployment/setup/setup_lanhu.py')
|
|
746
770
|
return
|
|
747
771
|
|
|
748
772
|
entry = servers['lanhu']
|
|
@@ -818,7 +842,7 @@ def main():
|
|
|
818
842
|
print('=' * 56)
|
|
819
843
|
return 1
|
|
820
844
|
if _has_source_code():
|
|
821
|
-
print('环境健康, 可以开始工作: /wl-prd
|
|
845
|
+
print('环境健康, 可以开始工作: /wl-prd <需求描述>')
|
|
822
846
|
else:
|
|
823
847
|
print('工作流核心已就绪 (见上方降级说明补源码)。')
|
|
824
848
|
print('=' * 56)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
3
3
|
import os as _o, sys as _s
|
|
4
|
-
|
|
4
|
+
_f = _o.path.abspath(__file__)
|
|
5
|
+
for _ in range(10):
|
|
6
|
+
_f = _o.path.dirname(_f)
|
|
7
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
8
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
9
|
+
break
|
|
5
10
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
6
11
|
from bootstrap import setup; setup()
|
|
12
|
+
from foundation.core.paths import get_repo_root
|
|
7
13
|
|
|
8
14
|
"""
|
|
9
15
|
install_qoderwork.py - 把 .qoder/skills/ 安装到 QoderWork 桌面端可识别的位置
|
|
@@ -46,7 +52,7 @@ if sys.platform == "win32":
|
|
|
46
52
|
|
|
47
53
|
# 路径自检:项目根 = 本文件上四级 (v3.0: setup/ -> scripts/ -> .qoder/ -> repo)
|
|
48
54
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
49
|
-
PROJECT_ROOT =
|
|
55
|
+
PROJECT_ROOT = get_repo_root()
|
|
50
56
|
SOURCE_SKILLS_DIR = PROJECT_ROOT / ".qoder" / "skills"
|
|
51
57
|
SOURCE_COMMANDS_DIR = PROJECT_ROOT / ".qoder" / "commands"
|
|
52
58
|
|
|
@@ -416,10 +422,12 @@ def rewrite_mcp_json_for_launcher():
|
|
|
416
422
|
# 绝对路径每次 install 时探测, 换机器重跑 update 自动刷新。
|
|
417
423
|
# 依赖查找: 先找装了 duckdb 的 python (find_python_with_core_deps),
|
|
418
424
|
# 找不到回退 detect_python_command。
|
|
419
|
-
try
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
425
|
+
# ⚠ find_python_with_core_deps 返回 None (不抛异常) 时, 旧代码因 try/except
|
|
426
|
+
# 捕不到 → py_cmd 留 None → mcp.json 写 "command": null → QoderWork 起 MCP
|
|
427
|
+
# 失败变黄。这里显式 None 判断 + 多级回退, 绝不写 null。
|
|
428
|
+
py_cmd = find_python_with_core_deps()
|
|
429
|
+
if not py_cmd:
|
|
430
|
+
py_cmd = detect_python_command() or sys.executable or "python"
|
|
423
431
|
launcher = str(_HOME / ".qoderwork" / "mcp_launcher.py")
|
|
424
432
|
# MCP 名 → launcher 子命令
|
|
425
433
|
name_map = {
|
|
@@ -496,7 +504,7 @@ def main():
|
|
|
496
504
|
print("MCP 配置刷新 (--mcp-only)")
|
|
497
505
|
print("=" * 56)
|
|
498
506
|
# 1. 复制 launcher
|
|
499
|
-
launcher_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "mcp" / "mcp_launcher.py" # v3.0: mcp子包
|
|
507
|
+
launcher_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "protocol" / "mcp" / "mcp_launcher.py" # v3.0: protocol/mcp子包
|
|
500
508
|
launcher_dst = _HOME / ".qoderwork" / "mcp_launcher.py"
|
|
501
509
|
try:
|
|
502
510
|
launcher_dst.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -669,7 +677,7 @@ def main():
|
|
|
669
677
|
# QoderWork 桌面端工作目录是临时会话目录, 不是仓库根, 相对路径失效。
|
|
670
678
|
# repo_root.py 从 mcp.json 反推仓库根, 命令文件靠它定位脚本/模板。
|
|
671
679
|
if action in ("install", "check"):
|
|
672
|
-
repo_root_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "setup" / "repo_root.py" # v3.0: setup子包
|
|
680
|
+
repo_root_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "deployment" / "setup" / "repo_root.py" # v3.0: deployment/setup子包
|
|
673
681
|
repo_root_dst = _HOME / ".qoderwork" / "repo_root.py"
|
|
674
682
|
if repo_root_src.is_file():
|
|
675
683
|
if action == "check":
|
|
@@ -694,7 +702,7 @@ def main():
|
|
|
694
702
|
# .repo-root 锚点文件让 launcher 能定位仓库根 (不依赖 mcp.json 里的路径)。
|
|
695
703
|
if action in ("install", "check"):
|
|
696
704
|
print(f"\n--- mcp_launcher.py (统一 MCP 启动器) ---")
|
|
697
|
-
launcher_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "mcp" / "mcp_launcher.py" # v3.0: mcp子包
|
|
705
|
+
launcher_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "protocol" / "mcp" / "mcp_launcher.py" # v3.0: protocol/mcp子包
|
|
698
706
|
launcher_dst = _HOME / ".qoderwork" / "mcp_launcher.py"
|
|
699
707
|
anchor_dst = _HOME / ".qoderwork" / ".repo-root"
|
|
700
708
|
if action == "check":
|
|
@@ -765,7 +773,7 @@ def main():
|
|
|
765
773
|
elif lh_status == "would-add":
|
|
766
774
|
print(f" [MISS] 未注册蓝湖 MCP, 安装时会写入 {QODERWORK_MCP_FILE}")
|
|
767
775
|
# STDIO 模式由 QoderWork 自动管, 不查端口; 只确认 wrapper + 源码就绪
|
|
768
|
-
wrapper = PROJECT_ROOT / ".qoder" / "scripts" / "lanhu_stdio_wrapper.py"
|
|
776
|
+
wrapper = PROJECT_ROOT / ".qoder" / "scripts" / "protocol" / "mcp" / "lanhu_stdio_wrapper.py"
|
|
769
777
|
lanhu_dir = PROJECT_ROOT / "external" / "lanhu-mcp"
|
|
770
778
|
if wrapper.is_file():
|
|
771
779
|
print(f" wrapper 就绪: {wrapper.name} (按角色读 cookie)")
|
|
@@ -777,8 +785,8 @@ def main():
|
|
|
777
785
|
if action == "install" and counts["err"] == 0:
|
|
778
786
|
print("\n✓ 安装完成。重启 QoderWork(或新建对话)后技能生效。")
|
|
779
787
|
print(" 在 QoderWork 里直接用自然语言即可,例如:")
|
|
780
|
-
print(' "写个保险异常筛选的 PRD" -> /wl-prd
|
|
781
|
-
print(' "列表加个导出按钮" -> /wl-prd
|
|
788
|
+
print(' "写个保险异常筛选的 PRD" -> /wl-prd(正经需求, 完整档)')
|
|
789
|
+
print(' "列表加个导出按钮" -> /wl-prd(小改动, 自动走快速档)')
|
|
782
790
|
print(' "查一下考勤代码在哪" -> /wl-search')
|
|
783
791
|
elif action == "install" and counts["err"] > 0:
|
|
784
792
|
print(f"\n⚠ 有 {counts['err']} 个安装失败,见上方 [ERR] 行。")
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
4
4
|
import os as _o, sys as _s
|
|
5
|
-
|
|
5
|
+
_f = _o.path.abspath(__file__)
|
|
6
|
+
for _ in range(10):
|
|
7
|
+
_f = _o.path.dirname(_f)
|
|
8
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
9
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
10
|
+
break
|
|
6
11
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
7
12
|
from bootstrap import setup; setup()
|
|
13
|
+
from foundation.core.paths import get_repo_root
|
|
8
14
|
|
|
9
15
|
"""
|
|
10
16
|
platform_doctor.py - 跨平台环境自诊断 (任何 OS 跑, 输出环境真相)
|
|
@@ -49,7 +55,7 @@ for candidate in [HERE.parent.parent, HERE.parent, HERE]:
|
|
|
49
55
|
BASE = candidate
|
|
50
56
|
break
|
|
51
57
|
if BASE is None:
|
|
52
|
-
BASE =
|
|
58
|
+
BASE = get_repo_root()
|
|
53
59
|
|
|
54
60
|
report = {'platform': {}, 'tools': {}, 'engine': {}, 'mcp': {},
|
|
55
61
|
'role': {}, 'issues': [], 'verdict': 'UNKNOWN'}
|
|
@@ -1,112 +1,113 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
#
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from bootstrap import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
python ~/.qoderwork/repo_root.py
|
|
20
|
-
python ~/.qoderwork/repo_root.py --
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
python
|
|
24
|
-
""
|
|
25
|
-
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
('
|
|
97
|
-
('
|
|
98
|
-
('
|
|
99
|
-
('
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# repo_root.py — 自适应定位 QODER 流水线仓库根(QoderWork 桌面端专用)。
|
|
3
|
+
#
|
|
4
|
+
# ⚠️ 本文件被 install_qoderwork.py 复制到 ~/.qoderwork/repo_root.py, 在那里它
|
|
5
|
+
# 独立运行 (不依赖仓库内的任何模块)。所以这里**零 import 依赖**——
|
|
6
|
+
# 不能 from bootstrap import (那是仓库内的模块, 定位器不能依赖被定位的东西)。
|
|
7
|
+
# bootstrap 的 sys.path 自举作用对其他被复制脚本有效, 对本定位器是死循环。
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
repo_root.py — 自适应定位 QODER 流水线仓库根(QoderWork 桌面端专用)。
|
|
11
|
+
|
|
12
|
+
为什么需要它:
|
|
13
|
+
QoderWork 桌面端的工作目录是临时会话目录(workspace/xxx), 不是仓库根。
|
|
14
|
+
命令文件里的相对路径 .qoder/scripts/xxx.py 全部失效。
|
|
15
|
+
本脚本从 ~/.qoderwork/mcp.json 的 kg_mcp_server.py 绝对路径反推仓库根,
|
|
16
|
+
自适应(换机器重装 install 后 mcp.json 会更新, 无需硬编码)。
|
|
17
|
+
|
|
18
|
+
用法(命令文件里):
|
|
19
|
+
python ~/.qoderwork/repo_root.py # 打印仓库根绝对路径
|
|
20
|
+
python ~/.qoderwork/repo_root.py --script kg.py # 打印仓库内脚本的绝对路径
|
|
21
|
+
python ~/.qoderwork/repo_root.py --template prd-quick-template.md
|
|
22
|
+
|
|
23
|
+
R=$(python ~/.qoderwork/repo_root.py) # 在 Bash 里捕获仓库根
|
|
24
|
+
python "$R/.qoder/scripts/kg.py" context 保险 --platform web
|
|
25
|
+
"""
|
|
26
|
+
import json
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def find_repo_root():
|
|
32
|
+
"""定位 QODER 仓库根。优先级:
|
|
33
|
+
1. ~/.qoderwork/.repo-root 文件 (install 时写, 主路径)
|
|
34
|
+
2. 环境变量 QODER_REPO
|
|
35
|
+
3. 向上找 .qoder/scripts/ (cwd 在仓库内)
|
|
36
|
+
4. 本脚本所在位置 (开发态)
|
|
37
|
+
失败返回 None。
|
|
38
|
+
"""
|
|
39
|
+
home = os.path.expanduser('~')
|
|
40
|
+
|
|
41
|
+
# 方法1: .repo-root 锚点文件 (install_qoderwork 写的, 最可靠)
|
|
42
|
+
anchor = os.path.join(home, '.qoderwork', '.repo-root')
|
|
43
|
+
if os.path.isfile(anchor):
|
|
44
|
+
try:
|
|
45
|
+
line = open(anchor, encoding='utf-8').read().strip()
|
|
46
|
+
if line and os.path.isdir(os.path.join(line, '.qoder', 'scripts')):
|
|
47
|
+
return line
|
|
48
|
+
except OSError:
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
# 方法2: 环境变量
|
|
52
|
+
env_repo = os.environ.get('QODER_REPO')
|
|
53
|
+
if env_repo and os.path.isdir(os.path.join(env_repo, '.qoder', 'scripts')):
|
|
54
|
+
return env_repo
|
|
55
|
+
|
|
56
|
+
# 方法3: 向上找 .qoder 目录(适用于工作目录在仓库内的情况, 如 IDE)
|
|
57
|
+
here = os.path.abspath(os.getcwd())
|
|
58
|
+
for _ in range(8):
|
|
59
|
+
if os.path.isdir(os.path.join(here, '.qoder', 'scripts')):
|
|
60
|
+
return here
|
|
61
|
+
parent = os.path.dirname(here)
|
|
62
|
+
if parent == here:
|
|
63
|
+
break
|
|
64
|
+
here = parent
|
|
65
|
+
|
|
66
|
+
# 方法4: 本脚本所在位置(若它被放到仓库 .qoder/scripts/ 下)
|
|
67
|
+
try:
|
|
68
|
+
s = os.path.abspath(__file__)
|
|
69
|
+
root = os.path.dirname(os.path.dirname(os.path.dirname(s)))
|
|
70
|
+
if os.path.isdir(os.path.join(root, '.qoder', 'scripts')):
|
|
71
|
+
return root
|
|
72
|
+
except Exception:
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main():
|
|
79
|
+
root = find_repo_root()
|
|
80
|
+
if not root:
|
|
81
|
+
print('ERROR: 无法定位 QODER 仓库根。请确认 ~/.qoderwork/mcp.json 存在且指向有效的 kg_mcp_server.py', file=sys.stderr)
|
|
82
|
+
return 1
|
|
83
|
+
|
|
84
|
+
# 子路径模式: --script / --template
|
|
85
|
+
args = sys.argv[1:]
|
|
86
|
+
if args and args[0] in ('--script', '--scripts'):
|
|
87
|
+
# 打印仓库内 .qoder/scripts/<name> 的绝对路径
|
|
88
|
+
name = args[1] if len(args) > 1 else ''
|
|
89
|
+
print(os.path.join(root, '.qoder', 'scripts', name))
|
|
90
|
+
elif args and args[0] in ('--template', '--templates'):
|
|
91
|
+
name = args[1] if len(args) > 1 else ''
|
|
92
|
+
print(os.path.join(root, '.qoder', 'templates', name))
|
|
93
|
+
elif args and args[0] == '--test':
|
|
94
|
+
# 自检: 验证关键文件存在
|
|
95
|
+
checks = [
|
|
96
|
+
('kg.py', '.qoder/scripts/domain/kg/kg.py'),
|
|
97
|
+
('eval_prd.py', '.qoder/scripts/validation/metrics/eval_prd.py'),
|
|
98
|
+
('quick模板', '.qoder/templates/prd-quick-template.md'),
|
|
99
|
+
('full模板', '.qoder/templates/prd-full-template.md'),
|
|
100
|
+
('kg.duckdb', 'data/index/kg.duckdb'),
|
|
101
|
+
]
|
|
102
|
+
print('仓库根: %s' % root)
|
|
103
|
+
for label, rel in checks:
|
|
104
|
+
ok = os.path.isfile(os.path.join(root, rel))
|
|
105
|
+
print(' %s %s' % ('✅' if ok else '❌', label))
|
|
106
|
+
else:
|
|
107
|
+
# 默认: 只打印仓库根
|
|
108
|
+
print(root)
|
|
109
|
+
return 0
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == '__main__':
|
|
113
|
+
sys.exit(main())
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
4
4
|
import os as _o, sys as _s
|
|
5
|
-
|
|
5
|
+
_f = _o.path.abspath(__file__)
|
|
6
|
+
for _ in range(10):
|
|
7
|
+
_f = _o.path.dirname(_f)
|
|
8
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
9
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
10
|
+
break
|
|
6
11
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
7
12
|
from bootstrap import setup; setup()
|
|
13
|
+
from foundation.core.paths import get_repo_root
|
|
8
14
|
|
|
9
15
|
"""
|
|
10
16
|
setup.py - 一键就绪 (小而美)
|
|
@@ -41,7 +47,7 @@ except (AttributeError, TypeError, OSError):
|
|
|
41
47
|
pass
|
|
42
48
|
|
|
43
49
|
THIS_DIR = Path(__file__).resolve().parent
|
|
44
|
-
BASE =
|
|
50
|
+
BASE = get_repo_root()
|
|
45
51
|
|
|
46
52
|
|
|
47
53
|
# ============================================================
|
|
@@ -641,10 +647,12 @@ def offer_cron(skip=False):
|
|
|
641
647
|
return
|
|
642
648
|
|
|
643
649
|
if ask('注册周五 18:00 自动更新知识图谱? (团队只需一台机器注册)', 'y'):
|
|
650
|
+
# cron 脚本在 scripts/ 根 (THIS_DIR = scripts/deployment/setup/, 上两级)
|
|
651
|
+
cron_dir = THIS_DIR.parent.parent
|
|
644
652
|
if sys.platform == 'win32':
|
|
645
|
-
r = run(['cmd', '/c', str(
|
|
653
|
+
r = run(['cmd', '/c', str(cron_dir / 'setup_weekly_cron.bat')], cwd=str(BASE))
|
|
646
654
|
else:
|
|
647
|
-
r = run(['bash', str(
|
|
655
|
+
r = run(['bash', str(cron_dir / 'setup_weekly_cron.sh')], cwd=str(BASE))
|
|
648
656
|
if r.returncode == 0:
|
|
649
657
|
ok('cron 已注册 (周五 18:00)')
|
|
650
658
|
else:
|
|
@@ -764,13 +772,25 @@ def print_ready(name, role):
|
|
|
764
772
|
if projects:
|
|
765
773
|
ok(f'源码仓库: {len(projects)} 个项目 ({", ".join(projects[:3])})')
|
|
766
774
|
|
|
767
|
-
#
|
|
768
|
-
|
|
769
|
-
if
|
|
775
|
+
# 知识图谱 (DuckDB 是唯一事实源; 旧 code-keyword.json 已废弃)
|
|
776
|
+
kg = BASE / 'data' / 'index' / 'kg.duckdb'
|
|
777
|
+
if kg.is_file():
|
|
770
778
|
try:
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
779
|
+
size_kb = kg.stat().st_size // 1024
|
|
780
|
+
# 尝试读关键词行数作为"有内容"的证据 (读不到只报大小)
|
|
781
|
+
kw_n = None
|
|
782
|
+
try:
|
|
783
|
+
import duckdb as _ddb
|
|
784
|
+
con = _ddb.connect(str(kg), read_only=True)
|
|
785
|
+
row = con.execute('SELECT COUNT(*) FROM keywords').fetchone()
|
|
786
|
+
con.close()
|
|
787
|
+
kw_n = row[0] if row else None
|
|
788
|
+
except Exception:
|
|
789
|
+
pass
|
|
790
|
+
if kw_n:
|
|
791
|
+
ok(f'知识图谱: {kw_n} keywords (kg.duckdb {size_kb} KB)')
|
|
792
|
+
else:
|
|
793
|
+
ok(f'知识图谱: kg.duckdb {size_kb} KB')
|
|
774
794
|
except Exception:
|
|
775
795
|
pass
|
|
776
796
|
|
|
@@ -793,7 +813,7 @@ def print_ready(name, role):
|
|
|
793
813
|
|
|
794
814
|
print()
|
|
795
815
|
print(' 现在可以开始了:')
|
|
796
|
-
print(' /wl-prd
|
|
816
|
+
print(' /wl-prd 写需求 /wl-search 查代码 /wl-task 建任务')
|
|
797
817
|
print(' /wl-status 看进度 /wl-report 出日报 /wl-commit 提交')
|
|
798
818
|
print()
|
|
799
819
|
print(' 或直接用自然语言:')
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
4
4
|
import os as _o, sys as _s
|
|
5
|
-
|
|
5
|
+
_f = _o.path.abspath(__file__)
|
|
6
|
+
for _ in range(10):
|
|
7
|
+
_f = _o.path.dirname(_f)
|
|
8
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
9
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
10
|
+
break
|
|
6
11
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
7
12
|
from bootstrap import setup; setup()
|
|
13
|
+
from foundation.core.paths import get_repo_root
|
|
8
14
|
|
|
9
15
|
"""
|
|
10
16
|
setup_lanhu.py - 蓝湖 MCP 引导器 (幂等)
|
|
@@ -48,7 +54,7 @@ except (AttributeError, TypeError, OSError):
|
|
|
48
54
|
pass
|
|
49
55
|
|
|
50
56
|
THIS_DIR = Path(__file__).resolve().parent
|
|
51
|
-
BASE =
|
|
57
|
+
BASE = get_repo_root()
|
|
52
58
|
|
|
53
59
|
LANHU_REPO = 'https://github.com/dsphper/lanhu-mcp.git'
|
|
54
60
|
EXTERNAL_DIR = BASE / 'external'
|
|
@@ -71,7 +77,7 @@ def _current_developer():
|
|
|
71
77
|
"""读 .qoder/.developer 确定当前用户。没有返回 None。"""
|
|
72
78
|
try:
|
|
73
79
|
sys.path.insert(0, str(THIS_DIR))
|
|
74
|
-
from
|
|
80
|
+
from foundation.core.paths import get_developer
|
|
75
81
|
return get_developer(BASE)
|
|
76
82
|
except Exception:
|
|
77
83
|
return None
|
|
@@ -85,14 +91,14 @@ def lanhu_secrets_dir(developer=None):
|
|
|
85
91
|
dev = developer or _current_developer() or 'default'
|
|
86
92
|
try:
|
|
87
93
|
sys.path.insert(0, str(BASE / '.qoder' / 'scripts'))
|
|
88
|
-
from
|
|
94
|
+
from foundation.core.paths import get_secrets_dir
|
|
89
95
|
return Path(get_secrets_dir(dev))
|
|
90
96
|
except Exception:
|
|
91
97
|
return BASE / 'workspace' / 'members' / dev / '.secrets'
|
|
92
98
|
|
|
93
99
|
|
|
94
100
|
def lanhu_env_file(developer=None):
|
|
95
|
-
"""当前用户的蓝湖 cookie 文件: workspace/members/{dev}/.secrets/lanhu.env"""
|
|
101
|
+
"""当前用户的蓝湖 cookie 文件: workspace/members/{dev}/.private/secrets/lanhu.env"""
|
|
96
102
|
return lanhu_secrets_dir(developer) / 'lanhu.env'
|
|
97
103
|
|
|
98
104
|
|
|
@@ -349,7 +355,7 @@ def ensure_deps(dry=False, _rebuilt=False):
|
|
|
349
355
|
|
|
350
356
|
|
|
351
357
|
# ============================================================
|
|
352
|
-
# Step 3: cookie (按开发者隔离, workspace/members/{dev}/.secrets/lanhu.env)
|
|
358
|
+
# Step 3: cookie (按开发者隔离, workspace/members/{dev}/.private/secrets/lanhu.env)
|
|
353
359
|
# ============================================================
|
|
354
360
|
# 为什么不放 external/lanhu-mcp/.env:
|
|
355
361
|
# 1. cookie 是个人登录凭证, 不该进仓库代码区 (即使 gitignore)
|
|
@@ -378,7 +384,7 @@ def _read_env_cookie(developer=None):
|
|
|
378
384
|
def _write_env_cookie(cookie, developer=None):
|
|
379
385
|
"""把 LANHU_COOKIE 写进当前用户的 lanhu.env (保留其他行)。
|
|
380
386
|
|
|
381
|
-
文件: workspace/members/{dev}/.secrets/lanhu.env (已 gitignore)
|
|
387
|
+
文件: workspace/members/{dev}/.private/secrets/lanhu.env (已 gitignore)
|
|
382
388
|
"""
|
|
383
389
|
env_file = lanhu_env_file(developer)
|
|
384
390
|
try:
|
|
File without changes
|
|
File without changes
|