@comate/zulu 1.2.1-beta.2 → 1.3.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.
- package/comate-engine/assets/skills/auto-commit-comate/SKILL.md +260 -0
- package/comate-engine/assets/skills/auto-commit-comate/references/data_structures.md +189 -0
- package/comate-engine/assets/skills/auto-commit-comate/references/new_version_instruction.md +209 -0
- package/comate-engine/assets/skills/auto-commit-comate/references/old_version_instruction.md +208 -0
- package/comate-engine/assets/skills/auto-commit-comate/scripts/git_diff_cli.py +196 -0
- package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/git_utils.py +20 -10
- package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/client.py +69 -40
- package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/farseer.py +8 -9
- package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/matching.py +65 -9
- package/comate-engine/assets/skills/auto-commit-comate/scripts/match_card_cli.py +37 -0
- package/comate-engine/assets/skills/cnap-comate/SKILL.md +157 -0
- package/comate-engine/assets/skills/cnap-comate/references/cases.md +198 -0
- package/comate-engine/assets/skills/cnap-comate/references/deploy-troubleshoot.md +15 -0
- package/comate-engine/assets/skills/cnap-comate/references/install.md +43 -0
- package/comate-engine/assets/skills/cnap-comate/references/kubectl.md +55 -0
- package/comate-engine/assets/skills/cnap-comate/references/login.md +125 -0
- package/comate-engine/assets/skills/cnap-comate/references/oncall.md +24 -0
- package/comate-engine/assets/skills/cnap-comate/scripts/install_cnap_cli.sh +36 -0
- package/comate-engine/assets/skills/code-security/SKILL.md +176 -0
- package/comate-engine/assets/skills/code-security/references/credential_hosting.md +102 -0
- package/comate-engine/assets/skills/code-security/references/vul_repair_sensitive.md +219 -0
- package/comate-engine/assets/skills/code-security/scripts/build_repair_info.py +0 -0
- package/comate-engine/assets/skills/code-security/scripts/credential_hosting.py +99 -0
- package/comate-engine/assets/skills/code-security/scripts/credential_poll.py +350 -0
- package/comate-engine/assets/skills/code-security/scripts/http_client.py +173 -0
- package/comate-engine/assets/skills/code-security/scripts/parse_scan_result.py +301 -0
- package/comate-engine/assets/skills/code-security/scripts/repair_vulnerability.py +261 -0
- package/comate-engine/assets/skills/code-security/scripts/report_chat.py +198 -0
- package/comate-engine/assets/skills/code-security/scripts/scan_vulnerability.py +316 -0
- package/comate-engine/assets/skills/code-security-comate/SKILL.md +219 -0
- package/comate-engine/assets/skills/code-security-comate/references/credential_hosting.md +102 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair-go_sql_injection.md +399 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair-java_sql_injection.md +591 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair-php_sql_injection.md +318 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair-python_sql_injection.md +198 -0
- package/comate-engine/assets/skills/code-security-comate/references/vul_repair_sensitive.md +219 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/credential_hosting.py +87 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/credential_poll.py +345 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/http_client.py +173 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/parse_scan_result.py +392 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/repair_vulnerability.py +245 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/report_chat.py +145 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/scan_vulnerability.py +444 -0
- package/comate-engine/assets/skills/code-security-comate/scripts/utils.py +153 -0
- package/comate-engine/assets/skills/comate-docs-comate/SKILL.md +148 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/doc-map-extended.md +78 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/models-and-billing.md +51 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/product-overview.md +73 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/query_content.md +83 -0
- package/comate-engine/assets/skills/comate-docs-comate/references/query_repo.md +57 -0
- package/comate-engine/assets/skills/comate-docs-comate/scripts/ku_operator.py +1575 -0
- package/comate-engine/assets/skills/create-image-comate/SKILL.md +278 -0
- package/comate-engine/assets/skills/create-skill-comate/SKILL.md +308 -217
- package/comate-engine/assets/skills/create-skill-comate/agents/analyzer.md +274 -0
- package/comate-engine/assets/skills/create-skill-comate/agents/comparator.md +202 -0
- package/comate-engine/assets/skills/create-skill-comate/agents/grader.md +223 -0
- package/comate-engine/assets/skills/create-skill-comate/assets/eval_review.html +146 -0
- package/comate-engine/assets/skills/create-skill-comate/eval-viewer/generate_review.py +489 -0
- package/comate-engine/assets/skills/create-skill-comate/eval-viewer/viewer.html +1325 -0
- package/comate-engine/assets/skills/create-skill-comate/references/schemas.md +430 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/__init__.py +0 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/__pycache__/aggregate_benchmark.cpython-311.pyc +0 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/aggregate_benchmark.py +412 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/generate_report.py +334 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/package_skill.py +140 -0
- package/comate-engine/assets/skills/create-skill-comate/scripts/utils.py +53 -0
- package/comate-engine/assets/skills/find-skills-comate/SKILL.md +15 -12
- package/comate-engine/assets/skills/find-skills-comate/scripts/fetch_skills.py +32 -3
- package/comate-engine/assets/skills/get-ugate-token-comate/SKILL.md +159 -0
- package/comate-engine/assets/skills/get-ugate-token-comate/getUgateToken.py +150 -0
- package/comate-engine/assets/skills/icafe-comate/SKILL.md +240 -0
- package/comate-engine/assets/skills/icafe-comate/references/ai-workflows.md +233 -0
- package/comate-engine/assets/skills/icafe-comate/references/commands.md +1147 -0
- package/comate-engine/assets/skills/icafe-comate/references/error-handling.md +164 -0
- package/comate-engine/assets/skills/icafe-comate/references/git-auto-bindcard-workflow.md +201 -0
- package/comate-engine/assets/skills/icafe-comate/references/git-bindcard-workflow.md +327 -0
- package/comate-engine/assets/skills/icafe-comate/references/iql-syntax.md +327 -0
- package/comate-engine/assets/skills/icafe-comate/references/platform-concepts.md +317 -0
- package/comate-engine/assets/skills/icafe-comate/references/smart-create-workflow.md +171 -0
- package/comate-engine/assets/skills/icafe-comate/references/smart-find-workflow.md +127 -0
- package/comate-engine/assets/skills/icafe-comate/references/smart-update-workflow.md +118 -0
- package/comate-engine/assets/skills/icode-comate/SKILL.md +366 -0
- package/comate-engine/assets/skills/icode-comate/references/api/add_reviewers.md +44 -0
- package/comate-engine/assets/skills/icode-comate/references/api/build_fetch_command.md +89 -0
- package/comate-engine/assets/skills/icode-comate/references/api/check_repo_permission.md +89 -0
- package/comate-engine/assets/skills/icode-comate/references/api/create_branch.md +79 -0
- package/comate-engine/assets/skills/icode-comate/references/api/create_draft_comment.md +109 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_ai_cr_result.md +190 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_ai_review.md +97 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_diff_content.md +92 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_diff_file.md +88 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_machine_check.md +73 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_my_reviews.md +115 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_person_commit.md +89 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_person_repo.md +63 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_repo_branch.md +62 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_repo_config.md +91 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_repo_members.md +118 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_repo_reviews.md +91 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_review_comments.md +87 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_review_info.md +81 -0
- package/comate-engine/assets/skills/icode-comate/references/api/get_submit_settings.md +105 -0
- package/comate-engine/assets/skills/icode-comate/references/api/icode-api.md +86 -0
- package/comate-engine/assets/skills/icode-comate/references/api/publish_comments.md +72 -0
- package/comate-engine/assets/skills/icode-comate/references/api/set_review_score.md +58 -0
- package/comate-engine/assets/skills/icode-comate/references/api/start_ai_review.md +77 -0
- package/comate-engine/assets/skills/icode-comate/references/api/submit_review.md +50 -0
- package/comate-engine/assets/skills/icode-comate/references/api/trigger_ai_cr.md +63 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/add-reviewer.md +92 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/fix-machine-check.md +144 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/merge-cr.md +100 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/ssh-setup.md +106 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/submit-acr.md +135 -0
- package/comate-engine/assets/skills/icode-comate/references/feature/submit-cr.md +123 -0
- package/comate-engine/assets/skills/icode-comate/references/git/clone.md +67 -0
- package/comate-engine/assets/skills/icode-comate/references/git/icode-git.md +68 -0
- package/comate-engine/assets/skills/icode-comate/references/git/push.md +64 -0
- package/comate-engine/assets/skills/icode-comate/references/git/push_cr.md +103 -0
- package/comate-engine/assets/skills/icode-comate/references/install.md +144 -0
- package/comate-engine/assets/skills/icode-comate/references/login.md +111 -0
- package/comate-engine/assets/skills/icode-comate/scripts/add-reviewer.sh +154 -0
- package/comate-engine/assets/skills/icode-comate/scripts/common.sh +145 -0
- package/comate-engine/assets/skills/icode-comate/scripts/fix-machine-check.sh +131 -0
- package/comate-engine/assets/skills/icode-comate/scripts/merge-cr.sh +105 -0
- package/comate-engine/assets/skills/icode-comate/scripts/ssh-setup.sh +159 -0
- package/comate-engine/assets/skills/icode-comate/scripts/submit-acr.sh +236 -0
- package/comate-engine/assets/skills/icode-comate/scripts/submit-cr.sh +104 -0
- package/comate-engine/assets/skills/icode-comate/scripts/test-preflight.sh +89 -0
- package/comate-engine/assets/skills/ku-operator-comate/SKILL.md +121 -0
- package/comate-engine/assets/skills/ku-operator-comate/examples.md +190 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/add_member.md +49 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/change_scope.md +38 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/copy_doc.md +50 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/create_doc.md +61 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/delete_doc.md +31 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/edit_content.md +568 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/move_doc.md +45 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_comment.md +79 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_content.md +83 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_flowchart.md +84 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_permission.md +38 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_recent_view.md +67 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_repo.md +57 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/query_user_info.md +37 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/update_member.md +41 -0
- package/comate-engine/assets/skills/ku-operator-comate/references/upload_attachment.md +52 -0
- package/comate-engine/assets/skills/ku-operator-comate/scripts/ku_operator.py +1575 -0
- package/comate-engine/node_modules/better-sqlite3/node_modules/.bin/prebuild-install +2 -2
- package/comate-engine/node_modules/tree-sitter-bash/node_modules/.bin/node-gyp-build +2 -2
- package/comate-engine/node_modules/tree-sitter-bash/node_modules/.bin/node-gyp-build-optional +2 -2
- package/comate-engine/node_modules/tree-sitter-bash/node_modules/.bin/node-gyp-build-test +2 -2
- package/comate-engine/package.json +2 -0
- package/comate-engine/server.js +263 -79
- package/dist/bundle/index.js +3 -3
- package/package.json +1 -1
- package/comate-engine/assets/skills/figma2code-comate/codeConnect.md +0 -37
- package/comate-engine/assets/skills/figma2code-comate/designToken.md +0 -3
- package/comate-engine/assets/skills/figma2code-comate/f2cMcp.md +0 -59
- package/comate-engine/assets/skills/smart-commit/SKILL.md +0 -646
- package/comate-engine/node_modules/@comate/plugin-host/dist/index-AZIho4HV.js +0 -1
- package/comate-engine/node_modules/@comate/plugin-host/dist/user-BIpzRUfb.js +0 -44
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/references/issue_type_mapping.json +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/references/query_reference.md +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/compat.py +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/create_card_cli.py +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/__init__.py +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/logger.py +0 -0
- /package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/recognize_card_cli.py +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# 旧版本 IDE 交互指南
|
|
2
|
+
|
|
3
|
+
本文档适用于**旧版本 IDE**(IDE 名称占位符未替换、或插件版本 < 4.1.0)的交互方式。旧版本不支持 `__silent:` 和 `__interactive:` 前缀。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 步骤 1:获取 iCafe 数据(旧版本命令)
|
|
8
|
+
|
|
9
|
+
使用 SKILL.md 步骤 1 中定义的命令模板,**不加 `__silent:` 前缀**直接执行。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 步骤 2:获取 git diff(旧版本命令)
|
|
14
|
+
|
|
15
|
+
使用 SKILL.md 步骤 2 中定义的命令模板,**不加 `__silent:` 前缀**直接执行。
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 步骤 4:展示卡片选择(文本交互)
|
|
20
|
+
|
|
21
|
+
根据 `viewMode` 输出文本列表。
|
|
22
|
+
|
|
23
|
+
**当 `viewMode == "list"`(有高匹配卡片)时:**
|
|
24
|
+
|
|
25
|
+
先展示卡片列表(已按匹配度排序,标注匹配理由),再展示新建选项:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
📋 根据代码变更,找到以下匹配的 iCafe 卡片:
|
|
29
|
+
|
|
30
|
+
1. ⭐ [${spacePrefix}-${card1.sequence}] ${card1.title}
|
|
31
|
+
类型: ${card1.type} | 状态: ${card1.status}
|
|
32
|
+
匹配理由: ${reason}
|
|
33
|
+
|
|
34
|
+
2. [${spacePrefix}-${card2.sequence}] ${card2.title}
|
|
35
|
+
类型: ${card2.type} | 状态: ${card2.status}
|
|
36
|
+
|
|
37
|
+
(最多显示 10 张卡片,⭐ 标记匹配度较高的卡片)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
🆕 如需新建卡片,为你推荐以下信息:
|
|
41
|
+
- 推荐标题:${result.defaults.title}
|
|
42
|
+
- 推荐空间:${spaceName} (${spacePrefix})
|
|
43
|
+
- 推荐类型:${推荐的类型名称}(类型 ID: ${result.defaults.type_id})
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
请回复:
|
|
47
|
+
- 输入序号(如 "1")选择对应卡片
|
|
48
|
+
- 输入卡片 ID(如 "DevOps-iScan-35835")直接关联
|
|
49
|
+
- 输入 "new" 使用推荐信息直接新建卡片
|
|
50
|
+
- 输入 "new 自定义标题" 使用推荐空间和类型、但自定义标题新建
|
|
51
|
+
- 输入 "new?" 查看所有可选空间和类型枚举
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**当 `viewMode == "create"`(无高匹配卡片)时:**
|
|
55
|
+
|
|
56
|
+
先展示新建卡片推荐(突出位置),再附上已有卡片作为备选:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
💡 当前代码变更与已有卡片匹配度较低,建议新建卡片:
|
|
60
|
+
|
|
61
|
+
🆕 推荐新建卡片信息:
|
|
62
|
+
- 推荐标题:${result.defaults.title}
|
|
63
|
+
- 推荐空间:${spaceName} (${spacePrefix})
|
|
64
|
+
- 推荐类型:${推荐的类型名称}(类型 ID: ${result.defaults.type_id})
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
📋 以下是你当前活跃的卡片(供参考):
|
|
68
|
+
|
|
69
|
+
1. [${spacePrefix}-${card1.sequence}] ${card1.title}
|
|
70
|
+
类型: ${card1.type} | 状态: ${card1.status}
|
|
71
|
+
|
|
72
|
+
(最多显示 10 张卡片)
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
请回复:
|
|
76
|
+
- 输入 "new" 使用推荐信息直接新建卡片
|
|
77
|
+
- 输入 "new 自定义标题" 使用推荐空间和类型、但自定义标题新建
|
|
78
|
+
- 输入序号(如 "1")选择对应卡片
|
|
79
|
+
- 输入卡片 ID(如 "DevOps-iScan-35835")直接关联
|
|
80
|
+
- 输入 "new?" 查看所有可选空间和类型枚举
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
如果没有找到卡片,输出:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
📋 未找到可关联的 iCafe 卡片
|
|
87
|
+
|
|
88
|
+
🆕 为你推荐以下建卡信息:
|
|
89
|
+
- 推荐标题:${result.defaults.title}
|
|
90
|
+
- 推荐空间:${spaceName} (${spacePrefix})
|
|
91
|
+
- 推荐类型:${推荐的类型名称}
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
请回复:
|
|
95
|
+
- 输入卡片 ID(如 "DevOps-iScan-35835")直接关联
|
|
96
|
+
- 输入 "new" 使用推荐信息直接新建卡片
|
|
97
|
+
- 输入 "new 自定义标题" 使用推荐空间和类型、但自定义标题新建
|
|
98
|
+
- 输入 "new?" 查看所有可选空间和类型枚举
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**推荐类型名称的获取方式:** 优先使用 `result.defaults.type_name`(由 Agent 在步骤 2 中根据 diff 语义推断)。如果为空,从 `result.available_spaces` 中找到当前空间(匹配 `space_prefix`),取其 `types` 列表中 `id` 等于 `result.defaults.type_id` 的类型的 `name`。如果仍然找不到,取该空间 `types` 列表第一个的 `name`。
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 步骤 5:处理用户操作(旧版本 IDE)
|
|
106
|
+
|
|
107
|
+
根据用户在对话中的文本回复:
|
|
108
|
+
|
|
109
|
+
**如果用户输入序号(如 "1"、"2"):**
|
|
110
|
+
- 解析用户选择的卡片,保存 `selected_card` 信息,继续步骤 7
|
|
111
|
+
|
|
112
|
+
**如果用户输入卡片 ID(如 "DevOps-iScan-35835"):**
|
|
113
|
+
- 调用 `recognize_card_cli.py` 获取卡片详情:
|
|
114
|
+
```
|
|
115
|
+
cd <用户项目目录> && python3 <skill_directory>/scripts/recognize_card_cli.py --link "<卡片ID>"
|
|
116
|
+
```
|
|
117
|
+
- 保存 `selected_card` 信息,继续步骤 7
|
|
118
|
+
|
|
119
|
+
**如果用户输入 "new"(使用推荐信息直接新建):**
|
|
120
|
+
- 使用 `result` 中的推荐信息调用 `create_card_cli.py` 创建卡片
|
|
121
|
+
- 标题 = `result.defaults.title`,空间 = `result.space_prefix`
|
|
122
|
+
- 类型 = 从 `result.available_spaces` 中匹配当前空间,取 `types` 中 `id` 等于 `result.defaults.type_id` 的类型名称
|
|
123
|
+
|
|
124
|
+
**如果用户输入 "new 自定义标题":**
|
|
125
|
+
- 与 "new" 逻辑相同,但标题使用用户输入的自定义标题(去掉 "new " 前缀后的部分)
|
|
126
|
+
|
|
127
|
+
**如果用户输入 "new?"(查看空间和类型枚举):**
|
|
128
|
+
|
|
129
|
+
从 `result.available_spaces` 输出完整枚举:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
📋 可选空间和类型:
|
|
133
|
+
|
|
134
|
+
空间 1: ${space1.name} (${space1.prefix})
|
|
135
|
+
可选类型:
|
|
136
|
+
- ${type1.name} (ID: ${type1.id})
|
|
137
|
+
- ${type2.name} (ID: ${type2.id})
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
请回复以下格式新建卡片:
|
|
141
|
+
new [标题] | [空间前缀] | [类型名称]
|
|
142
|
+
例如:new 修复登录问题 | dkx | Bug
|
|
143
|
+
|
|
144
|
+
也可以只指定部分:
|
|
145
|
+
new 修复登录问题 | dkx → 使用指定空间 + 该空间默认类型
|
|
146
|
+
new 修复登录问题 | | Story → 使用推荐空间 + 指定类型
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**如果用户输入 "new 标题 | 空间 | 类型"(完整指定):**
|
|
150
|
+
- 按 `|` 分割解析,第一段为标题,第二段(可选)为空间前缀,第三段(可选)为类型名称
|
|
151
|
+
- 为空的部分使用推荐值,调用 `create_card_cli.py` 创建卡片
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 步骤 8:展示提交确认(文本确认)
|
|
156
|
+
|
|
157
|
+
**当 `is_icode_repo = true` 且有绑定卡片时:**
|
|
158
|
+
|
|
159
|
+
输出:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
✅ 已关联卡片: ${spacePrefix}-${sequence}
|
|
163
|
+
标题: ${title}
|
|
164
|
+
类型: ${type} | 状态: ${status}
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
📝 建议的 commit message:
|
|
168
|
+
|
|
169
|
+
${spacePrefix}-${sequence} ${brief_description}
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
请确认:
|
|
173
|
+
- 回复 "ok" 或 "确认" 使用此 message 提交
|
|
174
|
+
- 回复 "edit: <新message>" 修改后提交(如 "edit: dkx-200 修复登录bug")
|
|
175
|
+
- 回复 "no" 或 "取消" 放弃提交
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**当 `is_icode_repo = false` 或无绑定卡片时:**
|
|
179
|
+
|
|
180
|
+
输出:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
📝 建议的 commit message:
|
|
184
|
+
|
|
185
|
+
${brief_description}
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
请确认:
|
|
189
|
+
- 回复 "ok" 或 "确认" 使用此 message 提交
|
|
190
|
+
- 回复 "edit: <新message>" 修改后提交
|
|
191
|
+
- 回复 "no" 或 "取消" 放弃提交
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 步骤 9:执行提交(旧版本 IDE)
|
|
197
|
+
|
|
198
|
+
**如果用户确认提交(回复 "ok"、"确认"、"yes"):**
|
|
199
|
+
- 执行 `git add . && git commit -m "${commit_message}"`
|
|
200
|
+
|
|
201
|
+
**如果用户修改后提交(回复 "edit: <新message>"):**
|
|
202
|
+
- 使用用户提供的新 message 执行提交
|
|
203
|
+
|
|
204
|
+
**如果用户取消(回复 "no"、"取消"):**
|
|
205
|
+
- 输出取消信息
|
|
206
|
+
|
|
207
|
+
旧版本 IDE 提交成功后额外提示:
|
|
208
|
+
- `如需推送到远程,请执行:git push origin HEAD:refs/for/<branch>`
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""命令行工具:获取 workspace 的 git diff 摘要
|
|
2
|
+
|
|
3
|
+
用法:
|
|
4
|
+
python3 git_diff_cli.py --workspace /path/to/project
|
|
5
|
+
|
|
6
|
+
输出:
|
|
7
|
+
JSON 格式的 diff 摘要,包含 changed_files、stat_summary、diff_content 等字段。
|
|
8
|
+
失败时输出 {"error": "错误信息"}。
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
# tracked diff 最大行数
|
|
18
|
+
MAX_TRACKED_DIFF_LINES = 300
|
|
19
|
+
# untracked diff 最大行数
|
|
20
|
+
MAX_UNTRACKED_DIFF_LINES = 200
|
|
21
|
+
# 合并后 diff 最大总行数
|
|
22
|
+
MAX_TOTAL_DIFF_LINES = 500
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def run_git(args, cwd, timeout=10):
|
|
26
|
+
"""执行 git 命令,返回 stdout 字符串。失败返回空字符串。"""
|
|
27
|
+
try:
|
|
28
|
+
result = subprocess.run(
|
|
29
|
+
["git"] + args,
|
|
30
|
+
capture_output=True, text=True, encoding="utf-8", errors="replace",
|
|
31
|
+
timeout=timeout, cwd=cwd
|
|
32
|
+
)
|
|
33
|
+
if result.returncode == 0:
|
|
34
|
+
return result.stdout
|
|
35
|
+
return ""
|
|
36
|
+
except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
|
|
37
|
+
return ""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def parse_numstat(cwd):
|
|
41
|
+
"""通过 git diff HEAD --numstat 获取 tracked 文件变更统计。"""
|
|
42
|
+
output = run_git(["diff", "HEAD", "--numstat"], cwd)
|
|
43
|
+
files = []
|
|
44
|
+
for line in output.strip().splitlines():
|
|
45
|
+
if not line:
|
|
46
|
+
continue
|
|
47
|
+
parts = line.split("\t")
|
|
48
|
+
if len(parts) != 3:
|
|
49
|
+
continue
|
|
50
|
+
ins_str, del_str, file_path = parts
|
|
51
|
+
# binary 文件的 numstat 输出是 - - filename
|
|
52
|
+
insertions = int(ins_str) if ins_str != "-" else 0
|
|
53
|
+
deletions = int(del_str) if del_str != "-" else 0
|
|
54
|
+
files.append({
|
|
55
|
+
"file": file_path,
|
|
56
|
+
"insertions": insertions,
|
|
57
|
+
"deletions": deletions,
|
|
58
|
+
})
|
|
59
|
+
return files
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_untracked_files(cwd):
|
|
63
|
+
"""获取 untracked 文件列表。"""
|
|
64
|
+
output = run_git(["ls-files", "--others", "--exclude-standard"], cwd)
|
|
65
|
+
return [f for f in output.strip().splitlines() if f]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_tracked_diff(cwd):
|
|
69
|
+
"""获取 tracked 文件的 diff 内容,截断到 MAX_TRACKED_DIFF_LINES 行。"""
|
|
70
|
+
output = run_git(["diff", "HEAD"], cwd, timeout=30)
|
|
71
|
+
lines = output.splitlines()
|
|
72
|
+
truncated = len(lines) > MAX_TRACKED_DIFF_LINES
|
|
73
|
+
if truncated:
|
|
74
|
+
lines = lines[:MAX_TRACKED_DIFF_LINES]
|
|
75
|
+
return "\n".join(lines), truncated
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_untracked_diff_and_stats(cwd, untracked_files):
|
|
79
|
+
"""获取 untracked 文件的 diff 和变更统计。
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
(changed_files, diff_content, truncated)
|
|
83
|
+
"""
|
|
84
|
+
changed_files = []
|
|
85
|
+
diff_lines = []
|
|
86
|
+
total_lines = 0
|
|
87
|
+
truncated = False
|
|
88
|
+
|
|
89
|
+
for file_path in untracked_files:
|
|
90
|
+
full_path = os.path.join(cwd, file_path)
|
|
91
|
+
try:
|
|
92
|
+
with open(full_path, "r", encoding="utf-8", errors="replace") as f:
|
|
93
|
+
lines = f.readlines()
|
|
94
|
+
except (OSError, IOError):
|
|
95
|
+
continue
|
|
96
|
+
|
|
97
|
+
insertions = len(lines)
|
|
98
|
+
if insertions > 0:
|
|
99
|
+
changed_files.append({
|
|
100
|
+
"file": file_path,
|
|
101
|
+
"insertions": insertions,
|
|
102
|
+
"deletions": 0,
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
# 构造 unified diff 格式的输出
|
|
106
|
+
file_diff_lines = [
|
|
107
|
+
f"diff --git a/{file_path} b/{file_path}",
|
|
108
|
+
"new file mode 100644",
|
|
109
|
+
f"--- /dev/null",
|
|
110
|
+
f"+++ b/{file_path}",
|
|
111
|
+
f"@@ -0,0 +1,{insertions} @@",
|
|
112
|
+
] + [f"+{line.rstrip()}" for line in lines]
|
|
113
|
+
|
|
114
|
+
# 检查总行数上限
|
|
115
|
+
remaining = MAX_UNTRACKED_DIFF_LINES - total_lines
|
|
116
|
+
if remaining <= 0:
|
|
117
|
+
truncated = True
|
|
118
|
+
break
|
|
119
|
+
if len(file_diff_lines) > remaining:
|
|
120
|
+
file_diff_lines = file_diff_lines[:remaining]
|
|
121
|
+
truncated = True
|
|
122
|
+
diff_lines.extend(file_diff_lines)
|
|
123
|
+
total_lines += len(file_diff_lines)
|
|
124
|
+
|
|
125
|
+
return changed_files, "\n".join(diff_lines), truncated
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def build_stat_summary(changed_files):
|
|
129
|
+
"""构建统计摘要字符串,如 '3 files, +130, -78'。"""
|
|
130
|
+
total_ins = sum(f["insertions"] for f in changed_files)
|
|
131
|
+
total_del = sum(f["deletions"] for f in changed_files)
|
|
132
|
+
n = len(changed_files)
|
|
133
|
+
return f"{n} file{'s' if n != 1 else ''}, +{total_ins}, -{total_del}"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def main():
|
|
137
|
+
"""解析命令行参数并输出 workspace 的 git diff 摘要 JSON。"""
|
|
138
|
+
parser = argparse.ArgumentParser(description="获取 workspace 的 git diff 摘要")
|
|
139
|
+
parser.add_argument("--workspace", required=True, help="workspace 路径")
|
|
140
|
+
parser.add_argument("--max-diff-lines", type=int, default=MAX_TOTAL_DIFF_LINES,
|
|
141
|
+
help="diff 内容最大总行数")
|
|
142
|
+
args = parser.parse_args()
|
|
143
|
+
|
|
144
|
+
workspace = os.path.abspath(args.workspace)
|
|
145
|
+
if not os.path.isdir(workspace):
|
|
146
|
+
print(json.dumps({"error": f"workspace 路径不存在: {workspace}"}))
|
|
147
|
+
sys.exit(1)
|
|
148
|
+
|
|
149
|
+
max_total = args.max_diff_lines
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
# 1. tracked 文件变更统计
|
|
153
|
+
tracked_files = parse_numstat(workspace)
|
|
154
|
+
|
|
155
|
+
# 2. untracked 文件列表
|
|
156
|
+
untracked_files = get_untracked_files(workspace)
|
|
157
|
+
|
|
158
|
+
# 3. tracked diff 内容
|
|
159
|
+
tracked_diff, tracked_truncated = get_tracked_diff(workspace)
|
|
160
|
+
|
|
161
|
+
# 4. untracked diff 和统计
|
|
162
|
+
untracked_changed, untracked_diff, untracked_truncated = \
|
|
163
|
+
get_untracked_diff_and_stats(workspace, untracked_files)
|
|
164
|
+
|
|
165
|
+
# 5. 合并 changed_files
|
|
166
|
+
all_changed = tracked_files + untracked_changed
|
|
167
|
+
|
|
168
|
+
# 6. 合并 diff 内容,检查总行数上限
|
|
169
|
+
tracked_lines = tracked_diff.splitlines() if tracked_diff else []
|
|
170
|
+
untracked_lines = untracked_diff.splitlines() if untracked_diff else []
|
|
171
|
+
all_lines = tracked_lines + untracked_lines
|
|
172
|
+
truncated = tracked_truncated or untracked_truncated or len(all_lines) > max_total
|
|
173
|
+
if len(all_lines) > max_total:
|
|
174
|
+
all_lines = all_lines[:max_total]
|
|
175
|
+
diff_content = "\n".join(all_lines)
|
|
176
|
+
|
|
177
|
+
# 7. 构建输出
|
|
178
|
+
has_changes = bool(all_changed) or bool(untracked_files)
|
|
179
|
+
output = {
|
|
180
|
+
"workspace": workspace,
|
|
181
|
+
"changed_files": all_changed,
|
|
182
|
+
"untracked_files": untracked_files,
|
|
183
|
+
"stat_summary": build_stat_summary(all_changed) if all_changed else "",
|
|
184
|
+
"has_changes": has_changes,
|
|
185
|
+
"diff_content": diff_content,
|
|
186
|
+
"truncated": truncated,
|
|
187
|
+
}
|
|
188
|
+
print(json.dumps(output, ensure_ascii=False))
|
|
189
|
+
|
|
190
|
+
except Exception as e:
|
|
191
|
+
print(json.dumps({"error": f"获取 diff 摘要异常: {type(e).__name__}: {e}"}))
|
|
192
|
+
sys.exit(1)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
if __name__ == "__main__":
|
|
196
|
+
main()
|
package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/git_utils.py
RENAMED
|
@@ -63,7 +63,8 @@ def get_current_user(username: Optional[str] = None) -> Optional[str]:
|
|
|
63
63
|
try:
|
|
64
64
|
result = subprocess.run(
|
|
65
65
|
["git", "config", "user.email"],
|
|
66
|
-
capture_output=True, text=True,
|
|
66
|
+
capture_output=True, text=True, encoding="utf-8", errors="replace",
|
|
67
|
+
timeout=5
|
|
67
68
|
)
|
|
68
69
|
if result.returncode == 0 and result.stdout.strip():
|
|
69
70
|
username = result.stdout.strip().split("@")[0]
|
|
@@ -77,7 +78,8 @@ def get_current_user(username: Optional[str] = None) -> Optional[str]:
|
|
|
77
78
|
try:
|
|
78
79
|
result = subprocess.run(
|
|
79
80
|
["git", "config", "user.name"],
|
|
80
|
-
capture_output=True, text=True,
|
|
81
|
+
capture_output=True, text=True, encoding="utf-8", errors="replace",
|
|
82
|
+
timeout=5
|
|
81
83
|
)
|
|
82
84
|
if result.returncode == 0 and result.stdout.strip():
|
|
83
85
|
username = result.stdout.strip()
|
|
@@ -112,7 +114,8 @@ def get_git_diff_summary(max_diff_lines: int = DEFAULT_MAX_DIFF_LINES) -> Option
|
|
|
112
114
|
try:
|
|
113
115
|
stat_result = subprocess.run(
|
|
114
116
|
["git", "diff", "HEAD", "--stat"],
|
|
115
|
-
capture_output=True, text=True,
|
|
117
|
+
capture_output=True, text=True, encoding="utf-8", errors="replace",
|
|
118
|
+
timeout=10
|
|
116
119
|
)
|
|
117
120
|
if stat_result.returncode != 0 or not stat_result.stdout.strip():
|
|
118
121
|
logger.info("git diff 无变更")
|
|
@@ -136,7 +139,8 @@ def get_git_diff_summary(max_diff_lines: int = DEFAULT_MAX_DIFF_LINES) -> Option
|
|
|
136
139
|
try:
|
|
137
140
|
diff_result = subprocess.run(
|
|
138
141
|
["git", "diff", "HEAD"],
|
|
139
|
-
capture_output=True, text=True,
|
|
142
|
+
capture_output=True, text=True, encoding="utf-8", errors="replace",
|
|
143
|
+
timeout=30
|
|
140
144
|
)
|
|
141
145
|
diff_content = diff_result.stdout if diff_result.returncode == 0 else ""
|
|
142
146
|
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
@@ -178,7 +182,8 @@ def extract_space_ids_from_git_log(
|
|
|
178
182
|
try:
|
|
179
183
|
result = subprocess.run(
|
|
180
184
|
["git", "log", "--oneline", "-n", str(max_commits)],
|
|
181
|
-
capture_output=True, text=True,
|
|
185
|
+
capture_output=True, text=True, encoding="utf-8", errors="replace",
|
|
186
|
+
timeout=10
|
|
182
187
|
)
|
|
183
188
|
if result.returncode != 0:
|
|
184
189
|
return []
|
|
@@ -203,17 +208,22 @@ def extract_space_ids_from_git_log(
|
|
|
203
208
|
return sorted_prefixes
|
|
204
209
|
|
|
205
210
|
# 策略 2:正则启发式兜底(无已知前缀或精确匹配无结果)
|
|
206
|
-
|
|
211
|
+
# 支持含连字符的复合前缀,如 DevOps-iScan-36261、TPUE-EE-2-22
|
|
212
|
+
# 贪婪匹配:最后一个 -数字 是卡片 ID,前面所有部分都是空间前缀
|
|
213
|
+
pattern = re.compile(r'\b([a-zA-Z][a-zA-Z0-9_]*(?:-[a-zA-Z0-9_]+)*)-(\d+)\b')
|
|
207
214
|
counter_fallback: Dict[str, int] = {}
|
|
208
215
|
|
|
209
216
|
for line in log_text.splitlines():
|
|
210
217
|
for match in pattern.finditer(line):
|
|
211
|
-
|
|
212
|
-
|
|
218
|
+
raw_prefix = match.group(1)
|
|
219
|
+
prefix_lower = raw_prefix.lower()
|
|
220
|
+
# 检查前缀首段是否是常见误报(如 feat-xxx、fix-xxx)
|
|
221
|
+
first_segment = raw_prefix.split('-', 1)[0].lower()
|
|
222
|
+
if first_segment in GIT_LOG_FALSE_POSITIVE_PREFIXES:
|
|
213
223
|
continue
|
|
214
|
-
if len(
|
|
224
|
+
if len(raw_prefix) <= 1:
|
|
215
225
|
continue
|
|
216
|
-
counter_fallback[
|
|
226
|
+
counter_fallback[prefix_lower] = counter_fallback.get(prefix_lower, 0) + 1
|
|
217
227
|
|
|
218
228
|
sorted_prefixes = sorted(counter_fallback, key=counter_fallback.get, reverse=True)
|
|
219
229
|
logger.info("git log 提取前缀: %s, 策略=正则启发式", sorted_prefixes)
|
package/comate-engine/assets/skills/{smart-commit → auto-commit-comate}/scripts/icafe/client.py
RENAMED
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
包含常量、配置类和 API 客户端。
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
import json as _json
|
|
6
7
|
import os
|
|
8
|
+
import urllib.error
|
|
9
|
+
import urllib.parse
|
|
10
|
+
import urllib.request
|
|
7
11
|
from dataclasses import dataclass
|
|
8
12
|
from pathlib import Path
|
|
9
13
|
from typing import Dict, List, Any, Optional
|
|
10
14
|
|
|
11
|
-
import requests
|
|
12
|
-
|
|
13
15
|
from logger import get_logger
|
|
14
16
|
|
|
15
17
|
logger = get_logger()
|
|
@@ -126,34 +128,69 @@ class ICafeQueryClient:
|
|
|
126
128
|
|
|
127
129
|
def __init__(self, config: Optional[ICafeQueryConfig] = None):
|
|
128
130
|
self.config = config or ICafeQueryConfig()
|
|
129
|
-
self.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
})
|
|
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
|
+
}
|
|
134
135
|
|
|
135
136
|
auth_token = self.config._get_auth_token()
|
|
136
137
|
if auth_token:
|
|
137
|
-
self.
|
|
138
|
+
self._default_headers["x-ac-Authorization"] = auth_token
|
|
138
139
|
|
|
139
|
-
def
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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"))
|
|
144
186
|
|
|
145
|
-
def _get_with_retry(self, url: str, params: dict, max_retries: int = 3) ->
|
|
146
|
-
"""带重试的 GET
|
|
187
|
+
def _get_with_retry(self, url: str, params: dict, max_retries: int = 3) -> Any:
|
|
188
|
+
"""带重试的 GET 请求,返回解析后的 JSON"""
|
|
147
189
|
import time
|
|
148
190
|
last_exc = None
|
|
149
191
|
for attempt in range(max_retries + 1):
|
|
150
192
|
try:
|
|
151
|
-
|
|
152
|
-
url, params=params, headers=self._get_headers(),
|
|
153
|
-
timeout=self.config.timeout
|
|
154
|
-
)
|
|
155
|
-
response.raise_for_status()
|
|
156
|
-
return response
|
|
193
|
+
return self._http_request(url, params=params)
|
|
157
194
|
except Exception as e:
|
|
158
195
|
last_exc = e
|
|
159
196
|
if attempt < max_retries:
|
|
@@ -195,7 +232,7 @@ class ICafeQueryClient:
|
|
|
195
232
|
|
|
196
233
|
Raises:
|
|
197
234
|
ValueError: 当 space_id 或 iql 为空时
|
|
198
|
-
|
|
235
|
+
urllib.error.URLError: 请求失败时
|
|
199
236
|
|
|
200
237
|
IQL 表达式示例:
|
|
201
238
|
- "类型 = Bug"
|
|
@@ -234,8 +271,7 @@ class ICafeQueryClient:
|
|
|
234
271
|
|
|
235
272
|
url = f"{self.config.base_url}/api/spaces/{space_id}/cards"
|
|
236
273
|
logger.info("查询卡片: space=%s, iql=%s", space_id, iql)
|
|
237
|
-
|
|
238
|
-
result = response.json()
|
|
274
|
+
result = self._get_with_retry(url, params)
|
|
239
275
|
cards_count = len(result.get("cards", []))
|
|
240
276
|
logger.info("查询卡片返回: %d 张", cards_count)
|
|
241
277
|
return result
|
|
@@ -263,7 +299,7 @@ class ICafeQueryClient:
|
|
|
263
299
|
|
|
264
300
|
Raises:
|
|
265
301
|
ValueError: 当 space_id 或 card_id 为空时
|
|
266
|
-
|
|
302
|
+
urllib.error.URLError: 请求失败时
|
|
267
303
|
"""
|
|
268
304
|
if not space_id or not card_id:
|
|
269
305
|
raise ValueError("space_id 和 card_id 不能为空")
|
|
@@ -279,8 +315,7 @@ class ICafeQueryClient:
|
|
|
279
315
|
params['showAccumulate'] = ''
|
|
280
316
|
|
|
281
317
|
url = f"{self.config.base_url}/api/spaces/{space_id}/cards/{card_id}"
|
|
282
|
-
|
|
283
|
-
return response.json()
|
|
318
|
+
return self._get_with_retry(url, params)
|
|
284
319
|
|
|
285
320
|
# ========================================
|
|
286
321
|
# 3. 查询最近访问的空间列表
|
|
@@ -297,7 +332,7 @@ class ICafeQueryClient:
|
|
|
297
332
|
|
|
298
333
|
Raises:
|
|
299
334
|
ValueError: 当 current_user 为空时
|
|
300
|
-
|
|
335
|
+
urllib.error.URLError: 请求失败时
|
|
301
336
|
"""
|
|
302
337
|
if not current_user:
|
|
303
338
|
raise ValueError("current_user 不能为空")
|
|
@@ -305,8 +340,7 @@ class ICafeQueryClient:
|
|
|
305
340
|
logger.info("查询最近访问空间: user=%s, limit=%d", current_user, limit)
|
|
306
341
|
url = f"{self.config.base_url}/api/v2/space/latest"
|
|
307
342
|
params = {'currentUser': current_user}
|
|
308
|
-
|
|
309
|
-
data = response.json()
|
|
343
|
+
data = self._get_with_retry(url, params)
|
|
310
344
|
|
|
311
345
|
# 对返回的空间列表截取前 limit 个
|
|
312
346
|
if isinstance(data, dict) and 'result' in data:
|
|
@@ -330,14 +364,13 @@ class ICafeQueryClient:
|
|
|
330
364
|
|
|
331
365
|
Raises:
|
|
332
366
|
ValueError: 当 space_id 为空时
|
|
333
|
-
|
|
367
|
+
urllib.error.URLError: 请求失败时
|
|
334
368
|
"""
|
|
335
369
|
if not space_id:
|
|
336
370
|
raise ValueError("space_id 不能为空")
|
|
337
371
|
|
|
338
372
|
url = f"{self.config.base_url}/api/v2/space/{space_id}/plans"
|
|
339
|
-
|
|
340
|
-
return response.json()
|
|
373
|
+
return self._get_with_retry(url, {})
|
|
341
374
|
|
|
342
375
|
# ========================================
|
|
343
376
|
# 5. 获取空间卡片类型列表
|
|
@@ -353,14 +386,13 @@ class ICafeQueryClient:
|
|
|
353
386
|
|
|
354
387
|
Raises:
|
|
355
388
|
ValueError: 当 space_prefix 为空时
|
|
356
|
-
|
|
389
|
+
urllib.error.URLError: 请求失败时
|
|
357
390
|
"""
|
|
358
391
|
if not space_prefix:
|
|
359
392
|
raise ValueError("space_prefix 不能为空")
|
|
360
393
|
|
|
361
394
|
url = f"{self.config.base_url}/api/v2/space/{space_prefix}/issueTypes"
|
|
362
|
-
|
|
363
|
-
return response.json()
|
|
395
|
+
return self._get_with_retry(url, {})
|
|
364
396
|
|
|
365
397
|
# ========================================
|
|
366
398
|
# 6. 创建卡片
|
|
@@ -421,10 +453,7 @@ class ICafeQueryClient:
|
|
|
421
453
|
'Content-Type': 'application/json'
|
|
422
454
|
}
|
|
423
455
|
|
|
424
|
-
|
|
425
|
-
response = self.session.post(url, json=data, headers=headers, timeout=self.config.timeout)
|
|
426
|
-
response.raise_for_status()
|
|
427
|
-
result = response.json()
|
|
456
|
+
result = self._http_request(url, data=data, headers=headers)
|
|
428
457
|
|
|
429
458
|
# 检查返回的状态
|
|
430
459
|
if isinstance(result, dict):
|