@comate/zulu 1.4.0-beta.2 → 1.4.0-beta.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 (206) hide show
  1. package/comate-engine/assets/skills/auto-commit/SKILL.md +241 -0
  2. package/comate-engine/assets/skills/auto-commit/references/data_structures.md +183 -0
  3. package/comate-engine/assets/skills/auto-commit/references/interaction_instruction.md +220 -0
  4. package/comate-engine/assets/skills/auto-commit/references/issue_type_mapping.json +19 -0
  5. package/comate-engine/assets/skills/auto-commit/references/query_reference.md +176 -0
  6. package/comate-engine/assets/skills/auto-commit/scripts/build_git_commit_payload.py +195 -0
  7. package/comate-engine/assets/skills/auto-commit/scripts/build_icafe_cards_payload.py +80 -0
  8. package/comate-engine/assets/skills/auto-commit/scripts/cache_manager.py +69 -0
  9. package/comate-engine/assets/skills/auto-commit/scripts/create_card_cli.py +67 -0
  10. package/comate-engine/assets/skills/auto-commit/scripts/git_diff_cli.py +201 -0
  11. package/comate-engine/assets/skills/auto-commit/scripts/git_utils.py +230 -0
  12. package/comate-engine/assets/skills/auto-commit/scripts/icafe/__init__.py +66 -0
  13. package/comate-engine/assets/skills/auto-commit/scripts/icafe/client.py +473 -0
  14. package/comate-engine/assets/skills/auto-commit/scripts/icafe/farseer.py +52 -0
  15. package/comate-engine/assets/skills/auto-commit/scripts/icafe/matching.py +784 -0
  16. package/comate-engine/assets/skills/auto-commit/scripts/logger.py +32 -0
  17. package/comate-engine/assets/skills/auto-commit/scripts/match_card_cli.py +41 -0
  18. package/comate-engine/assets/skills/auto-commit/scripts/payload_validators.py +309 -0
  19. package/comate-engine/assets/skills/auto-commit/scripts/recognize_card_cli.py +63 -0
  20. package/comate-engine/assets/skills/{automation-browser-comate → automation-browser}/SKILL.md +1 -0
  21. package/comate-engine/assets/skills/{cnap-comate → cnap}/SKILL.md +1 -0
  22. package/comate-engine/assets/skills/code-review/SKILL.md +202 -0
  23. package/comate-engine/assets/skills/code-review/agents/correctness-reviewer.md +62 -0
  24. package/comate-engine/assets/skills/code-review/agents/custom-reviewer.md +53 -0
  25. package/comate-engine/assets/skills/code-review/agents/meta-reviewer.md +84 -0
  26. package/comate-engine/assets/skills/code-review/agents/reliability-reviewer.md +72 -0
  27. package/comate-engine/assets/skills/code-review/agents/reuse-reviewer.md +101 -0
  28. package/comate-engine/assets/skills/code-review/agents/style-reviewer.md +65 -0
  29. package/comate-engine/assets/skills/code-review/evals/SKILL.md +334 -0
  30. package/comate-engine/assets/skills/code-review/evals/agents/gt-generator.md +76 -0
  31. package/comate-engine/assets/skills/code-review/evals/agents/miner.md +87 -0
  32. package/comate-engine/assets/skills/code-review/evals/agents/score-judge.md +168 -0
  33. package/comate-engine/assets/skills/code-review/evals/references/cli-query-template.md +114 -0
  34. package/comate-engine/assets/skills/code-review/evals/references/gt-schema.md +77 -0
  35. package/comate-engine/assets/skills/code-review/references/custom-rules/RULE_TEMPLATE.md +141 -0
  36. package/comate-engine/assets/skills/code-review/references/dispatch-template.md +142 -0
  37. package/comate-engine/assets/skills/code-review/references/output-schema.md +197 -0
  38. package/comate-engine/assets/skills/code-review/references/report-format.md +41 -0
  39. package/comate-engine/assets/skills/code-review/references/rules/Go/GO_AUTH_RULES.md +29 -0
  40. package/comate-engine/assets/skills/code-review/references/rules/Go/GO_CORRECTNESS_RULES.md +111 -0
  41. package/comate-engine/assets/skills/code-review/references/rules/Go/GO_RESOURCE_CONCURRENCY_RULES.md +190 -0
  42. package/comate-engine/assets/skills/code-review/references/rules/Go/GO_STYLE_RULES.md +354 -0
  43. package/comate-engine/assets/skills/code-review/references/rules/Java/JAVA_AUTH_RULES.md +34 -0
  44. package/comate-engine/assets/skills/code-review/references/rules/Java/JAVA_CORRECTNESS_RULES.md +207 -0
  45. package/comate-engine/assets/skills/code-review/references/rules/Java/JAVA_RESOURCE_CONCURRENCY_RULES.md +220 -0
  46. package/comate-engine/assets/skills/code-review/references/rules/Java/JAVA_STYLE_RULES.md +306 -0
  47. package/comate-engine/assets/skills/code-review/references/rules/Js/JS_AUTH_RULES.md +48 -0
  48. package/comate-engine/assets/skills/code-review/references/rules/Js/JS_CORRECTNESS_RULES.md +364 -0
  49. package/comate-engine/assets/skills/code-review/references/rules/Js/JS_RESOURCE_CONCURRENCY_RULES.md +180 -0
  50. package/comate-engine/assets/skills/code-review/references/rules/Js/JS_STYLE_RULES.md +350 -0
  51. package/comate-engine/assets/skills/code-review/references/rules/Python/PYTHON_AUTH_RULES.md +38 -0
  52. package/comate-engine/assets/skills/code-review/references/rules/Python/PYTHON_CORRECTNESS_RULES.md +255 -0
  53. package/comate-engine/assets/skills/code-review/references/rules/Python/PYTHON_RESOURCE_CONCURRENCY_RULES.md +180 -0
  54. package/comate-engine/assets/skills/code-review/references/rules/Python/PYTHON_STYLE_RULES.md +195 -0
  55. package/comate-engine/assets/skills/code-review/references/telemetry.md +27 -0
  56. package/comate-engine/assets/skills/{code-security-comate → code-security}/SKILL.md +1 -0
  57. package/comate-engine/assets/skills/{comate-docs-comate → comate-docs}/SKILL.md +1 -1
  58. package/comate-engine/assets/skills/create-automation-tasks-comate/SKILL.md +300 -0
  59. package/comate-engine/assets/skills/create-automation-tasks-comate/references/backend_dev.md +109 -0
  60. package/comate-engine/assets/skills/create-automation-tasks-comate/references/env_setup.md +130 -0
  61. package/comate-engine/assets/skills/create-automation-tasks-comate/references/frontend_dev.md +74 -0
  62. package/comate-engine/assets/skills/create-automation-tasks-comate/references/git_operations.md +88 -0
  63. package/comate-engine/assets/skills/create-automation-tasks-comate/references/long_running_task.md +96 -0
  64. package/comate-engine/assets/skills/create-automation-tasks-comate/references/testing_strategy.md +94 -0
  65. package/comate-engine/assets/skills/create-automation-tasks-comate/scripts/check_config.py +397 -0
  66. package/comate-engine/assets/skills/{create-image-comate → create-image}/SKILL.md +14 -9
  67. package/comate-engine/assets/skills/{create-rule-comate → create-rule}/SKILL.md +1 -0
  68. package/comate-engine/assets/skills/{create-skill-comate → create-skill}/SKILL.md +2 -3
  69. package/comate-engine/assets/skills/{figma2code-comate → figma2code}/SKILL.md +1 -0
  70. package/comate-engine/assets/skills/{get-ugate-token-comate → get-ugate-token}/SKILL.md +97 -13
  71. package/comate-engine/assets/skills/get-ugate-token/getUgateToken.py +244 -0
  72. package/comate-engine/assets/skills/{icafe-comate → icafe}/SKILL.md +1 -13
  73. package/comate-engine/assets/skills/{icode-comate → icode}/SKILL.md +1 -0
  74. package/comate-engine/fallbackServer.js +1 -1
  75. package/comate-engine/node_modules/@baidu/comate-browser-use/dist/launch-chrome/index.js +1 -1
  76. package/comate-engine/node_modules/@baidu/comate-browser-use/package.json +5 -5
  77. package/comate-engine/node_modules/@comate/plugin-shared-internals/dist/index.js +3 -3
  78. package/comate-engine/package.json +1 -1
  79. package/comate-engine/server.js +137 -77
  80. package/dist/bundle/index.js +20 -9
  81. package/package.json +1 -1
  82. package/comate-engine/assets/skills/get-ugate-token-comate/getUgateToken.py +0 -150
  83. /package/comate-engine/assets/skills/{cnap-comate → cnap}/references/cases.md +0 -0
  84. /package/comate-engine/assets/skills/{cnap-comate → cnap}/references/deploy-troubleshoot.md +0 -0
  85. /package/comate-engine/assets/skills/{cnap-comate → cnap}/references/install.md +0 -0
  86. /package/comate-engine/assets/skills/{cnap-comate → cnap}/references/kubectl.md +0 -0
  87. /package/comate-engine/assets/skills/{cnap-comate → cnap}/references/login.md +0 -0
  88. /package/comate-engine/assets/skills/{cnap-comate → cnap}/references/oncall.md +0 -0
  89. /package/comate-engine/assets/skills/{cnap-comate → cnap}/scripts/install_cnap_cli.sh +0 -0
  90. /package/comate-engine/assets/skills/{code-security-comate → code-security}/references/credential_hosting.md +0 -0
  91. /package/comate-engine/assets/skills/{code-security-comate → code-security}/references/vul_repair-go_sql_injection.md +0 -0
  92. /package/comate-engine/assets/skills/{code-security-comate → code-security}/references/vul_repair-java_sql_injection.md +0 -0
  93. /package/comate-engine/assets/skills/{code-security-comate → code-security}/references/vul_repair-php_sql_injection.md +0 -0
  94. /package/comate-engine/assets/skills/{code-security-comate → code-security}/references/vul_repair-python_sql_injection.md +0 -0
  95. /package/comate-engine/assets/skills/{code-security-comate → code-security}/references/vul_repair_sensitive.md +0 -0
  96. /package/comate-engine/assets/skills/{code-security-comate → code-security}/scripts/credential_hosting.py +0 -0
  97. /package/comate-engine/assets/skills/{code-security-comate → code-security}/scripts/credential_poll.py +0 -0
  98. /package/comate-engine/assets/skills/{code-security-comate → code-security}/scripts/http_client.py +0 -0
  99. /package/comate-engine/assets/skills/{code-security-comate → code-security}/scripts/parse_scan_result.py +0 -0
  100. /package/comate-engine/assets/skills/{code-security-comate → code-security}/scripts/repair_vulnerability.py +0 -0
  101. /package/comate-engine/assets/skills/{code-security-comate → code-security}/scripts/report_chat.py +0 -0
  102. /package/comate-engine/assets/skills/{code-security-comate → code-security}/scripts/scan_vulnerability.py +0 -0
  103. /package/comate-engine/assets/skills/{code-security-comate → code-security}/scripts/utils.py +0 -0
  104. /package/comate-engine/assets/skills/{comate-docs-comate → comate-docs}/references/doc-map-extended.md +0 -0
  105. /package/comate-engine/assets/skills/{comate-docs-comate → comate-docs}/references/models-and-billing.md +0 -0
  106. /package/comate-engine/assets/skills/{comate-docs-comate → comate-docs}/references/product-overview.md +0 -0
  107. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/LICENSE.txt +0 -0
  108. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/agents/analyzer.md +0 -0
  109. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/agents/comparator.md +0 -0
  110. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/agents/grader.md +0 -0
  111. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/assets/eval_review.html +0 -0
  112. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/eval-viewer/generate_review.py +0 -0
  113. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/eval-viewer/viewer.html +0 -0
  114. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/references/schemas.md +0 -0
  115. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/scripts/__init__.py +0 -0
  116. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  117. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/scripts/__pycache__/aggregate_benchmark.cpython-311.pyc +0 -0
  118. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/scripts/aggregate_benchmark.py +0 -0
  119. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/scripts/generate_report.py +0 -0
  120. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/scripts/package_skill.py +0 -0
  121. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/scripts/quick_validate.py +0 -0
  122. /package/comate-engine/assets/skills/{create-skill-comate → create-skill}/scripts/utils.py +0 -0
  123. /package/comate-engine/assets/skills/{create-subagent-comate → create-subagent}/SKILL.md +0 -0
  124. /package/comate-engine/assets/skills/{figma2code-comate → figma2code}/references/codeConnect.md +0 -0
  125. /package/comate-engine/assets/skills/{figma2code-comate → figma2code}/references/designToken.md +0 -0
  126. /package/comate-engine/assets/skills/{figma2code-comate → figma2code}/references/image2design.md +0 -0
  127. /package/comate-engine/assets/skills/{find-skills-comate → find-skills}/SKILL.md +0 -0
  128. /package/comate-engine/assets/skills/{find-skills-comate → find-skills}/scripts/fetch_skills.py +0 -0
  129. /package/comate-engine/assets/skills/{find-skills-comate → find-skills}/scripts/get_download_url.py +0 -0
  130. /package/comate-engine/assets/skills/{find-skills-comate → find-skills}/scripts/install_skill.py +0 -0
  131. /package/comate-engine/assets/skills/{find-skills-comate → find-skills}/scripts/preview_skill.py +0 -0
  132. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/ai-workflows.md +0 -0
  133. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/commands.md +0 -0
  134. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/error-handling.md +0 -0
  135. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/git-auto-bindcard-workflow.md +0 -0
  136. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/git-bindcard-workflow.md +0 -0
  137. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/iql-syntax.md +0 -0
  138. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/platform-concepts.md +0 -0
  139. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/smart-create-workflow.md +0 -0
  140. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/smart-find-workflow.md +0 -0
  141. /package/comate-engine/assets/skills/{icafe-comate → icafe}/references/smart-update-workflow.md +0 -0
  142. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/add_reviewers.md +0 -0
  143. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/build_fetch_command.md +0 -0
  144. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/check_repo_permission.md +0 -0
  145. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/create_branch.md +0 -0
  146. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/create_draft_comment.md +0 -0
  147. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_ai_cr_result.md +0 -0
  148. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_ai_review.md +0 -0
  149. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_diff_content.md +0 -0
  150. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_diff_file.md +0 -0
  151. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_machine_check.md +0 -0
  152. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_my_reviews.md +0 -0
  153. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_person_commit.md +0 -0
  154. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_person_repo.md +0 -0
  155. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_repo_branch.md +0 -0
  156. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_repo_config.md +0 -0
  157. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_repo_members.md +0 -0
  158. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_repo_reviews.md +0 -0
  159. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_review_comments.md +0 -0
  160. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_review_info.md +0 -0
  161. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/get_submit_settings.md +0 -0
  162. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/icode-api.md +0 -0
  163. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/publish_comments.md +0 -0
  164. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/set_review_score.md +0 -0
  165. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/start_ai_review.md +0 -0
  166. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/submit_review.md +0 -0
  167. /package/comate-engine/assets/skills/{icode-comate → icode}/references/api/trigger_ai_cr.md +0 -0
  168. /package/comate-engine/assets/skills/{icode-comate → icode}/references/feature/add-reviewer.md +0 -0
  169. /package/comate-engine/assets/skills/{icode-comate → icode}/references/feature/fix-machine-check.md +0 -0
  170. /package/comate-engine/assets/skills/{icode-comate → icode}/references/feature/merge-cr.md +0 -0
  171. /package/comate-engine/assets/skills/{icode-comate → icode}/references/feature/ssh-setup.md +0 -0
  172. /package/comate-engine/assets/skills/{icode-comate → icode}/references/feature/submit-acr.md +0 -0
  173. /package/comate-engine/assets/skills/{icode-comate → icode}/references/feature/submit-cr.md +0 -0
  174. /package/comate-engine/assets/skills/{icode-comate → icode}/references/git/clone.md +0 -0
  175. /package/comate-engine/assets/skills/{icode-comate → icode}/references/git/icode-git.md +0 -0
  176. /package/comate-engine/assets/skills/{icode-comate → icode}/references/git/push.md +0 -0
  177. /package/comate-engine/assets/skills/{icode-comate → icode}/references/git/push_cr.md +0 -0
  178. /package/comate-engine/assets/skills/{icode-comate → icode}/references/install.md +0 -0
  179. /package/comate-engine/assets/skills/{icode-comate → icode}/references/login.md +0 -0
  180. /package/comate-engine/assets/skills/{icode-comate → icode}/scripts/add-reviewer.sh +0 -0
  181. /package/comate-engine/assets/skills/{icode-comate → icode}/scripts/common.sh +0 -0
  182. /package/comate-engine/assets/skills/{icode-comate → icode}/scripts/fix-machine-check.sh +0 -0
  183. /package/comate-engine/assets/skills/{icode-comate → icode}/scripts/merge-cr.sh +0 -0
  184. /package/comate-engine/assets/skills/{icode-comate → icode}/scripts/ssh-setup.sh +0 -0
  185. /package/comate-engine/assets/skills/{icode-comate → icode}/scripts/submit-acr.sh +0 -0
  186. /package/comate-engine/assets/skills/{icode-comate → icode}/scripts/submit-cr.sh +0 -0
  187. /package/comate-engine/assets/skills/{icode-comate → icode}/scripts/test-preflight.sh +0 -0
  188. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/SKILL.md +0 -0
  189. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/examples.md +0 -0
  190. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/add_member.md +0 -0
  191. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/change_scope.md +0 -0
  192. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/copy_doc.md +0 -0
  193. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/create_doc.md +0 -0
  194. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/delete_doc.md +0 -0
  195. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/edit_content.md +0 -0
  196. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/move_doc.md +0 -0
  197. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/query_comment.md +0 -0
  198. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/query_content.md +0 -0
  199. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/query_flowchart.md +0 -0
  200. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/query_permission.md +0 -0
  201. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/query_recent_view.md +0 -0
  202. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/query_repo.md +0 -0
  203. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/query_user_info.md +0 -0
  204. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/update_member.md +0 -0
  205. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/references/upload_attachment.md +0 -0
  206. /package/comate-engine/assets/skills/{ku-operator-comate → ku-operator}/scripts/ku_operator.py +0 -0
