@hupan56/wlkj 2.7.12 → 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 -1107
- package/package.json +29 -29
- package/templates/qoder/agents/insight-planning.md +1 -1
- package/templates/qoder/agents/insight-research.md +28 -15
- package/templates/qoder/commands/optional/wl-insight.md +161 -161
- 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 +6 -6
- 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 +43 -0
- 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 +43 -17
- package/templates/qoder/config.yaml +52 -14
- package/templates/qoder/hooks/post-tool-use.py +181 -0
- package/templates/qoder/hooks/session-start.py +94 -23
- 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 +85 -49
- package/templates/qoder/scripts/README.md +102 -0
- 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/deployment/setup/__init__.py +11 -0
- package/templates/qoder/scripts/deployment/setup/carriers.py +669 -0
- package/templates/qoder/scripts/deployment/setup/carriers_verify.py +148 -0
- package/templates/qoder/scripts/{init_doctor.py → deployment/setup/init_doctor.py} +100 -39
- package/templates/qoder/scripts/{install_qoderwork.py → deployment/setup/install_qoderwork.py} +48 -30
- package/templates/qoder/scripts/{platform_doctor.py → deployment/setup/platform_doctor.py} +271 -259
- package/templates/qoder/scripts/{repo_root.py → deployment/setup/repo_root.py} +9 -2
- package/templates/qoder/scripts/{setup.py → deployment/setup/setup.py} +143 -14
- package/templates/qoder/scripts/{setup_lanhu.py → deployment/setup/setup_lanhu.py} +979 -963
- package/templates/qoder/scripts/domain/design/__init__.py +0 -0
- package/templates/qoder/scripts/{fill_prototype.py → domain/design/fill_prototype.py} +17 -5
- package/templates/qoder/scripts/{gen_design_doc.py → domain/design/gen_design_doc.py} +406 -394
- package/templates/qoder/scripts/domain/kg/__init__.py +11 -0
- package/templates/qoder/scripts/domain/kg/build/__init__.py +0 -0
- package/templates/qoder/scripts/domain/kg/build/build_entity_registry.py +201 -0
- package/templates/qoder/scripts/domain/kg/build/build_relations.py +132 -0
- package/templates/qoder/scripts/{build_style_index.py → domain/kg/build/build_style_index.py} +50 -15
- package/templates/qoder/scripts/domain/kg/build/build_workflows.py +149 -0
- package/templates/qoder/scripts/{kg_build.py → domain/kg/build/kg_build.py} +685 -612
- package/templates/qoder/scripts/{kg_build_db.py → domain/kg/build/kg_build_db.py} +338 -327
- package/templates/qoder/scripts/{kg_incremental.py → domain/kg/build/kg_incremental.py} +425 -393
- package/templates/qoder/scripts/{learn_aggregate.py → domain/kg/build/learn_aggregate.py} +212 -201
- 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/domain/kg/extract/test_extract.py +115 -0
- 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_link_db.py → domain/kg/graph/kg_link_db.py} +235 -224
- package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +683 -0
- package/templates/qoder/scripts/{kg.py → domain/kg/kg.py} +871 -708
- package/templates/qoder/scripts/domain/kg/kg_capabilities.py +182 -0
- package/templates/qoder/scripts/domain/kg/search/__init__.py +0 -0
- package/templates/qoder/scripts/{context_pack.py → domain/kg/search/context_pack.py} +45 -17
- package/templates/qoder/scripts/{enrich_prompt.py → domain/kg/search/enrich_prompt.py} +238 -226
- package/templates/qoder/scripts/domain/kg/search/prefetch.py +384 -0
- package/templates/qoder/scripts/{common → domain/kg/search}/search_engine.py +207 -205
- package/templates/qoder/scripts/{search_index.py → domain/kg/search/search_index.py} +210 -88
- 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_duckdb.py → domain/kg/storage/kg_duckdb.py} +70 -45
- package/templates/qoder/scripts/domain/learning/__init__.py +0 -0
- package/templates/qoder/scripts/{learn.py → domain/learning/learn.py} +157 -146
- package/templates/qoder/scripts/domain/report/__init__.py +11 -0
- package/templates/qoder/scripts/{add_session.py → domain/report/add_session.py} +256 -244
- package/templates/qoder/scripts/{export.py → domain/report/export.py} +72 -4
- package/templates/qoder/scripts/{report.py → domain/report/report.py} +292 -281
- package/templates/qoder/scripts/domain/report/report_snapshot.py +261 -0
- package/templates/qoder/scripts/domain/report/role.py +39 -0
- package/templates/qoder/scripts/{status.py → domain/report/status.py} +737 -628
- 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/{archive_prd.py → domain/requirement/archive_prd.py} +389 -377
- package/templates/qoder/scripts/domain/requirement/req.py +228 -0
- package/templates/qoder/scripts/domain/task/__init__.py +11 -0
- package/templates/qoder/scripts/{git_sync.py → domain/task/git_sync.py} +90 -50
- package/templates/qoder/scripts/{syncgate.py → domain/task/syncgate.py} +18 -7
- package/templates/qoder/scripts/domain/task/task.py +229 -0
- package/templates/qoder/scripts/domain/task/task_lifecycle.py +606 -0
- package/templates/qoder/scripts/domain/task/task_query.py +162 -0
- package/templates/qoder/scripts/domain/task/task_relations.py +425 -0
- package/templates/qoder/scripts/{team_sync.py → domain/task/team_sync.py} +101 -23
- package/templates/qoder/scripts/domain/task/zentao_sync.py +370 -0
- package/templates/qoder/scripts/foundation/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/bootstrap.py +145 -0
- package/templates/qoder/scripts/foundation/core/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/core/cmd_registry.py +112 -0
- package/templates/qoder/scripts/foundation/core/config.py +187 -0
- package/templates/qoder/scripts/{common → foundation/core}/paths.py +706 -400
- package/templates/qoder/scripts/foundation/data/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/data/contract.py +317 -0
- package/templates/qoder/scripts/{common → foundation/data}/events.py +2 -2
- package/templates/qoder/scripts/foundation/data/result.py +223 -0
- package/templates/qoder/scripts/{common → foundation/data}/task_utils.py +427 -392
- package/templates/qoder/scripts/foundation/identity/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/identity/check_publish.py +103 -0
- package/templates/qoder/scripts/{common → foundation/identity}/developer.py +239 -238
- package/templates/qoder/scripts/foundation/identity/guard.py +159 -0
- package/templates/qoder/scripts/{common → foundation/identity}/identity.py +132 -9
- package/templates/qoder/scripts/foundation/identity/roles.py +60 -0
- 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 +11 -10
- 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/foundation/protocol/mcp_base.py +268 -0
- 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/{lanhu_stdio_wrapper.py → protocol/mcp/lanhu_stdio_wrapper.py} +131 -119
- package/templates/qoder/scripts/protocol/mcp/mcp_doctor.py +548 -0
- package/templates/qoder/scripts/protocol/mcp/mcp_launcher.py +600 -0
- package/templates/qoder/scripts/protocol/mcp/mysql_mcp_server.py +461 -0
- 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/{eval_prd.py → validation/metrics/eval_prd.py} +84 -15
- 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/{autotest.py → validation/test/autotest.py} +1234 -1751
- package/templates/qoder/scripts/validation/test/autotest_auth.py +109 -0
- package/templates/qoder/scripts/{autotest_batch.py → validation/test/autotest_batch.py} +255 -224
- package/templates/qoder/scripts/validation/test/autotest_data.py +680 -0
- package/templates/qoder/scripts/validation/test/autotest_opencli.py +646 -0
- package/templates/qoder/scripts/{autotest_run.py → validation/test/autotest_run.py} +323 -297
- package/templates/qoder/scripts/validation/test/autotest_webaccess.py +571 -0
- package/templates/qoder/scripts/{benchmark.py → validation/test/benchmark.py} +17 -5
- package/templates/qoder/scripts/{kg_auto_login.py → validation/test/kg_auto_login.py} +208 -196
- package/templates/qoder/scripts/{kg_test_runner.py → validation/test/kg_test_runner.py} +13 -2
- package/templates/qoder/scripts/{page_probe.py → validation/test/page_probe.py} +470 -459
- package/templates/qoder/scripts/validation/test/smoke_all_commands.py +170 -0
- package/templates/qoder/settings.json +23 -2
- package/templates/qoder/skills/design-import/SKILL.md +235 -226
- package/templates/qoder/skills/design-review/SKILL.md +91 -82
- package/templates/qoder/skills/prd-generator/SKILL.md +38 -24
- package/templates/qoder/skills/prd-review/SKILL.md +8 -6
- package/templates/qoder/skills/prototype-generator/SKILL.md +296 -247
- package/templates/qoder/skills/spec-coder/SKILL.md +24 -15
- package/templates/qoder/skills/spec-generator/SKILL.md +24 -12
- package/templates/qoder/skills/test-generator/SKILL.md +9 -7
- package/templates/qoder/skills/wl-code/SKILL.md +25 -13
- package/templates/qoder/skills/wl-commit/SKILL.md +10 -9
- package/templates/qoder/skills/wl-design/SKILL.md +7 -5
- package/templates/qoder/skills/wl-init/SKILL.md +8 -8
- package/templates/qoder/skills/wl-insight/SKILL.md +25 -12
- package/templates/qoder/skills/wl-prd-full/SKILL.md +59 -8
- package/templates/qoder/skills/wl-prd-quick/SKILL.md +7 -7
- package/templates/qoder/skills/wl-prd-review/SKILL.md +18 -6
- package/templates/qoder/skills/wl-report/SKILL.md +27 -25
- package/templates/qoder/skills/wl-search/SKILL.md +151 -80
- package/templates/qoder/skills/wl-spec/SKILL.md +9 -7
- package/templates/qoder/skills/wl-status/SKILL.md +50 -18
- package/templates/qoder/skills/wl-task/SKILL.md +94 -12
- package/templates/qoder/skills/wl-test/SKILL.md +154 -45
- package/templates/qoder/templates/prd-full-template.md +7 -0
- package/templates/root/AGENTS.md +275 -237
- 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/hooks/inject-workflow-state.py +0 -169
- package/templates/qoder/scripts/__pycache__/check_mcp_launch.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/__pycache__/install_qoderwork.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/__pycache__/mcp_launcher.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/__pycache__/platform_doctor.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/check_carriers.py +0 -238
- package/templates/qoder/scripts/check_mcp.py +0 -298
- package/templates/qoder/scripts/check_mcp_launch.py +0 -183
- package/templates/qoder/scripts/check_qoderwork_consistency.py +0 -166
- package/templates/qoder/scripts/collect_prds.py +0 -31
- package/templates/qoder/scripts/common/mentions.py +0 -134
- package/templates/qoder/scripts/common/utf8.py +0 -38
- package/templates/qoder/scripts/extract_api_params.py +0 -246
- package/templates/qoder/scripts/extract_routes.py +0 -54
- package/templates/qoder/scripts/extract_routes_tree.py +0 -78
- package/templates/qoder/scripts/handoff.py +0 -22
- package/templates/qoder/scripts/init_developer.py +0 -76
- package/templates/qoder/scripts/kg_mcp_server.py +0 -801
- package/templates/qoder/scripts/kg_semantic.py +0 -150
- package/templates/qoder/scripts/mcp_launcher.py +0 -414
- package/templates/qoder/scripts/mysql_mcp_server.py +0 -396
- package/templates/qoder/scripts/parse_prds.py +0 -33
- package/templates/qoder/scripts/role.py +0 -51
- package/templates/qoder/scripts/sync_carriers.py +0 -259
- package/templates/qoder/scripts/task.py +0 -1261
- package/templates/qoder/scripts/workspace_init.py +0 -102
- package/templates/qoder/scripts/zentao_mcp_server.py +0 -424
- package/templates/qoder/skills/prompt-enrich/SKILL.md +0 -90
- /package/templates/qoder/scripts/{common → deployment}/__init__.py +0 -0
- /package/templates/qoder/{skills/prototype-generator/SKILL.md.zcode-79180-2af4721f-f9a6-412c-88db-c0af680d211b.tmp → scripts/domain/__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/{secure-ls.js → validation/test/secure-ls.js} +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
kg_capabilities.py - 知识图谱共享查询能力 (Strategy 模式, 消除 CLI↔MCP 重复)
|
|
4
|
+
|
|
5
|
+
v3.0 f3: kg.py (CLI) 和 kg_mcp_server.py (MCP) 有近字重复的查询逻辑
|
|
6
|
+
(workflow/hop/wiki/design_system 等)。本模块提取共享查询, 两边都调它,
|
|
7
|
+
消除重复, 且保证 CLI 和 MCP 行为完全一致。
|
|
8
|
+
|
|
9
|
+
核心 API (都接收已打开的 duckdb con, 由调用方管理连接):
|
|
10
|
+
workflow_query(con, q) -> str 业务流程链查询
|
|
11
|
+
# hop_query / wiki_query / design_system_query 后续添加
|
|
12
|
+
|
|
13
|
+
设计: 查询逻辑 (数据清洗/SQL/格式化) 在此单一真源;
|
|
14
|
+
kg.py 和 kg_mcp_server 只负责"开连接 + 调本模块 + 返回"。
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
__all__ = ["workflow_query", "hop_query", "wiki_query"]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def workflow_query(con, q):
|
|
21
|
+
"""workflows 表查询 + 脏数据清洗 + 中文兜底。
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
con: 已打开的 duckdb 连接 (read_only)
|
|
25
|
+
q: 模块名 (英文 assets/cost/hr 或中文触发兜底)
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
格式化的业务流程链文本
|
|
29
|
+
"""
|
|
30
|
+
q = (q or '').strip()
|
|
31
|
+
# 1) 精确 + 模糊匹配 workflows.module(英文)
|
|
32
|
+
hits = con.execute(
|
|
33
|
+
"SELECT DISTINCT module FROM workflows WHERE module = ? OR module LIKE '%' || ? || '%' ORDER BY module",
|
|
34
|
+
[q.lower(), q.lower()]
|
|
35
|
+
).fetchall()
|
|
36
|
+
if not hits:
|
|
37
|
+
# 2) 中文兜底: 查 entities.cn 返回英文候选
|
|
38
|
+
cn_hits = con.execute(
|
|
39
|
+
"SELECT canonical, cn FROM entities WHERE type IN ('FEATURE','MODULE') AND cn <> '' AND (cn LIKE '%' || ? OR cn LIKE '%' || ? || '%')",
|
|
40
|
+
[q, q]
|
|
41
|
+
).fetchall()
|
|
42
|
+
if cn_hits:
|
|
43
|
+
cands = ', '.join('%s(%s)' % (c[0], c[1]) for c in cn_hits[:8])
|
|
44
|
+
return "未在 workflows 表找到模块 '%s'。但 entities 表有相近中文名,可换这些英文模块名重试:\n %s" % (q, cands)
|
|
45
|
+
all_mods = [r[0] for r in con.execute("SELECT DISTINCT module FROM workflows ORDER BY module").fetchall()]
|
|
46
|
+
return "未找到模块 '%s'。现有模块: %s" % (q, ', '.join(all_mods))
|
|
47
|
+
|
|
48
|
+
out = []
|
|
49
|
+
for (mod,) in hits:
|
|
50
|
+
# 清洗: 过滤空端点和模板泄漏按钮
|
|
51
|
+
rows = con.execute("""
|
|
52
|
+
SELECT state, seq, button, endpoint FROM workflows
|
|
53
|
+
WHERE module = ?
|
|
54
|
+
AND endpoint <> 'None' AND endpoint <> ''
|
|
55
|
+
AND button NOT LIKE '{{%'
|
|
56
|
+
ORDER BY seq, state
|
|
57
|
+
""", [mod]).fetchall()
|
|
58
|
+
if not rows:
|
|
59
|
+
continue
|
|
60
|
+
out.append('=== %s (%d 步, 已清洗脏数据) ===' % (mod, len(rows)))
|
|
61
|
+
cur_seq = -1
|
|
62
|
+
for st, sq, btn, ep in rows:
|
|
63
|
+
if sq != cur_seq:
|
|
64
|
+
out.append(' [%d] %s' % (sq, st))
|
|
65
|
+
cur_seq = sq
|
|
66
|
+
out.append(' %-16s -> %s' % (btn, ep))
|
|
67
|
+
out.append('')
|
|
68
|
+
return '\n'.join(out).strip() or "模块 '%s' 清洗后无有效操作链" % q
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def hop_query(con, symbol, depth, multi_hop_fn=None):
|
|
72
|
+
"""多跳遍历: 别名解析(三级兜底) + 递归CTE + 按depth分组展示。
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
con: duckdb 连接
|
|
76
|
+
symbol: 起始符号 (中文/端点/函数名, 自动别名解析)
|
|
77
|
+
depth: 最大跳数 1-5
|
|
78
|
+
multi_hop_fn: kg_duckdb.multi_hop 函数 (避免硬依赖)
|
|
79
|
+
Returns:
|
|
80
|
+
格式化的多跳遍历文本
|
|
81
|
+
"""
|
|
82
|
+
# 1) 别名解析(三级兜底)
|
|
83
|
+
start_id = symbol
|
|
84
|
+
resolved = con.execute(
|
|
85
|
+
"SELECT entity_id FROM aliases WHERE alias = ?", [symbol.lower()]
|
|
86
|
+
).fetchone()
|
|
87
|
+
if resolved:
|
|
88
|
+
start_id = resolved[0]
|
|
89
|
+
else:
|
|
90
|
+
fuzzy = con.execute(
|
|
91
|
+
"SELECT id FROM entities WHERE id = ? OR id LIKE '%' || ? || '%' LIMIT 1",
|
|
92
|
+
[symbol, symbol]
|
|
93
|
+
).fetchone()
|
|
94
|
+
if fuzzy:
|
|
95
|
+
start_id = fuzzy[0]
|
|
96
|
+
else:
|
|
97
|
+
edge_hit = con.execute(
|
|
98
|
+
"SELECT from_id FROM edges WHERE from_id LIKE '%' || ? || '%' LIMIT 1",
|
|
99
|
+
[symbol]
|
|
100
|
+
).fetchone()
|
|
101
|
+
if edge_hit:
|
|
102
|
+
start_id = edge_hit[0]
|
|
103
|
+
|
|
104
|
+
# 2) 递归 CTE 遍历
|
|
105
|
+
if multi_hop_fn is None:
|
|
106
|
+
from domain.kg.storage import kg_duckdb as K
|
|
107
|
+
multi_hop_fn = K.multi_hop
|
|
108
|
+
try:
|
|
109
|
+
hops = multi_hop_fn(con, start_id, max_depth=depth)
|
|
110
|
+
except Exception as e:
|
|
111
|
+
return "遍历出错 (起点=%s): %s" % (start_id, str(e))
|
|
112
|
+
|
|
113
|
+
if not hops or (len(hops) == 1 and hops[0][1] == 0):
|
|
114
|
+
return "从 '%s' (解析为 %s) 出发无可达节点。可能该符号不在图谱中,或无出边。" % (symbol, start_id)
|
|
115
|
+
|
|
116
|
+
# 3) 按 depth 分组展示
|
|
117
|
+
from collections import defaultdict
|
|
118
|
+
by_depth = defaultdict(list)
|
|
119
|
+
for eid, d in hops:
|
|
120
|
+
by_depth[d].append(eid)
|
|
121
|
+
|
|
122
|
+
out = ['=== 多跳遍历: %s (解析为 %s) ===' % (symbol, start_id)]
|
|
123
|
+
out.append('可达 %d 个实体, 最大 %d 跳:' % (len(hops), max(by_depth.keys())))
|
|
124
|
+
out.append('')
|
|
125
|
+
for d in sorted(by_depth.keys()):
|
|
126
|
+
eids = by_depth[d]
|
|
127
|
+
out.append('[第 %d 跳] %d 个实体:' % (d, len(eids)))
|
|
128
|
+
shown = 0
|
|
129
|
+
for eid in eids:
|
|
130
|
+
if shown >= 12:
|
|
131
|
+
out.append(' ... 还有 %d 个' % (len(eids) - 12))
|
|
132
|
+
break
|
|
133
|
+
info = con.execute(
|
|
134
|
+
"SELECT type, canonical, cn FROM entities WHERE id = ?", [eid]
|
|
135
|
+
).fetchone()
|
|
136
|
+
if info:
|
|
137
|
+
t, c, cn = info
|
|
138
|
+
label = '%s / %s' % (c, cn) if cn and cn != c else c
|
|
139
|
+
out.append(' %-14s %-12s %s' % ('[%s]' % t, eid[:40], label))
|
|
140
|
+
else:
|
|
141
|
+
out.append(' %-14s %s' % ('[edge]', eid[:60]))
|
|
142
|
+
shown += 1
|
|
143
|
+
out.append('')
|
|
144
|
+
return '\n'.join(out).strip()
|
|
145
|
+
|
|
146
|
+
def wiki_query(kw):
|
|
147
|
+
"""Repo Wiki 搜索 + 格式化 (CLI/MCP 共用)。
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
kw: 搜索关键词
|
|
151
|
+
Returns:
|
|
152
|
+
格式化的 wiki 匹配结果文本
|
|
153
|
+
"""
|
|
154
|
+
import os
|
|
155
|
+
from foundation.core.paths import DATA_INDEX_DIR as _idx, PROJECT_ROOT as _base
|
|
156
|
+
wiki_path = os.path.join(str(_idx), 'wiki-index.json')
|
|
157
|
+
if not os.path.isfile(wiki_path):
|
|
158
|
+
return ("wiki-index.json 不存在。请手动构建(一次性):\n"
|
|
159
|
+
" python .qoder/scripts/domain/kg/search/search_index.py wiki")
|
|
160
|
+
try:
|
|
161
|
+
from repowiki import search_wiki
|
|
162
|
+
from foundation.integrations.terms import get_cn_map_with_auto
|
|
163
|
+
except ImportError as e:
|
|
164
|
+
return "Wiki 搜索模块缺失: %s" % str(e)
|
|
165
|
+
code_dir = os.path.join(_base, 'data', 'code')
|
|
166
|
+
try:
|
|
167
|
+
cn_map = get_cn_map_with_auto()
|
|
168
|
+
results = search_wiki(kw, str(_idx), code_dir, cn_map)
|
|
169
|
+
except Exception as e:
|
|
170
|
+
return "Wiki 搜索出错: %s" % str(e)
|
|
171
|
+
if not results:
|
|
172
|
+
return "No wiki pages match: %s" % kw
|
|
173
|
+
out = ['Wiki pages matching: %s (%d found)' % (kw, len(results)), '']
|
|
174
|
+
for i, r in enumerate(results, 1):
|
|
175
|
+
out.append(' %d. [%s] %s' % (i, r.get('project', '?'), r.get('title', '')))
|
|
176
|
+
deps = r.get('dependent_files') or []
|
|
177
|
+
if deps:
|
|
178
|
+
out.append(' 依赖: %s%s' % (', '.join(deps[:2]),
|
|
179
|
+
(' (共 %d 个文件)' % len(deps)) if len(deps) > 2 else ''))
|
|
180
|
+
if r.get('md_path'):
|
|
181
|
+
out.append(' 文档: %s' % r['md_path'])
|
|
182
|
+
return '\n'.join(out)
|
|
File without changes
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
|
+
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
4
|
+
import os as _o, sys as _s
|
|
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
|
|
11
|
+
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
12
|
+
from bootstrap import setup; setup()
|
|
13
|
+
from foundation.core.paths import get_repo_root
|
|
14
|
+
|
|
3
15
|
"""
|
|
4
16
|
QODER Context Pack - 一次调用返回写 PRD/原型所需的全部上下文
|
|
5
17
|
|
|
@@ -19,7 +31,7 @@ Usage:
|
|
|
19
31
|
"""
|
|
20
32
|
|
|
21
33
|
import os
|
|
22
|
-
from
|
|
34
|
+
from foundation.core.paths import BUILD_CACHE_DIR
|
|
23
35
|
import sys
|
|
24
36
|
import json
|
|
25
37
|
import time
|
|
@@ -34,9 +46,9 @@ except (AttributeError, TypeError, OSError, IOError):
|
|
|
34
46
|
pass
|
|
35
47
|
|
|
36
48
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
37
|
-
from
|
|
49
|
+
from foundation.integrations.terms import CN_MAP, BUSINESS_PATH_MAP, CN_TO_EN, get_platform_map, expand_chinese_query
|
|
38
50
|
|
|
39
|
-
BASE =
|
|
51
|
+
BASE = get_repo_root()
|
|
40
52
|
INDEX_DIR = os.path.join(BASE, 'data', 'index')
|
|
41
53
|
PLATFORM_MAP = get_platform_map()
|
|
42
54
|
MIN_FUZZY_LEN = 4
|
|
@@ -45,7 +57,7 @@ MIN_FUZZY_LEN = 4
|
|
|
45
57
|
def load(filename):
|
|
46
58
|
"""Load index from DuckDB (preferred) or JSON fallback."""
|
|
47
59
|
try:
|
|
48
|
-
from search_index import _duckdb_load
|
|
60
|
+
from domain.kg.search.search_index import _duckdb_load
|
|
49
61
|
result = _duckdb_load(filename)
|
|
50
62
|
if result is not None:
|
|
51
63
|
return result
|
|
@@ -62,11 +74,14 @@ def load(filename):
|
|
|
62
74
|
|
|
63
75
|
|
|
64
76
|
def expand_query(query):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
"""词扩展: 委托给 expand_chinese_query (三级匹配: 精确/分词/兜底)。
|
|
78
|
+
|
|
79
|
+
旧版只查精确匹配, 复合词如 "保险单OCR" / "异常记录" 查不到就 0 命中。
|
|
80
|
+
现在用 expand_chinese_query, 能拆 "保险单OCR" → "保险" + "ocr",
|
|
81
|
+
"异常记录" → "异常" + "记录", 大幅减少单词查询的 0 命中。
|
|
82
|
+
"""
|
|
83
|
+
words = expand_chinese_query(query)
|
|
84
|
+
# 兜底: 拆不出词就用原词小写 (让英文索引做子串匹配)
|
|
70
85
|
return sorted(set(w.lower() for w in words)) or [query.lower()]
|
|
71
86
|
|
|
72
87
|
|
|
@@ -132,7 +147,7 @@ def _save_cache(key, content):
|
|
|
132
147
|
os.replace(tmp, cache_path)
|
|
133
148
|
# LRU 清理: 保留最新 30 个, 删更老的
|
|
134
149
|
try:
|
|
135
|
-
from search_index import _cleanup_cache_dir
|
|
150
|
+
from domain.kg.search.search_index import _cleanup_cache_dir
|
|
136
151
|
_cleanup_cache_dir(cache_dir, 'ctx-cache-', max_files=30)
|
|
137
152
|
except Exception:
|
|
138
153
|
pass
|
|
@@ -212,6 +227,21 @@ def _compute_and_print(query, platform, page_type):
|
|
|
212
227
|
print('- {} (命中: {}) -> {}'.format(f, ','.join(sorted(kws)[:3]), full))
|
|
213
228
|
if not hits:
|
|
214
229
|
print('- (无命中 — 换业务词重试, 或该功能为全新)')
|
|
230
|
+
# 语义补充: 关键词命中稀疏时, 用 bge-small-zh 向量检索补一轮 (中→英跨语言)。
|
|
231
|
+
# 模型未装/无 embedding → 静默跳过, 不报错。
|
|
232
|
+
if len(hits) <= 2:
|
|
233
|
+
try:
|
|
234
|
+
from domain.kg.graph.kg_semantic import semantic_search_files, filter_semantic_by_platform
|
|
235
|
+
sem = semantic_search_files(query, top_k=8)
|
|
236
|
+
if sem:
|
|
237
|
+
filtered = filter_semantic_by_platform(sem, platform, BASE)
|
|
238
|
+
if filtered:
|
|
239
|
+
print('- [语义补充] (关键词命中少, 用向量检索跨语言补充):')
|
|
240
|
+
for fp, cn, score in filtered[:6]:
|
|
241
|
+
full = 'data/code/' + fp
|
|
242
|
+
print(' - %.2f %s -> %s' % (score, cn[:20], full))
|
|
243
|
+
except Exception:
|
|
244
|
+
pass
|
|
215
245
|
|
|
216
246
|
# ---- 2. 同类型页面真实示例 ----
|
|
217
247
|
si = load('ui-style.json') or {}
|
|
@@ -279,8 +309,8 @@ def _compute_and_print(query, platform, page_type):
|
|
|
279
309
|
code_dir = os.path.join(BASE, 'data', 'code')
|
|
280
310
|
wiki_results = []
|
|
281
311
|
try:
|
|
282
|
-
from
|
|
283
|
-
from
|
|
312
|
+
from repowiki import search_wiki, build_wiki_index
|
|
313
|
+
from foundation.integrations.terms import get_cn_map_with_auto
|
|
284
314
|
wiki_idx_path = os.path.join(BUILD_CACHE_DIR, 'wiki-index.json')
|
|
285
315
|
if not os.path.isfile(wiki_idx_path):
|
|
286
316
|
build_wiki_index(code_dir, wiki_idx_path)
|
|
@@ -315,10 +345,9 @@ def _compute_and_print(query, platform, page_type):
|
|
|
315
345
|
|
|
316
346
|
# ── 8. 数据库表结构 (从 kg_db.duckdb, 合并了原来要单独调 MCP 的查询) ──
|
|
317
347
|
try:
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if
|
|
321
|
-
con = _ddb2.connect(db_path, read_only=True)
|
|
348
|
+
from domain.kg.search.search_index import _get_kg_db
|
|
349
|
+
con = _get_kg_db() # 惰性缓存的只读连接, 不在此 close (供后续调用复用)
|
|
350
|
+
if con is not None:
|
|
322
351
|
# 关键词匹配表名 (英文词或snake_case, camelCase自动转)
|
|
323
352
|
kw_lower = query.lower()
|
|
324
353
|
# camelCase → snake_case (qualityCase → quality_case)
|
|
@@ -349,7 +378,6 @@ def _compute_and_print(query, platform, page_type):
|
|
|
349
378
|
if ents:
|
|
350
379
|
print(' {} → Entity: {}'.format(
|
|
351
380
|
tn, ', '.join(e[0] for e in ents)))
|
|
352
|
-
con.close()
|
|
353
381
|
except Exception:
|
|
354
382
|
pass # kg_db不存在/被占用 → 跳过, 不影响其它段
|
|
355
383
|
|