@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.
Files changed (253) hide show
  1. package/bin/cli.js +1435 -1107
  2. package/package.json +29 -29
  3. package/templates/qoder/agents/insight-planning.md +1 -1
  4. package/templates/qoder/agents/insight-research.md +28 -15
  5. package/templates/qoder/commands/optional/wl-insight.md +161 -161
  6. package/templates/qoder/commands/optional/wl-report.md +20 -39
  7. package/templates/qoder/commands/optional/wl-status.md +4 -4
  8. package/templates/qoder/commands/wl-code.md +2 -2
  9. package/templates/qoder/commands/wl-design.md +6 -6
  10. package/templates/qoder/commands/wl-init.md +3 -3
  11. package/templates/qoder/commands/wl-prd.md +26 -13
  12. package/templates/qoder/commands/wl-req.md +43 -0
  13. package/templates/qoder/commands/wl-search.md +78 -47
  14. package/templates/qoder/commands/wl-task.md +343 -40
  15. package/templates/qoder/commands/wl-test.md +43 -17
  16. package/templates/qoder/config.yaml +52 -14
  17. package/templates/qoder/hooks/post-tool-use.py +181 -0
  18. package/templates/qoder/hooks/session-start.py +94 -23
  19. package/templates/qoder/hooks/stop-eval.py +207 -0
  20. package/templates/qoder/hooks/user-prompt-submit.py +139 -0
  21. package/templates/qoder/rules/wl-pipeline.md +85 -49
  22. package/templates/qoder/scripts/README.md +102 -0
  23. package/templates/qoder/scripts/capability/__init__.py +26 -0
  24. package/templates/qoder/scripts/capability/__main__.py +72 -0
  25. package/templates/qoder/scripts/capability/adapters/__init__.py +29 -0
  26. package/templates/qoder/scripts/capability/adapters/cli.py +316 -0
  27. package/templates/qoder/scripts/capability/adapters/mcp.py +334 -0
  28. package/templates/qoder/scripts/capability/adapters/qw.py +271 -0
  29. package/templates/qoder/scripts/capability/caps/__init__.py +27 -0
  30. package/templates/qoder/scripts/capability/caps/context.py +36 -0
  31. package/templates/qoder/scripts/capability/caps/cron.py +50 -0
  32. package/templates/qoder/scripts/capability/caps/identity.py +43 -0
  33. package/templates/qoder/scripts/capability/caps/memory.py +71 -0
  34. package/templates/qoder/scripts/capability/caps/notify.py +41 -0
  35. package/templates/qoder/scripts/capability/caps/present.py +48 -0
  36. package/templates/qoder/scripts/capability/caps/repo.py +31 -0
  37. package/templates/qoder/scripts/capability/caps/sandbox.py +43 -0
  38. package/templates/qoder/scripts/capability/chain.py +92 -0
  39. package/templates/qoder/scripts/capability/memory_chain.py +41 -0
  40. package/templates/qoder/scripts/capability/registry.py +246 -0
  41. package/templates/qoder/scripts/capability/registry_mcp.py +250 -0
  42. package/templates/qoder/scripts/capability/smoke_test.py +211 -0
  43. package/templates/qoder/scripts/capability/smoke_test_report.json +94 -0
  44. package/templates/qoder/scripts/deployment/setup/__init__.py +11 -0
  45. package/templates/qoder/scripts/deployment/setup/carriers.py +669 -0
  46. package/templates/qoder/scripts/deployment/setup/carriers_verify.py +148 -0
  47. package/templates/qoder/scripts/{init_doctor.py → deployment/setup/init_doctor.py} +100 -39
  48. package/templates/qoder/scripts/{install_qoderwork.py → deployment/setup/install_qoderwork.py} +48 -30
  49. package/templates/qoder/scripts/{platform_doctor.py → deployment/setup/platform_doctor.py} +271 -259
  50. package/templates/qoder/scripts/{repo_root.py → deployment/setup/repo_root.py} +9 -2
  51. package/templates/qoder/scripts/{setup.py → deployment/setup/setup.py} +143 -14
  52. package/templates/qoder/scripts/{setup_lanhu.py → deployment/setup/setup_lanhu.py} +979 -963
  53. package/templates/qoder/scripts/domain/design/__init__.py +0 -0
  54. package/templates/qoder/scripts/{fill_prototype.py → domain/design/fill_prototype.py} +17 -5
  55. package/templates/qoder/scripts/{gen_design_doc.py → domain/design/gen_design_doc.py} +406 -394
  56. package/templates/qoder/scripts/domain/kg/__init__.py +11 -0
  57. package/templates/qoder/scripts/domain/kg/build/__init__.py +0 -0
  58. package/templates/qoder/scripts/domain/kg/build/build_entity_registry.py +201 -0
  59. package/templates/qoder/scripts/domain/kg/build/build_relations.py +132 -0
  60. package/templates/qoder/scripts/{build_style_index.py → domain/kg/build/build_style_index.py} +50 -15
  61. package/templates/qoder/scripts/domain/kg/build/build_workflows.py +149 -0
  62. package/templates/qoder/scripts/{kg_build.py → domain/kg/build/kg_build.py} +685 -612
  63. package/templates/qoder/scripts/{kg_build_db.py → domain/kg/build/kg_build_db.py} +338 -327
  64. package/templates/qoder/scripts/{kg_incremental.py → domain/kg/build/kg_incremental.py} +425 -393
  65. package/templates/qoder/scripts/{learn_aggregate.py → domain/kg/build/learn_aggregate.py} +212 -201
  66. package/templates/qoder/scripts/domain/kg/extract/__init__.py +0 -0
  67. package/templates/qoder/scripts/{common → domain/kg/extract}/extract.py +430 -419
  68. package/templates/qoder/scripts/domain/kg/extract/test_extract.py +115 -0
  69. package/templates/qoder/scripts/{common → domain/kg/extract}/ts_extract.py +614 -536
  70. package/templates/qoder/scripts/domain/kg/graph/__init__.py +0 -0
  71. package/templates/qoder/scripts/{kg_link_db.py → domain/kg/graph/kg_link_db.py} +235 -224
  72. package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +683 -0
  73. package/templates/qoder/scripts/{kg.py → domain/kg/kg.py} +871 -708
  74. package/templates/qoder/scripts/domain/kg/kg_capabilities.py +182 -0
  75. package/templates/qoder/scripts/domain/kg/search/__init__.py +0 -0
  76. package/templates/qoder/scripts/{context_pack.py → domain/kg/search/context_pack.py} +45 -17
  77. package/templates/qoder/scripts/{enrich_prompt.py → domain/kg/search/enrich_prompt.py} +238 -226
  78. package/templates/qoder/scripts/domain/kg/search/prefetch.py +384 -0
  79. package/templates/qoder/scripts/{common → domain/kg/search}/search_engine.py +207 -205
  80. package/templates/qoder/scripts/{search_index.py → domain/kg/search/search_index.py} +210 -88
  81. package/templates/qoder/scripts/domain/kg/server/__init__.py +0 -0
  82. package/templates/qoder/scripts/domain/kg/server/kgd.py +549 -0
  83. package/templates/qoder/scripts/domain/kg/server/perf_bench.py +197 -0
  84. package/templates/qoder/scripts/domain/kg/storage/__init__.py +0 -0
  85. package/templates/qoder/scripts/{kg_duckdb.py → domain/kg/storage/kg_duckdb.py} +70 -45
  86. package/templates/qoder/scripts/domain/learning/__init__.py +0 -0
  87. package/templates/qoder/scripts/{learn.py → domain/learning/learn.py} +157 -146
  88. package/templates/qoder/scripts/domain/report/__init__.py +11 -0
  89. package/templates/qoder/scripts/{add_session.py → domain/report/add_session.py} +256 -244
  90. package/templates/qoder/scripts/{export.py → domain/report/export.py} +72 -4
  91. package/templates/qoder/scripts/{report.py → domain/report/report.py} +292 -281
  92. package/templates/qoder/scripts/domain/report/report_snapshot.py +261 -0
  93. package/templates/qoder/scripts/domain/report/role.py +39 -0
  94. package/templates/qoder/scripts/{status.py → domain/report/status.py} +737 -628
  95. package/templates/qoder/scripts/domain/report/status_snapshot.py +191 -0
  96. package/templates/qoder/scripts/domain/requirement/__init__.py +0 -0
  97. package/templates/qoder/scripts/{archive_prd.py → domain/requirement/archive_prd.py} +389 -377
  98. package/templates/qoder/scripts/domain/requirement/req.py +228 -0
  99. package/templates/qoder/scripts/domain/task/__init__.py +11 -0
  100. package/templates/qoder/scripts/{git_sync.py → domain/task/git_sync.py} +90 -50
  101. package/templates/qoder/scripts/{syncgate.py → domain/task/syncgate.py} +18 -7
  102. package/templates/qoder/scripts/domain/task/task.py +229 -0
  103. package/templates/qoder/scripts/domain/task/task_lifecycle.py +606 -0
  104. package/templates/qoder/scripts/domain/task/task_query.py +162 -0
  105. package/templates/qoder/scripts/domain/task/task_relations.py +425 -0
  106. package/templates/qoder/scripts/{team_sync.py → domain/task/team_sync.py} +101 -23
  107. package/templates/qoder/scripts/domain/task/zentao_sync.py +370 -0
  108. package/templates/qoder/scripts/foundation/__init__.py +0 -0
  109. package/templates/qoder/scripts/foundation/bootstrap.py +145 -0
  110. package/templates/qoder/scripts/foundation/core/__init__.py +0 -0
  111. package/templates/qoder/scripts/foundation/core/cmd_registry.py +112 -0
  112. package/templates/qoder/scripts/foundation/core/config.py +187 -0
  113. package/templates/qoder/scripts/{common → foundation/core}/paths.py +706 -400
  114. package/templates/qoder/scripts/foundation/data/__init__.py +0 -0
  115. package/templates/qoder/scripts/foundation/data/contract.py +317 -0
  116. package/templates/qoder/scripts/{common → foundation/data}/events.py +2 -2
  117. package/templates/qoder/scripts/foundation/data/result.py +223 -0
  118. package/templates/qoder/scripts/{common → foundation/data}/task_utils.py +427 -392
  119. package/templates/qoder/scripts/foundation/identity/__init__.py +0 -0
  120. package/templates/qoder/scripts/foundation/identity/check_publish.py +103 -0
  121. package/templates/qoder/scripts/{common → foundation/identity}/developer.py +239 -238
  122. package/templates/qoder/scripts/foundation/identity/guard.py +159 -0
  123. package/templates/qoder/scripts/{common → foundation/identity}/identity.py +132 -9
  124. package/templates/qoder/scripts/foundation/identity/roles.py +60 -0
  125. package/templates/qoder/scripts/foundation/integrations/__init__.py +0 -0
  126. package/templates/qoder/scripts/{common → foundation/integrations}/active_task.py +30 -15
  127. package/templates/qoder/scripts/{common → foundation/integrations}/feishu.py +11 -10
  128. package/templates/qoder/scripts/{common → foundation/integrations}/terms.py +3 -3
  129. package/templates/qoder/scripts/foundation/integrations/zentao_client.py +220 -0
  130. package/templates/qoder/scripts/foundation/io/__init__.py +0 -0
  131. package/templates/qoder/scripts/{common → foundation/io}/filelock.py +1 -1
  132. package/templates/qoder/scripts/{common → foundation/io}/reqid.py +1 -1
  133. package/templates/qoder/scripts/foundation/protocol/__init__.py +0 -0
  134. package/templates/qoder/scripts/foundation/protocol/duckdb_conn.py +39 -0
  135. package/templates/qoder/scripts/foundation/protocol/mcp_base.py +268 -0
  136. package/templates/qoder/scripts/foundation/utils/__init__.py +0 -0
  137. package/templates/qoder/scripts/{common → foundation/utils}/eval_api.py +12 -1
  138. package/templates/qoder/scripts/{common → foundation/utils}/pip_install.py +23 -6
  139. package/templates/qoder/scripts/{common → foundation/utils}/platform_guard.py +1 -1
  140. package/templates/qoder/scripts/orchestration/__init__.py +0 -0
  141. package/templates/qoder/scripts/orchestration/wlkj.py +185 -0
  142. package/templates/qoder/scripts/protocol/__init__.py +0 -0
  143. package/templates/qoder/scripts/protocol/browser/README.md +207 -0
  144. package/templates/qoder/scripts/protocol/browser/SKILL.md +265 -0
  145. package/templates/qoder/scripts/protocol/browser/config.env +9 -0
  146. package/templates/qoder/scripts/protocol/browser/references/cdp-api.md +110 -0
  147. package/templates/qoder/scripts/protocol/browser/references/migration-2.5.3.md +72 -0
  148. package/templates/qoder/scripts/protocol/browser/references/site-patterns/.gitkeep +0 -0
  149. package/templates/qoder/scripts/protocol/browser/scripts/browser-discovery.mjs +138 -0
  150. package/templates/qoder/scripts/protocol/browser/scripts/cdp-proxy.mjs +672 -0
  151. package/templates/qoder/scripts/protocol/browser/scripts/check-deps.mjs +206 -0
  152. package/templates/qoder/scripts/protocol/browser/scripts/find-url.mjs +253 -0
  153. package/templates/qoder/scripts/protocol/browser/scripts/match-site.mjs +46 -0
  154. package/templates/qoder/scripts/protocol/browser/templates/config.env.template +9 -0
  155. package/templates/qoder/scripts/protocol/mcp/__init__.py +11 -0
  156. package/templates/qoder/scripts/protocol/mcp/kg_mcp_server.py +478 -0
  157. package/templates/qoder/scripts/{lanhu_stdio_wrapper.py → protocol/mcp/lanhu_stdio_wrapper.py} +131 -119
  158. package/templates/qoder/scripts/protocol/mcp/mcp_doctor.py +548 -0
  159. package/templates/qoder/scripts/protocol/mcp/mcp_launcher.py +600 -0
  160. package/templates/qoder/scripts/protocol/mcp/mysql_mcp_server.py +461 -0
  161. package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +1920 -0
  162. package/templates/qoder/scripts/protocol/transports/__init__.py +56 -0
  163. package/templates/qoder/scripts/protocol/transports/base.py +87 -0
  164. package/templates/qoder/scripts/protocol/transports/cli.py +132 -0
  165. package/templates/qoder/scripts/protocol/transports/http.py +141 -0
  166. package/templates/qoder/scripts/protocol/transports/stdio.py +293 -0
  167. package/templates/qoder/scripts/run_weekly_update.bat +27 -18
  168. package/templates/qoder/scripts/run_weekly_update.sh +22 -13
  169. package/templates/qoder/scripts/validation/__init__.py +0 -0
  170. package/templates/qoder/scripts/validation/eval/__init__.py +0 -0
  171. package/templates/qoder/scripts/validation/eval/perf-report-2026-06-24.md +139 -0
  172. package/templates/qoder/scripts/validation/eval/qwork_harness.py +617 -0
  173. package/templates/qoder/scripts/validation/eval/report-commands.md +220 -0
  174. package/templates/qoder/scripts/validation/eval/transcript_timing.py +386 -0
  175. package/templates/qoder/scripts/validation/metrics/__init__.py +0 -0
  176. package/templates/qoder/scripts/{eval_prd.py → validation/metrics/eval_prd.py} +84 -15
  177. package/templates/qoder/scripts/validation/metrics/usability_score.py +750 -0
  178. package/templates/qoder/scripts/validation/test/__init__.py +11 -0
  179. package/templates/qoder/scripts/validation/test/assertion_gen.py +551 -0
  180. package/templates/qoder/scripts/{autotest.py → validation/test/autotest.py} +1234 -1751
  181. package/templates/qoder/scripts/validation/test/autotest_auth.py +109 -0
  182. package/templates/qoder/scripts/{autotest_batch.py → validation/test/autotest_batch.py} +255 -224
  183. package/templates/qoder/scripts/validation/test/autotest_data.py +680 -0
  184. package/templates/qoder/scripts/validation/test/autotest_opencli.py +646 -0
  185. package/templates/qoder/scripts/{autotest_run.py → validation/test/autotest_run.py} +323 -297
  186. package/templates/qoder/scripts/validation/test/autotest_webaccess.py +571 -0
  187. package/templates/qoder/scripts/{benchmark.py → validation/test/benchmark.py} +17 -5
  188. package/templates/qoder/scripts/{kg_auto_login.py → validation/test/kg_auto_login.py} +208 -196
  189. package/templates/qoder/scripts/{kg_test_runner.py → validation/test/kg_test_runner.py} +13 -2
  190. package/templates/qoder/scripts/{page_probe.py → validation/test/page_probe.py} +470 -459
  191. package/templates/qoder/scripts/validation/test/smoke_all_commands.py +170 -0
  192. package/templates/qoder/settings.json +23 -2
  193. package/templates/qoder/skills/design-import/SKILL.md +235 -226
  194. package/templates/qoder/skills/design-review/SKILL.md +91 -82
  195. package/templates/qoder/skills/prd-generator/SKILL.md +38 -24
  196. package/templates/qoder/skills/prd-review/SKILL.md +8 -6
  197. package/templates/qoder/skills/prototype-generator/SKILL.md +296 -247
  198. package/templates/qoder/skills/spec-coder/SKILL.md +24 -15
  199. package/templates/qoder/skills/spec-generator/SKILL.md +24 -12
  200. package/templates/qoder/skills/test-generator/SKILL.md +9 -7
  201. package/templates/qoder/skills/wl-code/SKILL.md +25 -13
  202. package/templates/qoder/skills/wl-commit/SKILL.md +10 -9
  203. package/templates/qoder/skills/wl-design/SKILL.md +7 -5
  204. package/templates/qoder/skills/wl-init/SKILL.md +8 -8
  205. package/templates/qoder/skills/wl-insight/SKILL.md +25 -12
  206. package/templates/qoder/skills/wl-prd-full/SKILL.md +59 -8
  207. package/templates/qoder/skills/wl-prd-quick/SKILL.md +7 -7
  208. package/templates/qoder/skills/wl-prd-review/SKILL.md +18 -6
  209. package/templates/qoder/skills/wl-report/SKILL.md +27 -25
  210. package/templates/qoder/skills/wl-search/SKILL.md +151 -80
  211. package/templates/qoder/skills/wl-spec/SKILL.md +9 -7
  212. package/templates/qoder/skills/wl-status/SKILL.md +50 -18
  213. package/templates/qoder/skills/wl-task/SKILL.md +94 -12
  214. package/templates/qoder/skills/wl-test/SKILL.md +154 -45
  215. package/templates/qoder/templates/prd-full-template.md +7 -0
  216. package/templates/root/AGENTS.md +275 -237
  217. package/templates/root/requirements.txt +3 -0
  218. package/templates/root//344/275/277/347/224/250/350/257/264/346/230/216.md +3 -3
  219. package/templates/root//346/226/260/346/211/213/346/214/207/345/215/227.md +2 -2
  220. package/templates/qoder/hooks/inject-workflow-state.py +0 -169
  221. package/templates/qoder/scripts/__pycache__/check_mcp_launch.cpython-39.pyc +0 -0
  222. package/templates/qoder/scripts/__pycache__/install_qoderwork.cpython-39.pyc +0 -0
  223. package/templates/qoder/scripts/__pycache__/mcp_launcher.cpython-39.pyc +0 -0
  224. package/templates/qoder/scripts/__pycache__/platform_doctor.cpython-39.pyc +0 -0
  225. package/templates/qoder/scripts/check_carriers.py +0 -238
  226. package/templates/qoder/scripts/check_mcp.py +0 -298
  227. package/templates/qoder/scripts/check_mcp_launch.py +0 -183
  228. package/templates/qoder/scripts/check_qoderwork_consistency.py +0 -166
  229. package/templates/qoder/scripts/collect_prds.py +0 -31
  230. package/templates/qoder/scripts/common/mentions.py +0 -134
  231. package/templates/qoder/scripts/common/utf8.py +0 -38
  232. package/templates/qoder/scripts/extract_api_params.py +0 -246
  233. package/templates/qoder/scripts/extract_routes.py +0 -54
  234. package/templates/qoder/scripts/extract_routes_tree.py +0 -78
  235. package/templates/qoder/scripts/handoff.py +0 -22
  236. package/templates/qoder/scripts/init_developer.py +0 -76
  237. package/templates/qoder/scripts/kg_mcp_server.py +0 -801
  238. package/templates/qoder/scripts/kg_semantic.py +0 -150
  239. package/templates/qoder/scripts/mcp_launcher.py +0 -414
  240. package/templates/qoder/scripts/mysql_mcp_server.py +0 -396
  241. package/templates/qoder/scripts/parse_prds.py +0 -33
  242. package/templates/qoder/scripts/role.py +0 -51
  243. package/templates/qoder/scripts/sync_carriers.py +0 -259
  244. package/templates/qoder/scripts/task.py +0 -1261
  245. package/templates/qoder/scripts/workspace_init.py +0 -102
  246. package/templates/qoder/scripts/zentao_mcp_server.py +0 -424
  247. package/templates/qoder/skills/prompt-enrich/SKILL.md +0 -90
  248. /package/templates/qoder/scripts/{common → deployment}/__init__.py +0 -0
  249. /package/templates/qoder/{skills/prototype-generator/SKILL.md.zcode-79180-2af4721f-f9a6-412c-88db-c0af680d211b.tmp → scripts/domain/__init__.py} +0 -0
  250. /package/templates/qoder/scripts/{common → domain/kg/graph}/graph_traverse.py +0 -0
  251. /package/templates/qoder/scripts/{common → domain/kg/server}/repowiki.py +0 -0
  252. /package/templates/qoder/scripts/{common → foundation/io}/atomicio.py +0 -0
  253. /package/templates/qoder/scripts/{secure-ls.js → validation/test/secure-ls.js} +0 -0