@@ -0,0 +1,473 @@
1
+ """iCafe API 客户端
2
+
3
+ 包含常量、配置类和 API 客户端。
4
+ """
5
+
6
+ import json as _json
7
+ import os
8
+ import urllib.error
9
+ import urllib.parse
10
+ import urllib.request
11
+ from dataclasses import dataclass
12
+ from pathlib import Path
13
+ from typing import Dict, List, Any, Optional
14
+
15
+ from logger import get_logger
16
+
17
+ logger = get_logger()
18
+
19
+
20
+ # ========================================
21
+ # 常量配置
22
+ # ========================================
23
+
24
+ # iCafe API base URL
25
+ ICAFE_BASE_URL = "http://10.11.152.208:8701/api/process/icafe"
26
+
27
+ # Farseer API base URL
28
+ FARSEER_BASE_URL = "https://farseer.baidu.com/api/v1"
29
+
30
+ # 默认超时时间(秒)
31
+ DEFAULT_TIMEOUT = 30
32
+
33
+ # 默认查询参数
34
+ DEFAULT_LOOKBACK_DAYS = 14
35
+ DEFAULT_MAX_RECORDS = 20
36
+
37
+ # Git log 提取时的最大提交数
38
+ DEFAULT_MAX_COMMITS = 200
39
+
40
+ # Git diff 输出的最大行数
41
+ DEFAULT_MAX_DIFF_LINES = 500
42
+
43
+ # 不是 iCafe 空间 ID 的常见前缀(小写)
44
+ GIT_LOG_FALSE_POSITIVE_PREFIXES = {
45
+ 'v', 'sha', 'utf', 'iso', 'rfc', 'p', 'rc', 'pr', 'mr',
46
+ 'http', 'https', 'feat', 'fix', 'chore', 'docs', 'style',
47
+ 'refactor', 'perf', 'test', 'build', 'ci', 'revert',
48
+ }
49
+
50
+ # 卡片类型 ID -> 名称映射表
51
+ ISSUE_TYPE_MAP = {
52
+ 56075: "Epic",
53
+ 54443: "Feature",
54
+ 5007: "Story",
55
+ 54444: "Task",
56
+ 54621: "Tech Feature",
57
+ 54622: "Tech Task",
58
+ 5009: "Bug",
59
+ 5811: "Bug(线上)",
60
+ 5011: "Case",
61
+ 65085: "非研发任务",
62
+ 49460: "项目",
63
+ 5008: "需求",
64
+ 5010: "任务",
65
+ 88805: "Prompt Story",
66
+ 88806: "Prompt Task",
67
+ 88807: "GenAI Data Story",
68
+ 88808: "GenAI Data Task",
69
+ }
70
+
71
+ # 反向映射:名称 -> issueTypeId
72
+ ISSUE_TYPE_NAME_MAP = {v: k for k, v in ISSUE_TYPE_MAP.items()}
73
+
74
+
75
+ # ========================================
76
+ # 配置类
77
+ # ========================================
78
+
79
+ @dataclass
80
+ class ICafeQueryConfig:
81
+ """iCafe 查询 API 配置"""
82
+
83
+ base_url: str = ICAFE_BASE_URL
84
+ timeout: int = DEFAULT_TIMEOUT
85
+
86
+ @staticmethod
87
+ def _get_auth_token() -> Optional[str]:
88
+ """获取认证 token
89
+
90
+ 优先从环境变量 COMATE_AUTH_TOKEN 读取,
91
+ 如果没有则从 ~/.comate/login 文件读取
92
+
93
+ Returns:
94
+ 认证 token 字符串,如果都未找到则返回 None
95
+ """
96
+ token = os.environ.get("COMATE_AUTH_TOKEN")
97
+ if token:
98
+ logger.info("Token 来源: env")
99
+ return token
100
+
101
+ login_file = Path.home() / ".comate" / "login"
102
+ if login_file.exists():
103
+ try:
104
+ content = login_file.read_text().strip()
105
+ if content:
106
+ logger.info("Token 来源: file (~/.comate/login)")
107
+ return content
108
+ except Exception:
109
+ pass
110
+
111
+ logger.warning("Token 来源: none, 未找到认证 token")
112
+ return None
113
+
114
+
115
+ # ========================================
116
+ # API 客户端
117
+ # ========================================
118
+
119
+ class ICafeQueryClient:
120
+ """iCafe 卡片查询客户端
121
+
122
+ 专注于卡片查询场景,支持:
123
+ - 通过 IQL 条件表达式查询卡片
124
+ - 通过卡片 ID 获取卡片详情
125
+ - 查询空间列表和空间计划
126
+ - 分页、排序、展示选项等高级查询能力
127
+ """
128
+
129
+ def __init__(self, config: Optional[ICafeQueryConfig] = None):
130
+ self.config = config or ICafeQueryConfig()
131
+ self._default_headers: Dict[str, str] = {
132
+ "Content-Type": "application/json",
133
+ "User-Agent": "iAPI/1.0.0 (http://iapi.baidu-int.com)",
134
+ }
135
+
136
+ auth_token = self.config._get_auth_token()
137
+ if auth_token:
138
+ self._default_headers["x-ac-Authorization"] = auth_token
139
+
140
+ def _http_request(
141
+ self,
142
+ url: str,
143
+ params: Optional[dict] = None,
144
+ data: Optional[dict] = None,
145
+ headers: Optional[Dict[str, str]] = None,
146
+ timeout: Optional[int] = None,
147
+ ) -> Any:
148
+ """发送 HTTP 请求并返回解析后的 JSON
149
+
150
+ Args:
151
+ url: 请求 URL
152
+ params: GET 查询参数
153
+ data: POST 请求体(dict,会被序列化为 JSON)
154
+ headers: 额外 headers(会合并到默认 headers)
155
+ timeout: 超时时间(秒)
156
+
157
+ Returns:
158
+ 解析后的 JSON 对象(dict 或 list)
159
+
160
+ Raises:
161
+ urllib.error.HTTPError: HTTP 状态码非 2xx 时
162
+ urllib.error.URLError: 网络连接失败时
163
+ """
164
+ if timeout is None:
165
+ timeout = self.config.timeout
166
+
167
+ # 合并 headers
168
+ merged_headers = dict(self._default_headers)
169
+ if headers:
170
+ merged_headers.update(headers)
171
+
172
+ # 构建完整 URL
173
+ if params:
174
+ query_string = urllib.parse.urlencode(params, doseq=True)
175
+ url = f"{url}?{query_string}" if "?" not in url else f"{url}&{query_string}"
176
+
177
+ # 构建 Request
178
+ body = None
179
+ if data is not None:
180
+ body = _json.dumps(data).encode("utf-8")
181
+
182
+ req = urllib.request.Request(url, data=body, headers=merged_headers)
183
+
184
+ with urllib.request.urlopen(req, timeout=timeout) as resp:
185
+ return _json.loads(resp.read().decode("utf-8"))
186
+
187
+ def _get_with_retry(self, url: str, params: dict, max_retries: int = 3) -> Any:
188
+ """带重试的 GET 请求,返回解析后的 JSON"""
189
+ import time
190
+ last_exc = None
191
+ for attempt in range(max_retries + 1):
192
+ try:
193
+ return self._http_request(url, params=params)
194
+ except Exception as e:
195
+ last_exc = e
196
+ if attempt < max_retries:
197
+ logger.warning("API 请求失败 (attempt %d/%d): %s, error=%s", attempt + 1, max_retries, url, e)
198
+ time.sleep(0.5 * (attempt + 1))
199
+ logger.error("API 请求最终失败: %s, error=%s", url, last_exc)
200
+ raise last_exc
201
+
202
+ # ========================================
203
+ # 1. 通过 IQL 条件查询卡片
204
+ # ========================================
205
+ def query_cards(self, space_id: str, iql: str,
206
+ page: Optional[int] = None,
207
+ show_detail: bool = False,
208
+ show_associations: bool = False,
209
+ is_desc: bool = False,
210
+ order: Optional[str] = None,
211
+ show_children: bool = False,
212
+ max_records: Optional[int] = None,
213
+ show_okr: bool = False,
214
+ show_accumulate: bool = False) -> Dict[str, Any]:
215
+ """通过 IQL 条件表达式查询卡片
216
+
217
+ Args:
218
+ space_id: 空间 ID,如 "joytest"
219
+ iql: IQL 查询表达式,如 "类型 = Bug AND 负责人 = currentUser"
220
+ page: 页码(从 1 开始),可选
221
+ show_detail: 是否显示卡片详情内容,默认 False
222
+ show_associations: 是否显示关联信息,默认 False
223
+ is_desc: 是否降序排列,默认 False
224
+ order: 排序字段(如 "创建时间"、"更新时间"),可选
225
+ show_children: 是否显示子卡片,默认 False
226
+ max_records: 最大返回记录数,可选
227
+ show_okr: 是否显示 OKR 信息,默认 False
228
+ show_accumulate: 是否显示累计信息,默认 False
229
+
230
+ Returns:
231
+ 查询结果字典,包含卡片列表和分页信息
232
+
233
+ Raises:
234
+ ValueError: 当 space_id 或 iql 为空时
235
+ urllib.error.URLError: 请求失败时
236
+
237
+ IQL 表达式示例:
238
+ - "类型 = Bug"
239
+ - "负责人 = currentUser"
240
+ - "负责人 = dongkexin01"
241
+ - "类型 = Bug AND 负责人 = currentUser"
242
+ - "创建时间 > \\"2025-01-01\\""
243
+ - "类型 in (Bug, Epic, Story)"
244
+ - "标题 ~ 测试"
245
+ - "流程状态 in (新建, 开发中)"
246
+ """
247
+ if not space_id:
248
+ raise ValueError("space_id 不能为空")
249
+ if not iql:
250
+ raise ValueError("iql 查询表达式不能为空")
251
+
252
+ params = {'iql': iql}
253
+ if page is not None:
254
+ params['page'] = page
255
+ if show_detail:
256
+ params['showDetail'] = ''
257
+ if show_associations:
258
+ params['showAssociations'] = ''
259
+ if is_desc:
260
+ params['isDesc'] = ''
261
+ if order:
262
+ params['order'] = order
263
+ if show_children:
264
+ params['showChildren'] = ''
265
+ if max_records:
266
+ params['maxRecords'] = max_records
267
+ if show_okr:
268
+ params['showOkr'] = ''
269
+ if show_accumulate:
270
+ params['showAccumulate'] = ''
271
+
272
+ url = f"{self.config.base_url}/api/spaces/{space_id}/cards"
273
+ logger.info("查询卡片: space=%s, iql=%s", space_id, iql)
274
+ result = self._get_with_retry(url, params)
275
+ cards_count = len(result.get("cards", []))
276
+ logger.info("查询卡片返回: %d 张", cards_count)
277
+ return result
278
+
279
+ # ========================================
280
+ # 2. 通过卡片 ID 获取卡片详情
281
+ # ========================================
282
+ def get_card_by_id(self, space_id: str, card_id: str,
283
+ show_associations: bool = False,
284
+ show_children: bool = False,
285
+ show_okr: bool = False,
286
+ show_accumulate: bool = False) -> Dict[str, Any]:
287
+ """根据空间 ID 和卡片 ID 获取单张卡片详情
288
+
289
+ Args:
290
+ space_id: 空间 ID
291
+ card_id: 卡片 ID
292
+ show_associations: 是否显示关联信息
293
+ show_children: 是否显示子卡片
294
+ show_okr: 是否显示 OKR 信息
295
+ show_accumulate: 是否显示累计信息
296
+
297
+ Returns:
298
+ 卡片信息字典,包含 id, title, description, status, assignee 等
299
+
300
+ Raises:
301
+ ValueError: 当 space_id 或 card_id 为空时
302
+ urllib.error.URLError: 请求失败时
303
+ """
304
+ if not space_id or not card_id:
305
+ raise ValueError("space_id 和 card_id 不能为空")
306
+
307
+ params = {}
308
+ if show_associations:
309
+ params['showAssociations'] = ''
310
+ if show_children:
311
+ params['showChildren'] = ''
312
+ if show_okr:
313
+ params['showOkr'] = ''
314
+ if show_accumulate:
315
+ params['showAccumulate'] = ''
316
+
317
+ url = f"{self.config.base_url}/api/spaces/{space_id}/cards/{card_id}"
318
+ return self._get_with_retry(url, params)
319
+
320
+ # ========================================
321
+ # 3. 查询最近访问的空间列表
322
+ # ========================================
323
+ def get_latest_spaces(self, current_user: str, limit: int = 3) -> List[Dict[str, Any]]:
324
+ """查询用户最近访问的空间列表
325
+
326
+ Args:
327
+ current_user: 用户 ID,如 "dongkexin01"
328
+ limit: 最多返回的空间数量,默认 3
329
+
330
+ Returns:
331
+ 空间列表,每个空间包含 id, name, prefix_code, access_time 等
332
+
333
+ Raises:
334
+ ValueError: 当 current_user 为空时
335
+ urllib.error.URLError: 请求失败时
336
+ """
337
+ if not current_user:
338
+ raise ValueError("current_user 不能为空")
339
+
340
+ logger.info("查询最近访问空间: user=%s, limit=%d", current_user, limit)
341
+ url = f"{self.config.base_url}/api/v2/space/latest"
342
+ params = {'currentUser': current_user}
343
+ data = self._get_with_retry(url, params)
344
+
345
+ # 对返回的空间列表截取前 limit 个
346
+ if isinstance(data, dict) and 'result' in data:
347
+ data['result'] = data['result'][:limit]
348
+ elif isinstance(data, list):
349
+ data = data[:limit]
350
+
351
+ return data
352
+
353
+ # ========================================
354
+ # 4. 获取空间内所有计划
355
+ # ========================================
356
+ def get_space_plans(self, space_id: str) -> List[Dict[str, Any]]:
357
+ """获取空间内所有计划
358
+
359
+ Args:
360
+ space_id: 空间 ID
361
+
362
+ Returns:
363
+ 计划列表,每个计划包含 id, name, start_date, end_date, status 等
364
+
365
+ Raises:
366
+ ValueError: 当 space_id 为空时
367
+ urllib.error.URLError: 请求失败时
368
+ """
369
+ if not space_id:
370
+ raise ValueError("space_id 不能为空")
371
+
372
+ url = f"{self.config.base_url}/api/v2/space/{space_id}/plans"
373
+ return self._get_with_retry(url, {})
374
+
375
+ # ========================================
376
+ # 5. 获取空间卡片类型列表
377
+ # ========================================
378
+ def get_space_issue_types(self, space_prefix: str) -> List[Dict[str, Any]]:
379
+ """获取空间的卡片类型列表
380
+
381
+ Args:
382
+ space_prefix: 空间前缀(如 "dkx")
383
+
384
+ Returns:
385
+ 卡片类型列表,每个类型包含 id, name 等
386
+
387
+ Raises:
388
+ ValueError: 当 space_prefix 为空时
389
+ urllib.error.URLError: 请求失败时
390
+ """
391
+ if not space_prefix:
392
+ raise ValueError("space_prefix 不能为空")
393
+
394
+ url = f"{self.config.base_url}/api/v2/space/{space_prefix}/issueTypes"
395
+ return self._get_with_retry(url, {})
396
+
397
+ # ========================================
398
+ # 6. 创建卡片
399
+ # ========================================
400
+ def create_card(
401
+ self,
402
+ title: str,
403
+ space_id: str,
404
+ card_type: str,
405
+ description: str = "",
406
+ assignee_id: Optional[str] = None,
407
+ ) -> Optional[Dict[str, Any]]:
408
+ """创建 iCafe 卡片
409
+
410
+ Args:
411
+ title: 卡片标题
412
+ space_id: 空间前缀(字符串类型,如 "dkx"),注意不是数字 ID
413
+ card_type: 卡片类型名称(如 "Bug", "Story")
414
+ description: 卡片描述,默认为空
415
+ assignee_id: 负责人 ID,默认为当前用户
416
+
417
+ Returns:
418
+ 创建成功的卡片信息,包含:id, title, type, sequence 等。
419
+ 失败时返回 None。
420
+
421
+ Note:
422
+ 此实现完全参考 icafe-card-assistant 的 icafe_client.py create_card 方法
423
+ 重要: space_id 参数应该是空间前缀(如 "dkx"),而不是数字 ID
424
+ """
425
+ try:
426
+ if not title or not space_id:
427
+ return None
428
+
429
+ logger.info("创建卡片: title=%s, space=%s, type=%s, assignee=%s", title, space_id, card_type, assignee_id)
430
+ issue = {
431
+ 'title': title,
432
+ 'detail': description, # 简化处理,不做 HTML 转换
433
+ }
434
+
435
+ if card_type:
436
+ issue['type'] = card_type
437
+
438
+ # 构建自定义字段
439
+ fields = {}
440
+ if assignee_id:
441
+ fields['负责人'] = assignee_id
442
+
443
+ if fields:
444
+ issue['fields'] = fields
445
+
446
+ data = {
447
+ 'issues': [issue]
448
+ }
449
+
450
+ url = f"{self.config.base_url}/api/v2/space/{space_id}/issue/new"
451
+ headers = {
452
+ 'User-Agent': 'iAPI/1.0.0 (http://iapi.baidu-int.com)',
453
+ 'Content-Type': 'application/json'
454
+ }
455
+
456
+ result = self._http_request(url, data=data, headers=headers)
457
+
458
+ # 检查返回的状态
459
+ if isinstance(result, dict):
460
+ response_status = result.get('status')
461
+ if response_status != 200:
462
+ logger.error("创建卡片失败: API 返回业务状态码 %s, 消息: %s", response_status, result.get('message', 'Unknown'))
463
+ print(f"错误: API 返回业务状态码 {response_status}, 消息: {result.get('message', 'Unknown')}", file=__import__('sys').stderr)
464
+ return None
465
+
466
+ issues = result.get("issues", [])
467
+ seq = issues[0].get("sequence") if issues else "unknown"
468
+ logger.info("创建卡片成功: sequence=%s", seq)
469
+ return result
470
+ except Exception as e:
471
+ logger.error("创建卡片异常: %s: %s", type(e).__name__, e)
472
+ print(f"创建卡片异常: {type(e).__name__}: {e}", file=__import__('sys').stderr)
473
+ return None
@@ -0,0 +1,52 @@
1
+ """Farseer API 客户端"""
2
+
3
+ import json
4
+ import urllib.parse
5
+ import urllib.request
6
+ from typing import Dict, List, Any, Optional
7
+
8
+ from .client import FARSEER_BASE_URL, DEFAULT_TIMEOUT, ISSUE_TYPE_MAP
9
+ from logger import get_logger
10
+
11
+ logger = get_logger()
12
+
13
+
14
+ def get_binding_card_types(space_id: int, timeout: int = DEFAULT_TIMEOUT) -> List[Dict[str, Any]]:
15
+ """查询空间可绑定的卡片类型列表(含 ID 和名称)
16
+
17
+ 调用 farseer storyRule 接口获取空间的 engineeringBindingTypes,
18
+ 返回包含 issueTypeId 和类型名称的完整列表。
19
+
20
+ Args:
21
+ space_id: 空间数字 ID(如 56355)
22
+ timeout: 请求超时时间(秒)
23
+
24
+ Returns:
25
+ 卡片类型列表,如 [{"id": "5009", "name": "Bug"}, {"id": "5007", "name": "Story"}]。
26
+ 接口调用失败或无配置时返回空列表。
27
+ """
28
+ logger.info("查询 farseer 可绑定类型: space_id=%s", space_id)
29
+ try:
30
+ query_string = urllib.parse.urlencode({'icafeSpaceId': space_id})
31
+ url = f"{FARSEER_BASE_URL}/storyRule/getRule?{query_string}"
32
+ req = urllib.request.Request(url)
33
+ with urllib.request.urlopen(req, timeout=timeout) as resp:
34
+ data = json.loads(resp.read().decode("utf-8"))
35
+
36
+ rule_data = data.get('data', {}).get('data', {})
37
+ binding_types = rule_data.get('engineeringBindingTypes', [])
38
+
39
+ result = []
40
+ for item in binding_types:
41
+ type_id = item.get('issueTypeId')
42
+ if type_id and type_id in ISSUE_TYPE_MAP:
43
+ result.append({
44
+ 'id': str(type_id),
45
+ 'name': ISSUE_TYPE_MAP[type_id]
46
+ })
47
+
48
+ logger.info("获取到 %d 种可绑定卡片类型", len(result))
49
+ return result
50
+ except Exception as e:
51
+ logger.warning("farseer 查询失败: %s", e)
52
+ return []