@hupan56/wlkj 2.6.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/bin/cli.js +261 -11
  2. package/package.json +1 -1
  3. package/templates/qoder/agents/insight-planning.md +67 -0
  4. package/templates/qoder/agents/insight-research.md +61 -0
  5. package/templates/qoder/agents/prd-reference.md +8 -2
  6. package/templates/qoder/commands/optional/wl-insight.md +275 -0
  7. package/templates/qoder/commands/{wl-report.md → optional/wl-report.md} +13 -5
  8. package/templates/qoder/commands/{wl-spec.md → optional/wl-spec.md} +1 -1
  9. package/templates/qoder/commands/{wl-status.md → optional/wl-status.md} +28 -2
  10. package/templates/qoder/commands/wl-code.md +10 -2
  11. package/templates/qoder/commands/wl-commit.md +1 -1
  12. package/templates/qoder/commands/wl-design-draw.md +78 -0
  13. package/templates/qoder/commands/wl-design-scan.md +108 -0
  14. package/templates/qoder/commands/wl-design-spec.md +154 -0
  15. package/templates/qoder/commands/wl-design.md +32 -0
  16. package/templates/qoder/commands/wl-init.md +24 -3
  17. package/templates/qoder/commands/wl-prd-full.md +226 -0
  18. package/templates/qoder/commands/wl-prd-quick.md +134 -0
  19. package/templates/qoder/commands/wl-prd-review.md +104 -0
  20. package/templates/qoder/commands/wl-prd.md +17 -311
  21. package/templates/qoder/commands/wl-search.md +66 -30
  22. package/templates/qoder/commands/wl-task.md +290 -59
  23. package/templates/qoder/commands/wl-test.md +92 -24
  24. package/templates/qoder/config.yaml +51 -15
  25. package/templates/qoder/hooks/inject-workflow-state.py +2 -2
  26. package/templates/qoder/hooks/session-start.py +82 -51
  27. package/templates/qoder/rules/wl-pipeline.md +216 -105
  28. package/templates/qoder/scripts/__pycache__/search_index.cpython-39.pyc +0 -0
  29. package/templates/qoder/scripts/archive_prd.py +377 -0
  30. package/templates/qoder/scripts/autotest.py +1715 -0
  31. package/templates/qoder/scripts/autotest_batch.py +224 -0
  32. package/templates/qoder/scripts/autotest_run.py +297 -0
  33. package/templates/qoder/scripts/benchmark.py +210 -209
  34. package/templates/qoder/scripts/build_style_index.py +444 -4
  35. package/templates/qoder/scripts/check_carriers.py +238 -0
  36. package/templates/qoder/scripts/check_mcp.py +298 -0
  37. package/templates/qoder/scripts/check_qoderwork_consistency.py +166 -0
  38. package/templates/qoder/scripts/common/events.py +46 -0
  39. package/templates/qoder/scripts/common/extract.py +419 -0
  40. package/templates/qoder/scripts/common/graph_traverse.py +533 -0
  41. package/templates/qoder/scripts/common/paths.py +89 -0
  42. package/templates/qoder/scripts/common/pip_install.py +144 -0
  43. package/templates/qoder/scripts/common/platform_guard.py +61 -0
  44. package/templates/qoder/scripts/common/search_engine.py +205 -205
  45. package/templates/qoder/scripts/common/terms.py +57 -0
  46. package/templates/qoder/scripts/common/ts_extract.py +536 -0
  47. package/templates/qoder/scripts/context_pack.py +73 -13
  48. package/templates/qoder/scripts/enrich_prompt.py +226 -0
  49. package/templates/qoder/scripts/eval_prd.py +318 -231
  50. package/templates/qoder/scripts/export.py +487 -487
  51. package/templates/qoder/scripts/extract_api_params.py +246 -0
  52. package/templates/qoder/scripts/extract_routes.py +54 -0
  53. package/templates/qoder/scripts/extract_routes_tree.py +78 -0
  54. package/templates/qoder/scripts/fill_prototype.py +707 -0
  55. package/templates/qoder/scripts/gen_design_doc.py +394 -0
  56. package/templates/qoder/scripts/git_sync.py +27 -15
  57. package/templates/qoder/scripts/init_doctor.py +292 -40
  58. package/templates/qoder/scripts/install_qoderwork.py +366 -9
  59. package/templates/qoder/scripts/kg.py +708 -0
  60. package/templates/qoder/scripts/kg_auto_login.py +196 -0
  61. package/templates/qoder/scripts/kg_build.py +612 -0
  62. package/templates/qoder/scripts/kg_build_db.py +327 -0
  63. package/templates/qoder/scripts/kg_duckdb.py +549 -0
  64. package/templates/qoder/scripts/kg_incremental.py +393 -0
  65. package/templates/qoder/scripts/kg_link_db.py +224 -0
  66. package/templates/qoder/scripts/kg_mcp_server.py +801 -0
  67. package/templates/qoder/scripts/kg_semantic.py +150 -0
  68. package/templates/qoder/scripts/kg_test_runner.py +241 -0
  69. package/templates/qoder/scripts/lanhu_stdio_wrapper.py +119 -0
  70. package/templates/qoder/scripts/learn.py +118 -39
  71. package/templates/qoder/scripts/learn_aggregate.py +201 -0
  72. package/templates/qoder/scripts/mcp_launcher.py +359 -0
  73. package/templates/qoder/scripts/mysql_mcp_server.py +396 -0
  74. package/templates/qoder/scripts/repo_root.py +106 -0
  75. package/templates/qoder/scripts/role.py +12 -0
  76. package/templates/qoder/scripts/run_weekly_update.bat +5 -0
  77. package/templates/qoder/scripts/run_weekly_update.sh +5 -0
  78. package/templates/qoder/scripts/search_index.py +307 -60
  79. package/templates/qoder/scripts/secure-ls.js +5640 -0
  80. package/templates/qoder/scripts/setup.py +706 -641
  81. package/templates/qoder/scripts/setup_lanhu.py +963 -0
  82. package/templates/qoder/scripts/status.py +250 -11
  83. package/templates/qoder/scripts/sync_carriers.py +259 -0
  84. package/templates/qoder/scripts/syncgate.py +2 -2
  85. package/templates/qoder/scripts/task.py +75 -0
  86. package/templates/qoder/scripts/team_sync.py +60 -4
  87. package/templates/qoder/scripts/workspace_init.py +1 -1
  88. package/templates/qoder/skills/design-import/SKILL.md +226 -0
  89. package/templates/qoder/skills/design-import/figma-workflow.md +81 -0
  90. package/templates/qoder/skills/design-review/SKILL.md +82 -25
  91. package/templates/qoder/skills/prd-generator/SKILL.md +184 -60
  92. package/templates/qoder/skills/prd-review/SKILL.md +18 -1
  93. package/templates/qoder/skills/prompt-enrich/SKILL.md +90 -0
  94. package/templates/qoder/skills/prototype-generator/SKILL.md +256 -141
  95. package/templates/qoder/skills/prototype-generator/SKILL.md.zcode-79180-2af4721f-f9a6-412c-88db-c0af680d211b.tmp +0 -0
  96. package/templates/qoder/skills/spec-coder/SKILL.md +18 -1
  97. package/templates/qoder/skills/spec-generator/SKILL.md +18 -1
  98. package/templates/qoder/skills/test-generator/SKILL.md +15 -2
  99. package/templates/qoder/skills/wl-code/SKILL.md +55 -36
  100. package/templates/qoder/skills/wl-commit/SKILL.md +89 -76
  101. package/templates/qoder/skills/wl-design/SKILL.md +55 -0
  102. package/templates/qoder/skills/wl-init/SKILL.md +76 -67
  103. package/templates/qoder/skills/wl-insight/SKILL.md +201 -81
  104. package/templates/qoder/skills/wl-prd-full/SKILL.md +69 -0
  105. package/templates/qoder/skills/wl-prd-quick/SKILL.md +49 -0
  106. package/templates/qoder/skills/wl-prd-review/SKILL.md +34 -0
  107. package/templates/qoder/skills/wl-report/SKILL.md +131 -107
  108. package/templates/qoder/skills/wl-search/SKILL.md +141 -75
  109. package/templates/qoder/skills/wl-spec/SKILL.md +49 -39
  110. package/templates/qoder/skills/wl-status/SKILL.md +83 -61
  111. package/templates/qoder/skills/wl-task/SKILL.md +132 -58
  112. package/templates/qoder/skills/wl-test/SKILL.md +406 -40
  113. package/templates/qoder/templates/prototype-app.html +13 -8
  114. package/templates/qoder/templates/prototype-web.html +376 -93
  115. package/templates/root/AGENTS.md +89 -34
  116. package/templates/root/requirements.txt +21 -0
  117. package/templates/root//344/275/277/347/224/250/350/257/264/346/230/216.md +259 -259
  118. package/templates/root//346/226/260/346/211/213/346/214/207/345/215/227.md +186 -186
  119. package/templates/qoder/agents/prd-planning.md +0 -57
  120. package/templates/qoder/agents/prd-research.md +0 -34
  121. package/templates/qoder/commands/wl-insight.md +0 -51
  122. package/templates/qoder/scripts/__pycache__/init_doctor.cpython-39.pyc +0 -0
  123. package/templates/qoder/scripts/__pycache__/setup.cpython-39.pyc +0 -0
  124. package/templates/qoder/scripts/common/__pycache__/developer.cpython-39.pyc +0 -0
  125. package/templates/qoder/skills/wl-prd/SKILL.md +0 -92