@@ -1,226 +1,238 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """enrich_prompt.py - 极速提示词润色 (用户提问后第 0 步)
4
-
5
- 目标: 在用户提问后, <10ms 内判断这句话命中哪些业务关键词,
6
- 输出一个「润色后的提示词」给用户确认, 再走原命令。
7
-
8
- 设计:
9
- - 纯内存查表 (不跑重检索 context_pack, 那个留给确认后)
10
- - 中文分词复用 common/terms.py 的 expand_chinese_query
11
- - 命中 keyword-index / api-index / prd-index 的键
12
- - 命中 0 = 非业务消息 (谢谢/继续), 直接放行不润色
13
-
14
- 用法:
15
- python .qoder/scripts/enrich_prompt.py "保险批改那个异常统计页加个审批按钮"
16
- python .qoder/scripts/enrich_prompt.py "保险批改..." --json # 机器可读
17
-
18
- 输出 (默认人类可读):
19
- ── 极速润色 ──
20
- 业务词: 保险→insurance, 批改→amend, 异常→abnormal...
21
- 相关代码符号: 108 (abnormalovertime, approval-cell...)
22
- 相关API: 5
23
- 历史 PRD: 2
24
- ──────────────
25
- 将以上下文继续。回复"改:xxx"调整, 任意其它内容=接受。
26
- """
27
- import os, sys, json, time
28
-
29
- if sys.platform == 'win32':
30
- try:
31
- sys.stdout.reconfigure(encoding='utf-8')
32
- except Exception:
33
- pass
34
-
35
- BASE = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
36
- sys.path.insert(0, os.path.join(BASE, '.qoder', 'scripts'))
37
-
38
- IDX_DIR = os.path.join(BASE, 'data', 'index')
39
- # 缓存: 同一进程内只加载一次索引
40
- _CACHE = {}
41
-
42
-
43
- def _load(name):
44
- """加载索引 (优先 DuckDB, 回退 JSON)。复用 search_index.load_index 的 fallback 逻辑。"""
45
- if name in _CACHE:
46
- return _CACHE[name]
47
- try:
48
- from search_index import load_index
49
- d = load_index(name) or {}
50
- except ImportError:
51
- # search_index 不可用时, 直接读 JSON (老逻辑)
52
- d = {}
53
- path = os.path.join(IDX_DIR, name)
54
- if os.path.isfile(path):
55
- try:
56
- for enc in ('utf-8', 'gbk'):
57
- try:
58
- with open(path, encoding=enc) as f:
59
- d = json.load(f)
60
- break
61
- except (OSError, UnicodeDecodeError):
62
- continue
63
- except Exception:
64
- pass
65
- _CACHE[name] = d
66
- return d
67
-
68
-
69
- # 短而无意义的英文 token 黑名单 (避免子串误命中 'cs'/'fl'/'in' 这类噪声)
70
- # 提到模块级: _match_keys code_total 共用一份
71
- NOISE_KEYS = {
72
- 'app', 'api', 'all', 'add', 'age', 'and', 'are', 'ars', 'ase', 'ask',
73
- 'ate', 'aud', 'bar', 'big', 'btn', 'can', 'car', 'cas', 'cat', 'code',
74
- 'con', 'cor', 'cs', 'cur', 'dae', 'dat', 'day', 'del', 'dep', 'des',
75
- 'det', 'dim', 'div', 'doc', 'dos', 'ear', 'ecs', 'ema', 'end', 'ent',
76
- 'err', 'eva', 'exe', 'exp', 'ext', 'fil', 'fix', 'fl', 'for', 'ge',
77
- 'gen', 'get', 'has', 'her', 'his', 'ics', 'idx', 'imp', 'int', 'inv',
78
- 'io', 'is', 'iso', 'ite', 'its', 'key', 'lab', 'lan', 'lat', 'let',
79
- 'lin', 'lis', 'log', 'ma', 'map', 'max', 'min', 'mod', 'msg', 'new',
80
- 'nil', 'not', 'now', 'num', 'obj', 'off', 'one', 'opt', 'ord', 'out',
81
- 'ove', 'own', 'pag', 'par', 'pas', 'pay', 'pen', 'per', 'pos', 'pre',
82
- 'pro', 'put', 'que', 'rec', 'red', 'ref', 'reg', 'rep', 'res', 'ret',
83
- 'rev', 'row', 'run', 'sa', 'sel', 'set', 'sev', 'sie', 'sit', 'sor',
84
- 'src', 'sta', 'sub', 'sum', 'sys', 'tab', 'tar', 'tes', 'tex', 'tim',
85
- 'tmp', 'tok', 'tom', 'top', 'tot', 'tru', 'try', 'typ', 'udp', 'uni',
86
- 'upd', 'url', 'use', 'usr', 'val', 'ver', 'vid', 'vio', 'vis', 'voi',
87
- 'was', 'way', 'who', 'why', 'win', 'wri', 'xml', 'you', 'your', 'zone',
88
- }
89
-
90
-
91
- def _match_keys(query_lower, keys, max_hits=15, min_len=3):
92
- """在 keys 里找被 query 包含的 (子串匹配), 返回命中列表 + 总数。
93
- min_len: 短于这个长度的键忽略 (避免 'cs'/'fl'/'in' 这类噪声子串)。"""
94
- hits = []
95
- for k in keys:
96
- kl = k.lower()
97
- if len(kl) < min_len:
98
- continue
99
- if kl in NOISE_KEYS:
100
- continue
101
- if kl in query_lower:
102
- hits.append(k)
103
- if len(hits) >= max_hits:
104
- break
105
- return hits
106
- for k in keys:
107
- kl = k.lower()
108
- if len(kl) < min_len:
109
- continue
110
- if kl in NOISE:
111
- continue
112
- if kl in query_lower:
113
- hits.append(k)
114
- if len(hits) >= max_hits:
115
- break
116
- return hits
117
-
118
-
119
- def enrich(query):
120
- """润色主函数。返回 dict:
121
- {
122
- 'is_business': bool, # 是否业务消息 (有命中才算)
123
- 'cn_words': [...], # 中文分词出的英文搜索词
124
- 'code_hits': [...], # 命中的代码符号 (样例)
125
- 'code_total': int, # 代码命中总数
126
- 'api_hits': [...], # 命中的 API
127
- 'prd_hits': [...], # 命中的历史 PRD
128
- 'elapsed_ms': float, # 耗时
129
- 'polished': str, # 润色后的提示词 (人类可读)
130
- }
131
- """
132
- t0 = time.perf_counter()
133
- from common.terms import expand_chinese_query
134
-
135
- # 1. 中文分词 → 英文搜索词
136
- cn_words = list(dict.fromkeys(expand_chinese_query(query))) # 去重保序
137
-
138
- # 2. 构造匹配串: 原句 + 扩展出的英文词, 一起拿去命中索引
139
- match_str = query.lower()
140
- for w in cn_words:
141
- match_str += ' ' + w.lower()
142
-
143
- # 3. 命中三类索引
144
- code_idx = _load('code-keyword.json')
145
- code_keys = list(code_idx.keys()) if isinstance(code_idx, dict) else []
146
- code_hits = _match_keys(match_str, code_keys)
147
-
148
- api_idx = _load('code-api.json')
149
- api_keys = []
150
- if isinstance(api_idx, dict):
151
- api_keys = list(api_idx.keys())
152
- api_hits = _match_keys(match_str, api_keys)
153
-
154
- prd_idx = _load('prd-index.json')
155
- prd_keys = []
156
- if isinstance(prd_idx, dict):
157
- prd_keys = list(prd_idx.keys())
158
- prd_hits = _match_keys(match_str, prd_keys, max_hits=5)
159
-
160
- # 4. 代码命中总数 (不限 max, 用于展示规模; 用与 _match_keys 一致的过滤)
161
- code_total = 0
162
- if code_keys:
163
- code_total = sum(1 for k in code_keys
164
- if len(k) >= 3 and k.lower() not in NOISE_KEYS
165
- and k.lower() in match_str)
166
-
167
- elapsed_ms = (time.perf_counter() - t0) * 1000
168
- is_business = bool(code_hits or api_hits or prd_hits or cn_words)
169
-
170
- # 5. 组装润色后提示词 (人类可读)
171
- lines = []
172
- if not is_business:
173
- lines.append('(非业务消息,无需润色,直接放行)')
174
- else:
175
- if cn_words:
176
- shown = ', '.join(cn_words[:8])
177
- lines.append('业务词: ' + shown)
178
- if code_total:
179
- sample = ', '.join(code_hits[:8])
180
- more = '' if code_total <= len(code_hits) else ' ...'
181
- lines.append('相关代码符号: %d 处 (%s%s)' % (code_total, sample, more))
182
- if api_hits:
183
- lines.append('相关 API: %d 个 (%s)' % (len(api_hits), ', '.join(api_hits[:5])))
184
- if prd_hits:
185
- lines.append('历史 PRD: %s' % ', '.join(prd_hits[:5]))
186
-
187
- polished = '\n'.join(lines)
188
-
189
- return {
190
- 'is_business': is_business,
191
- 'cn_words': cn_words,
192
- 'code_hits': code_hits,
193
- 'code_total': code_total,
194
- 'api_hits': api_hits,
195
- 'prd_hits': prd_hits,
196
- 'elapsed_ms': round(elapsed_ms, 2),
197
- 'polished': polished,
198
- }
199
-
200
-
201
- def main():
202
- args = sys.argv[1:]
203
- if not args:
204
- print(__doc__)
205
- print('错误: 缺少查询参数。用法: enrich_prompt.py "你的问题"')
206
- sys.exit(2)
207
- query = ' '.join(args[:1]) if args[0] in ('--json',) else ' '.join(args)
208
- # 处理 --json 标志
209
- as_json = '--json' in args
210
- query = query.replace('--json', '').strip()
211
-
212
- result = enrich(query)
213
- if as_json:
214
- print(json.dumps(result, ensure_ascii=False))
215
- return
216
-
217
- # 人类可读输出
218
- print('── 极速润色 (%.1fms) ──' % result['elapsed_ms'])
219
- print(result['polished'])
220
- if result['is_business']:
221
- print('──────────────')
222
- print('将以上下文继续。回复"改:xxx"调整,任意其它内容=接受。')
223
-
224
-
225
- if __name__ == '__main__':
226
- 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
+ _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
+
15
+ """enrich_prompt.py - 极速提示词润色 (用户提问后第 0 步)
16
+
17
+ 目标: 在用户提问后, <10ms 内判断这句话命中哪些业务关键词,
18
+ 输出一个「润色后的提示词」给用户确认, 再走原命令。
19
+
20
+ 设计:
21
+ - 纯内存查表 (不跑重检索 context_pack, 那个留给确认后)
22
+ - 中文分词复用 common/terms.py 的 expand_chinese_query
23
+ - 命中 keyword-index / api-index / prd-index 的键
24
+ - 命中 0 个 = 非业务消息 (谢谢/继续), 直接放行不润色
25
+
26
+ 用法:
27
+ python .qoder/scripts/enrich_prompt.py "保险批改那个异常统计页加个审批按钮"
28
+ python .qoder/scripts/enrich_prompt.py "保险批改..." --json # 机器可读
29
+
30
+ 输出 (默认人类可读):
31
+ ── 极速润色 ──
32
+ 业务词: 保险→insurance, 批改→amend, 异常→abnormal...
33
+ 相关代码符号: 108 处 (abnormalovertime, approval-cell...)
34
+ 相关API: 5 个
35
+ 历史 PRD: 2 篇
36
+ ──────────────
37
+ 将以上下文继续。回复"改:xxx"调整, 任意其它内容=接受。
38
+ """
39
+ import os, sys, json, time
40
+
41
+ if sys.platform == 'win32':
42
+ try:
43
+ sys.stdout.reconfigure(encoding='utf-8')
44
+ except Exception:
45
+ pass
46
+
47
+ BASE = get_repo_root()
48
+ sys.path.insert(0, os.path.join(BASE, '.qoder', 'scripts'))
49
+
50
+ IDX_DIR = os.path.join(BASE, 'data', 'index')
51
+ # 缓存: 同一进程内只加载一次索引
52
+ _CACHE = {}
53
+
54
+
55
+ def _load(name):
56
+ """加载索引 (优先 DuckDB, 回退 JSON)。复用 search_index.load_index 的 fallback 逻辑。"""
57
+ if name in _CACHE:
58
+ return _CACHE[name]
59
+ try:
60
+ from domain.kg.search.search_index import load_index
61
+ d = load_index(name) or {}
62
+ except ImportError:
63
+ # search_index 不可用时, 直接读 JSON (老逻辑)
64
+ d = {}
65
+ path = os.path.join(IDX_DIR, name)
66
+ if os.path.isfile(path):
67
+ try:
68
+ for enc in ('utf-8', 'gbk'):
69
+ try:
70
+ with open(path, encoding=enc) as f:
71
+ d = json.load(f)
72
+ break
73
+ except (OSError, UnicodeDecodeError):
74
+ continue
75
+ except Exception:
76
+ pass
77
+ _CACHE[name] = d
78
+ return d
79
+
80
+
81
+ # 短而无意义的英文 token 黑名单 (避免子串误命中 'cs'/'fl'/'in' 这类噪声)
82
+ # 提到模块级: _match_keys code_total 共用一份
83
+ NOISE_KEYS = {
84
+ 'app', 'api', 'all', 'add', 'age', 'and', 'are', 'ars', 'ase', 'ask',
85
+ 'ate', 'aud', 'bar', 'big', 'btn', 'can', 'car', 'cas', 'cat', 'code',
86
+ 'con', 'cor', 'cs', 'cur', 'dae', 'dat', 'day', 'del', 'dep', 'des',
87
+ 'det', 'dim', 'div', 'doc', 'dos', 'ear', 'ecs', 'ema', 'end', 'ent',
88
+ 'err', 'eva', 'exe', 'exp', 'ext', 'fil', 'fix', 'fl', 'for', 'ge',
89
+ 'gen', 'get', 'has', 'her', 'his', 'ics', 'idx', 'imp', 'int', 'inv',
90
+ 'io', 'is', 'iso', 'ite', 'its', 'key', 'lab', 'lan', 'lat', 'let',
91
+ 'lin', 'lis', 'log', 'ma', 'map', 'max', 'min', 'mod', 'msg', 'new',
92
+ 'nil', 'not', 'now', 'num', 'obj', 'off', 'one', 'opt', 'ord', 'out',
93
+ 'ove', 'own', 'pag', 'par', 'pas', 'pay', 'pen', 'per', 'pos', 'pre',
94
+ 'pro', 'put', 'que', 'rec', 'red', 'ref', 'reg', 'rep', 'res', 'ret',
95
+ 'rev', 'row', 'run', 'sa', 'sel', 'set', 'sev', 'sie', 'sit', 'sor',
96
+ 'src', 'sta', 'sub', 'sum', 'sys', 'tab', 'tar', 'tes', 'tex', 'tim',
97
+ 'tmp', 'tok', 'tom', 'top', 'tot', 'tru', 'try', 'typ', 'udp', 'uni',
98
+ 'upd', 'url', 'use', 'usr', 'val', 'ver', 'vid', 'vio', 'vis', 'voi',
99
+ 'was', 'way', 'who', 'why', 'win', 'wri', 'xml', 'you', 'your', 'zone',
100
+ }
101
+
102
+
103
+ def _match_keys(query_lower, keys, max_hits=15, min_len=3):
104
+ """在 keys 里找被 query 包含的 (子串匹配), 返回命中列表 + 总数。
105
+ min_len: 短于这个长度的键忽略 (避免 'cs'/'fl'/'in' 这类噪声子串)。"""
106
+ hits = []
107
+ for k in keys:
108
+ kl = k.lower()
109
+ if len(kl) < min_len:
110
+ continue
111
+ if kl in NOISE_KEYS:
112
+ continue
113
+ if kl in query_lower:
114
+ hits.append(k)
115
+ if len(hits) >= max_hits:
116
+ break
117
+ return hits
118
+ for k in keys:
119
+ kl = k.lower()
120
+ if len(kl) < min_len:
121
+ continue
122
+ if kl in NOISE:
123
+ continue
124
+ if kl in query_lower:
125
+ hits.append(k)
126
+ if len(hits) >= max_hits:
127
+ break
128
+ return hits
129
+
130
+
131
+ def enrich(query):
132
+ """润色主函数。返回 dict:
133
+ {
134
+ 'is_business': bool, # 是否业务消息 (有命中才算)
135
+ 'cn_words': [...], # 中文分词出的英文搜索词
136
+ 'code_hits': [...], # 命中的代码符号 (样例)
137
+ 'code_total': int, # 代码命中总数
138
+ 'api_hits': [...], # 命中的 API
139
+ 'prd_hits': [...], # 命中的历史 PRD
140
+ 'elapsed_ms': float, # 耗时
141
+ 'polished': str, # 润色后的提示词 (人类可读)
142
+ }
143
+ """
144
+ t0 = time.perf_counter()
145
+ from foundation.integrations.terms import expand_chinese_query
146
+
147
+ # 1. 中文分词 → 英文搜索词
148
+ cn_words = list(dict.fromkeys(expand_chinese_query(query))) # 去重保序
149
+
150
+ # 2. 构造匹配串: 原句 + 扩展出的英文词, 一起拿去命中索引
151
+ match_str = query.lower()
152
+ for w in cn_words:
153
+ match_str += ' ' + w.lower()
154
+
155
+ # 3. 命中三类索引
156
+ code_idx = _load('code-keyword.json')
157
+ code_keys = list(code_idx.keys()) if isinstance(code_idx, dict) else []
158
+ code_hits = _match_keys(match_str, code_keys)
159
+
160
+ api_idx = _load('code-api.json')
161
+ api_keys = []
162
+ if isinstance(api_idx, dict):
163
+ api_keys = list(api_idx.keys())
164
+ api_hits = _match_keys(match_str, api_keys)
165
+
166
+ prd_idx = _load('prd-index.json')
167
+ prd_keys = []
168
+ if isinstance(prd_idx, dict):
169
+ prd_keys = list(prd_idx.keys())
170
+ prd_hits = _match_keys(match_str, prd_keys, max_hits=5)
171
+
172
+ # 4. 代码命中总数 (不限 max, 用于展示规模; 用与 _match_keys 一致的过滤)
173
+ code_total = 0
174
+ if code_keys:
175
+ code_total = sum(1 for k in code_keys
176
+ if len(k) >= 3 and k.lower() not in NOISE_KEYS
177
+ and k.lower() in match_str)
178
+
179
+ elapsed_ms = (time.perf_counter() - t0) * 1000
180
+ is_business = bool(code_hits or api_hits or prd_hits or cn_words)
181
+
182
+ # 5. 组装润色后提示词 (人类可读)
183
+ lines = []
184
+ if not is_business:
185
+ lines.append('(非业务消息,无需润色,直接放行)')
186
+ else:
187
+ if cn_words:
188
+ shown = ', '.join(cn_words[:8])
189
+ lines.append('业务词: ' + shown)
190
+ if code_total:
191
+ sample = ', '.join(code_hits[:8])
192
+ more = '' if code_total <= len(code_hits) else ' ...'
193
+ lines.append('相关代码符号: %d 处 (%s%s)' % (code_total, sample, more))
194
+ if api_hits:
195
+ lines.append('相关 API: %d 个 (%s)' % (len(api_hits), ', '.join(api_hits[:5])))
196
+ if prd_hits:
197
+ lines.append('历史 PRD: %s' % ', '.join(prd_hits[:5]))
198
+
199
+ polished = '\n'.join(lines)
200
+
201
+ return {
202
+ 'is_business': is_business,
203
+ 'cn_words': cn_words,
204
+ 'code_hits': code_hits,
205
+ 'code_total': code_total,
206
+ 'api_hits': api_hits,
207
+ 'prd_hits': prd_hits,
208
+ 'elapsed_ms': round(elapsed_ms, 2),
209
+ 'polished': polished,
210
+ }
211
+
212
+
213
+ def main():
214
+ args = sys.argv[1:]
215
+ if not args:
216
+ print(__doc__)
217
+ print('错误: 缺少查询参数。用法: enrich_prompt.py "你的问题"')
218
+ sys.exit(2)
219
+ query = ' '.join(args[:1]) if args[0] in ('--json',) else ' '.join(args)
220
+ # 处理 --json 标志
221
+ as_json = '--json' in args
222
+ query = query.replace('--json', '').strip()
223
+
224
+ result = enrich(query)
225
+ if as_json:
226
+ print(json.dumps(result, ensure_ascii=False))
227
+ return
228
+
229
+ # 人类可读输出
230
+ print('── 极速润色 (%.1fms) ──' % result['elapsed_ms'])
231
+ print(result['polished'])
232
+ if result['is_business']:
233
+ print('──────────────')
234
+ print('将以上下文继续。回复"改:xxx"调整,任意其它内容=接受。')
235
+
236
+
237
+ if __name__ == '__main__':
238
+ main()