@hupan56/wlkj 3.3.3 → 3.3.4

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 (35) hide show
  1. package/package.json +1 -1
  2. package/templates/qoder/scripts/capability/adapters/mcp.py +8 -1
  3. package/templates/qoder/scripts/capability/registry_mcp.py +9 -3
  4. package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +41 -5
  5. package/templates/qoder/scripts/capability/__pycache__/__init__.cpython-39.pyc +0 -0
  6. package/templates/qoder/scripts/capability/__pycache__/present_html.cpython-39.pyc +0 -0
  7. package/templates/qoder/scripts/capability/__pycache__/registry.cpython-39.pyc +0 -0
  8. package/templates/qoder/scripts/capability/__pycache__/registry_mcp.cpython-39.pyc +0 -0
  9. package/templates/qoder/scripts/capability/adapters/__pycache__/__init__.cpython-39.pyc +0 -0
  10. package/templates/qoder/scripts/capability/adapters/__pycache__/cli.cpython-39.pyc +0 -0
  11. package/templates/qoder/scripts/capability/adapters/__pycache__/mcp.cpython-39.pyc +0 -0
  12. package/templates/qoder/scripts/capability/adapters/__pycache__/qw.cpython-39.pyc +0 -0
  13. package/templates/qoder/scripts/capability/caps/__pycache__/__init__.cpython-39.pyc +0 -0
  14. package/templates/qoder/scripts/capability/caps/__pycache__/context.cpython-39.pyc +0 -0
  15. package/templates/qoder/scripts/capability/caps/__pycache__/cron.cpython-39.pyc +0 -0
  16. package/templates/qoder/scripts/capability/caps/__pycache__/identity.cpython-39.pyc +0 -0
  17. package/templates/qoder/scripts/capability/caps/__pycache__/memory.cpython-39.pyc +0 -0
  18. package/templates/qoder/scripts/capability/caps/__pycache__/notify.cpython-39.pyc +0 -0
  19. package/templates/qoder/scripts/capability/caps/__pycache__/present.cpython-39.pyc +0 -0
  20. package/templates/qoder/scripts/capability/caps/__pycache__/repo.cpython-39.pyc +0 -0
  21. package/templates/qoder/scripts/capability/caps/__pycache__/sandbox.cpython-39.pyc +0 -0
  22. package/templates/qoder/scripts/domain/__pycache__/__init__.cpython-39.pyc +0 -0
  23. package/templates/qoder/scripts/domain/integration/__pycache__/__init__.cpython-39.pyc +0 -0
  24. package/templates/qoder/scripts/domain/integration/__pycache__/return_to_platform.cpython-39.pyc +0 -0
  25. package/templates/qoder/scripts/domain/task/__pycache__/wlkj_panel.cpython-39.pyc +0 -0
  26. package/templates/qoder/scripts/foundation/__pycache__/__init__.cpython-39.pyc +0 -0
  27. package/templates/qoder/scripts/foundation/core/__pycache__/__init__.cpython-39.pyc +0 -0
  28. package/templates/qoder/scripts/foundation/core/__pycache__/paths.cpython-39.pyc +0 -0
  29. package/templates/qoder/scripts/protocol/__pycache__/__init__.cpython-39.pyc +0 -0
  30. package/templates/qoder/scripts/protocol/transports/__pycache__/__init__.cpython-39.pyc +0 -0
  31. package/templates/qoder/scripts/protocol/transports/__pycache__/base.cpython-39.pyc +0 -0
  32. package/templates/qoder/scripts/protocol/transports/__pycache__/cli.cpython-39.pyc +0 -0
  33. package/templates/qoder/scripts/protocol/transports/__pycache__/http.cpython-39.pyc +0 -0
  34. package/templates/qoder/scripts/protocol/transports/__pycache__/stdio.cpython-39.pyc +0 -0
  35. package/templates/qoder/scripts/validation/metrics/__pycache__/present_board.cpython-39.pyc +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hupan56/wlkj",
3
- "version": "3.3.3",
3
+ "version": "3.3.4",
4
4
  "description": "AI Product R&D Workflow - PRD/Prototype/Search/Task/Report",