@@ -0,0 +1,196 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ 全自动登录: 获取验证码 → ddddocr识别 → 页面JS加密提交 → 保存token
4
+ 登录态保存到 auth-state.json, 后续测试复用(无需再次识别验证码)。
5
+ """
6
+ import base64
7
+ import json
8
+ import os
9
+ import sys
10
+ import requests
11
+ import ddddocr
12
+
13
+ BASE_URL = 'https://icsqas.inforecloud.com'
14
+ API_PREFIX = '/test-api'
15
+ USERNAME = '15888888887'
16
+ PASSWORD = 'admin123'
17
+ CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
18
+
19
+ # RSA公钥 (从 .env.production)
20
+ RSA_PUBLIC_KEY_B64 = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDN/EkuOg1gq/t2/PUI8GpcJCsCFQgHkSHUEdk7ZPrEQYd8IM1hFkHmDJrCOQ+qUPqKHG9a5BAI44yE6FuPI9Vvqu2ZrCww/zryR7A+2n5jaKIG2rJG9KHDzT5mAVOJrlhBf8L2i7wZc8eWrNg0md0BlwEowQyVEEj9oIBlw/nqTwIDAQAB'
21
+
22
+ # 保存路径
23
+ SCRIPTS_DIR = os.path.dirname(os.path.abspath(__file__))
24
+
25
+
26
+ def _read_developer():
27
+ """读 .qoder/.developer 拿当前开发者名, 用于身份隔离。
28
+ 多人共用 workspace 时, auth-state 必须按开发者分目录, 否则会串登录态。
29
+ 没有身份 → 抛异常 (绝不 fallback 到 hupan/default, 防串号)。"""
30
+ dev_file = os.path.join(SCRIPTS_DIR, '..', '..', '.qoder', '.developer')
31
+ if os.path.isfile(dev_file):
32
+ for ln in open(dev_file, encoding='utf-8'):
33
+ if ln.strip().startswith('name='):
34
+ return ln.strip().split('=', 1)[1].strip()
35
+ raise RuntimeError(
36
+ '未检测到开发者身份(.qoder/.developer)。请先运行 /wl-init 注册身份。'
37
+ ' (auth-state 按开发者分目录, 没身份无法隔离 → 拒绝执行防串号)'
38
+ )
39
+
40
+
41
+ STATE_FILE = os.path.join(SCRIPTS_DIR, '..', '..', 'workspace', 'members',
42
+ _read_developer(), 'auth-state.json')
43
+
44
+ out = []
45
+ def log(s=''):
46
+ out.append(s)
47
+ print(s)
48
+
49
+
50
+ def get_captcha():
51
+ """获取验证码图片 + uuid"""
52
+ resp = requests.get(BASE_URL + API_PREFIX + '/auth/code', timeout=10)
53
+ data = resp.json().get('data', {})
54
+ return data.get('uuid'), data.get('img'), data.get('captchaEnabled', False)
55
+
56
+
57
+ def recognize_captcha(img_b64):
58
+ """用 ddddocr 识别验证码图片, 并解析数学题(ICS 是 a op b = ? 形式).
59
+ 返回算出的答案字符串; 解析失败返回 None."""
60
+ import re as _re
61
+ ocr = ddddocr.DdddOcr(show_ad=False)
62
+ img_bytes = base64.b64decode(img_b64)
63
+ raw = ocr.classification(img_bytes)
64
+ # 规范化运算符 (x/X/× → *, ÷ → /), 去掉 = ? 尾部
65
+ expr = raw.replace('x', '*').replace('X', '*').replace('×', '*').replace('÷', '/')
66
+ expr = expr.rstrip('=??').strip()
67
+ m = _re.match(r'^\s*(\d+)\s*([+\-*/])\s*(\d+)\s*$', expr)
68
+ if not m:
69
+ return None
70
+ a, op, b = int(m.group(1)), m.group(2), int(m.group(3))
71
+ if op == '+':
72
+ ans = a + b
73
+ elif op == '-':
74
+ ans = a - b
75
+ elif op == '*':
76
+ ans = a * b
77
+ elif op == '/':
78
+ ans = a // b if b else None
79
+ else:
80
+ return None
81
+ return str(ans) if ans is not None else None
82
+
83
+
84
+ def encrypt_login(username, password, code, uuid):
85
+ """用 RSA+AES 加密登录请求 (复现前端加密逻辑)。
86
+ 使用 cryptography 库 (替代 pycryptodome)。"""
87
+ import os as _os
88
+ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
89
+ from cryptography.hazmat.primitives.padding import PKCS7
90
+ from cryptography.hazmat.primitives.asymmetric import padding as asym_padding
91
+ from cryptography.hazmat.primitives.serialization import load_der_public_key
92
+
93
+ # 1. 生成随机 AES 密钥 (前端用 randomUUID = 32 hex chars)
94
+ aes_key = _os.urandom(16).hex().encode('utf-8') # 32 bytes
95
+
96
+ # 2. AES-ECB-PKCS7 加密请求体
97
+ login_body = json.dumps({
98
+ 'username': username,
99
+ 'password': password,
100
+ 'grantType': 'password',
101
+ 'tenantId': '000000',
102
+ 'clientId': CLIENT_ID,
103
+ 'code': code,
104
+ 'uuid': uuid,
105
+ }, ensure_ascii=False).encode('utf-8')
106
+
107
+ padder = PKCS7(128).padder()
108
+ padded = padder.update(login_body) + padder.finalize()
109
+ cipher = Cipher(algorithms.AES(aes_key), modes.ECB())
110
+ encryptor = cipher.encryptor()
111
+ encrypted_body = base64.b64encode(encryptor.update(padded) + encryptor.finalize()).decode()
112
+
113
+ # 3. RSA 加密 AES 密钥 (前端: encrypt(encryptBase64(aesKey)))
114
+ aes_key_b64 = base64.b64encode(aes_key).decode()
115
+ pub_key = load_der_public_key(base64.b64decode(RSA_PUBLIC_KEY_B64))
116
+ encrypted_key_bytes = pub_key.encrypt(aes_key_b64.encode('utf-8'), asym_padding.PKCS1v15())
117
+ encrypted_key = base64.b64encode(encrypted_key_bytes).decode()
118
+
119
+ return encrypted_body, encrypted_key
120
+
121
+
122
+ def login():
123
+ """全自动登录流程"""
124
+ log('=== 全自动登录 ===')
125
+
126
+ # 1. 获取验证码
127
+ uuid, img_b64, captcha_enabled = get_captcha()
128
+ log('验证码: enabled=%s, uuid=%s' % (captcha_enabled, uuid[:8] if uuid else 'N/A'))
129
+
130
+ if not captcha_enabled:
131
+ log('验证码未开启, 直接登录')
132
+ code = ''
133
+ uuid = ''
134
+ else:
135
+ # 2. OCR 识别 + 数学题解析
136
+ code = recognize_captcha(img_b64)
137
+ log('OCR识别验证码: %s' % code)
138
+ if code is None:
139
+ # ddddocr 没读对(数学题识别不稳定), 本次放弃, 让外层重试
140
+ log('验证码识别失败(数学题未解析), 重试')
141
+ return None
142
+
143
+ # 3. 加密 + 登录
144
+ try:
145
+ encrypted_body, encrypted_key = encrypt_login(USERNAME, PASSWORD, code, uuid)
146
+ log('加密完成, 发送登录请求...')
147
+
148
+ resp = requests.post(
149
+ BASE_URL + API_PREFIX + '/auth/login',
150
+ data=encrypted_body,
151
+ headers={
152
+ 'Content-Type': 'application/json',
153
+ 'encrypt-key': encrypted_key,
154
+ },
155
+ timeout=10,
156
+ )
157
+ result = resp.json()
158
+ log('登录响应: code=%s, msg=%s' % (result.get('code'), result.get('msg')))
159
+
160
+ if result.get('code') == 200 and result.get('data', {}).get('access_token'):
161
+ token = result['data']['access_token']
162
+ log('✓ 登录成功! token=%s...' % token[:20])
163
+
164
+ # 保存登录态
165
+ os.makedirs(os.path.dirname(STATE_FILE), exist_ok=True)
166
+ with open(STATE_FILE, 'w', encoding='utf-8') as f:
167
+ json.dump({
168
+ 'access_token': token,
169
+ 'base_url': BASE_URL,
170
+ 'api_prefix': API_PREFIX,
171
+ 'saved_at': __import__('datetime').datetime.now().isoformat(),
172
+ }, f, indent=2)
173
+ log('登录态已保存: %s' % STATE_FILE)
174
+ return token
175
+ else:
176
+ log('✗ 登录失败: %s' % json.dumps(result, ensure_ascii=False)[:200])
177
+ log(' 可能验证码识别错误, 重试...')
178
+ return None
179
+ except Exception as e:
180
+ log('登录异常: %s' % str(e))
181
+ return None
182
+
183
+
184
+ if __name__ == '__main__':
185
+ # 数学题验证码识别不稳定, 多重试几次 (实测 ~30% 一次读对, 20 次基本必中)
186
+ import time as _time
187
+ for attempt in range(20):
188
+ log('--- 尝试 %d ---' % (attempt + 1))
189
+ token = login()
190
+ if token:
191
+ break
192
+ _time.sleep(0.3)
193
+ else:
194
+ log('20次尝试均失败, 请检查账号/密码/验证码/网络')
195
+
196
+ open(os.path.join(SCRIPTS_DIR, '_login_log.txt'), 'w', encoding='utf-8').write('\n'.join(out))