5
5
  "bin": {
6
6
  "wlkj": "bin/cli.js"
@@ -132,6 +132,11 @@ class McpCap:
132
132
 
133
133
  def _cli_fallback(self, tool_name: str, args: dict) -> Optional[str]:
134
134
  """MCP 工具名 → wlkj.py 执行。无映射返回 None。"""
135
+ # ★ 递归守卫:search_code→kg search→search_index→call_remote→call→_cli_fallback 会无限套娃。
136
+ # 已在降级子进程内(_run_wlkj 设了 _WLKJ_IN_CLI_FALLBACK=1)则直接放弃降级,返回原始错误。
137
+ import os as _os
138
+ if _os.environ.get("_WLKJ_IN_CLI_FALLBACK"):
139
+ return None
135
140
  entry = self._TOOL_TO_WLKJ.get(tool_name)
136
141
  if entry is None:
137
142
  return None
@@ -183,10 +188,12 @@ class McpCap:
183
188
  repo = os.getcwd()
184
189
  wlkj = os.path.join(repo, ".qoder", "scripts", "orchestration", "wlkj.py")
185
190
  try:
191
+ # 递归守卫:子进程内 _WLKJ_IN_CLI_FALLBACK=1,其 McpCap 不再降级(否则套娃)
192
+ env = dict(os.environ, _WLKJ_IN_CLI_FALLBACK="1")
186
193
  r = subprocess.run(
187
194
  [sys.executable, wlkj, cmd] + args,
188
195
  capture_output=True, text=True, timeout=60,
189
- encoding="utf-8", errors="replace",
196
+ encoding="utf-8", errors="replace", env=env,
190
197
  )
191
198
  if r.returncode == 0:
192
199
  return r.stdout.strip()
@@ -73,16 +73,22 @@ SERVERS: dict[str, dict] = {
73
73
 
74
74
 
75
75
  def _mcp_config_path() -> Path:
76
- """定位 mcp_config.json(在仓库根/宿主下)。"""
76
+ """定位 mcp_config.json(在仓库根/宿主下)。
77
+
78
+ ★ switch_project.py 实际写入位置是 {repo}/.qoder/mcp_config.json(云模式连云 bind 后),
79
+ 必须优先查这里——否则读不到 token,transport 用空 token 调云 MCP 鉴权失败(历史 bug:
80
+ 引擎 search 全返回"MCP返回非JSON"+递归降级套娃)。老形态 repo/mcp_config.json 兼容。
81
+ """
77
82
  repo = _get_repo_root()
78
83
  # registry_mcp.py 在 .../scripts/capability/, mcp_config.json 在宿主根(.qoder)。
79
84
  for cand in [
80
- repo / "mcp_config.json",
85
+ repo / ".qoder" / "mcp_config.json", # ★ 云模式实际写入位置(switch_project)
86
+ repo / "mcp_config.json", # 老形态:仓库根
81
87
  repo / "registry_mcp_config.json",
82
88
  ]:
83
89
  if cand.is_file():
84
90
  return cand
85
- return repo / "mcp_config.json"
91
+ return repo / ".qoder" / "mcp_config.json"
86
92
 
87
93
 
88
94
  def _load_servers() -> dict[str, dict]:
@@ -278,6 +278,31 @@ def build_embeddings(batch_size=64):
278
278
  con.close()
279
279
 
280
280
 
281
+ def _cloud_rag_search(query, top_k=10):
282
+ """云优先语义搜索:调工作台 MCP rag_search(本地无 KG/embedding,全迁云)。
283
+
284
+ Returns:
285
+ [(entity_id, text, score), ...] 或 None(云不可用时返回 None,让调用方退本地)。
286
+ """
287
+ try:
288
+ from domain.kg.search._remote import call_remote
289
+ data = call_remote("rag_search", {"query": query, "top_k": top_k})
290
+ except Exception:
291
+ return None
292
+ items = data.get("items") or []
293
+ out = []
294
+ for it in items[:top_k]:
295
+ eid = it.get("entity_id") or it.get("id") or ""
296
+ text = it.get("text") or it.get("name") or ""
297
+ score = it.get("score")
298
+ try:
299
+ score = float(score) if score is not None else 0.0
300
+ except Exception:
301
+ score = 0.0
302
+ out.append((eid, text, score))
303
+ return out
304
+
305
+
281
306
  def semantic_search(query, top_k=10):
282
307
  """语义搜索: query→向量→余弦相似度→top_k 实体。
283
308
 
@@ -656,13 +681,24 @@ if __name__ == '__main__':
656
681
  n = build_embeddings()
657
682
  print('Built %d embeddings' % n)
658
683
 
659
- elif len(sys.argv) > 2 and sys.argv[1] == 'search':
660
- results = semantic_search(sys.argv[2])
684
+ elif (len(sys.argv) > 2 and sys.argv[1] == 'search') or \
685
+ (len(sys.argv) > 1 and sys.argv[1] not in ('--check', '--label', 'build-embeddings', '--status', '--backfill-cn')):
686
+ # 兼容两种姿势: `search <词>` 和裸词 `<词>`(wlkj.py semantic 保险异常 透传过来)。
687
+ # ★ 云优先:本地无 KG/embedding(全迁云),先调云 rag_search;云不可用才退本地 semantic_search。
688
+ query = sys.argv[2] if sys.argv[1] == 'search' else sys.argv[1]
689
+ results = _cloud_rag_search(query)
690
+ if results is None:
691
+ # 云不可用 → 退本地(开发期有本地 embedding 时仍可用)
692
+ results = semantic_search(query)
661
693
  if results:
662
- for eid, text, score in results:
663
- print(' %.3f %s' % (score, text[:70]))
694
+ for row in results:
695
+ if len(row) == 3:
696
+ eid, text, score = row
697
+ print(' %.3f %s' % (score, text[:70]))
698
+ else:
699
+ print(' %s' % row)
664
700
  else:
665
- print('(无结果或 embedding 未构建)')
701
+ print('(无结果或云 rag_search 不可用 + 本地 embedding 未构建)')
666
702
 
667
703
  elif len(sys.argv) > 1 and sys.argv[1] == '--status':
668
704
  st = embedding_status()