@comate/zulu 1.3.5 → 1.3.6

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 (47) hide show
  1. package/comate-engine/server.js +21 -21
  2. package/dist/bundle/index.js +2 -2
  3. package/package.json +1 -1
  4. package/comate-engine/assets/skills/auto-commit/SKILL.md +0 -436
  5. package/comate-engine/assets/skills/auto-commit/references/issue_type_mapping.json +0 -19
  6. package/comate-engine/assets/skills/auto-commit/references/new_version_instruction.md +0 -196
  7. package/comate-engine/assets/skills/auto-commit/references/old_version_instruction.md +0 -189
  8. package/comate-engine/assets/skills/auto-commit/references/query_reference.md +0 -176
  9. package/comate-engine/assets/skills/auto-commit/scripts/compat.py +0 -86
  10. package/comate-engine/assets/skills/auto-commit/scripts/create_card_cli.py +0 -67
  11. package/comate-engine/assets/skills/auto-commit/scripts/git_diff_cli.py +0 -196
  12. package/comate-engine/assets/skills/auto-commit/scripts/git_utils.py +0 -230
  13. package/comate-engine/assets/skills/auto-commit/scripts/icafe/__init__.py +0 -66
  14. package/comate-engine/assets/skills/auto-commit/scripts/icafe/client.py +0 -473
  15. package/comate-engine/assets/skills/auto-commit/scripts/icafe/farseer.py +0 -52
  16. package/comate-engine/assets/skills/auto-commit/scripts/icafe/matching.py +0 -781
  17. package/comate-engine/assets/skills/auto-commit/scripts/logger.py +0 -32
  18. package/comate-engine/assets/skills/auto-commit/scripts/match_card_cli.py +0 -37
  19. package/comate-engine/assets/skills/auto-commit/scripts/recognize_card_cli.py +0 -63
  20. package/comate-engine/assets/skills/auto-commit-comate/references/new_version_instruction.md +0 -209
  21. package/comate-engine/assets/skills/auto-commit-comate/references/old_version_instruction.md +0 -208
  22. package/comate-engine/assets/skills/auto-commit-comate/scripts/compat.py +0 -86
  23. package/comate-engine/assets/skills/build-web-page-comate/SKILL.md +0 -160
  24. package/comate-engine/assets/skills/build-web-page-comate/setup-html-scaffold.md +0 -49
  25. package/comate-engine/assets/skills/build-web-page-comate/setup-react-scaffold.md +0 -103
  26. package/comate-engine/assets/skills/build-web-page-comate/work-with-user-intent.md +0 -112
  27. package/comate-engine/assets/skills/code-security/SKILL.md +0 -176
  28. package/comate-engine/assets/skills/code-security/references/credential_hosting.md +0 -102
  29. package/comate-engine/assets/skills/code-security/references/vul_repair_sensitive.md +0 -219
  30. package/comate-engine/assets/skills/code-security/scripts/build_repair_info.py +0 -0
  31. package/comate-engine/assets/skills/code-security/scripts/credential_hosting.py +0 -99
  32. package/comate-engine/assets/skills/code-security/scripts/credential_poll.py +0 -350
  33. package/comate-engine/assets/skills/code-security/scripts/http_client.py +0 -173
  34. package/comate-engine/assets/skills/code-security/scripts/parse_scan_result.py +0 -301
  35. package/comate-engine/assets/skills/code-security/scripts/repair_vulnerability.py +0 -261
  36. package/comate-engine/assets/skills/code-security/scripts/report_chat.py +0 -198
  37. package/comate-engine/assets/skills/code-security/scripts/scan_vulnerability.py +0 -316
  38. package/comate-engine/assets/skills/comate-docs-comate/references/query_content.md +0 -83
  39. package/comate-engine/assets/skills/comate-docs-comate/references/query_repo.md +0 -57
  40. package/comate-engine/assets/skills/comate-docs-comate/scripts/ku_operator.py +0 -1575
  41. package/comate-engine/assets/skills/create-skill-comate/references/output-patterns.md +0 -82
  42. package/comate-engine/assets/skills/create-skill-comate/references/workflows.md +0 -28
  43. package/comate-engine/assets/skills/create-skill-comate/scripts/init_skill.py +0 -308
  44. package/comate-engine/node_modules/@comate/plugin-host/dist/index-B8VdZIx4.js +0 -1
  45. package/comate-engine/node_modules/@comate/plugin-host/dist/index-QEN4ay0E.js +0 -1
  46. package/comate-engine/node_modules/@comate/plugin-host/dist/user-DAIE9qbz.js +0 -44
  47. package/comate-engine/node_modules/@comate/plugin-host/dist/user-vP8ulngb.js +0 -44
@@ -1,32 +0,0 @@
1
- """smart-commit 统一日志模块
2
-
3
- 日志写入 ~/.comate-engine/log/kernel-yyyy-mm-dd.log
4
- """
5
-
6
- import logging
7
- from datetime import date
8
- from pathlib import Path
9
-
10
-
11
- def get_logger(name: str = "smart-commit") -> logging.Logger:
12
- """获取 smart-commit 日志实例
13
-
14
- Args:
15
- name: 日志名称,默认 "smart-commit"
16
-
17
- Returns:
18
- 配置好的 Logger 实例,写入 ~/.comate-engine/log/kernel-yyyy-mm-dd.log
19
- """
20
- logger = logging.getLogger(f"comate.{name}")
21
- if not logger.handlers:
22
- log_dir = Path.home() / ".comate-engine" / "log"
23
- log_dir.mkdir(parents=True, exist_ok=True)
24
- log_file = log_dir / f"kernel-{date.today().isoformat()}.log"
25
- handler = logging.FileHandler(log_file, encoding="utf-8")
26
- handler.setFormatter(logging.Formatter(
27
- "[%(asctime)s] [smart-commit] [%(levelname)s] %(message)s",
28
- datefmt="%Y-%m-%d %H:%M:%S"
29
- ))
30
- logger.addHandler(handler)
31
- logger.setLevel(logging.DEBUG)
32
- return logger
@@ -1,37 +0,0 @@
1
- """命令行工具:查询 iCafe 匹配卡片
2
-
3
- 用法:
4
- python3 match_card_cli.py --username "dongkexin01"
5
-
6
- 输出:
7
- JSON 格式的匹配结果,包含 cards、space_prefix、available_types 等字段。
8
- 失败时输出 {"error": "错误信息"} 或 {"disabled": true, "message": "..."}。
9
- """
10
-
11
- import argparse
12
- import json
13
- import os
14
- import sys
15
-
16
- sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
17
-
18
- from icafe.matching import find_matching_card
19
-
20
-
21
- def main():
22
- """解析命令行参数并查询匹配卡片。"""
23
- parser = argparse.ArgumentParser(description="查询 iCafe 匹配卡片")
24
- parser.add_argument("--username", default=None, help="用户名,如 dongkexin01")
25
- args = parser.parse_args()
26
-
27
- try:
28
- username = args.username or os.environ.get("COMATE_USERNAME")
29
- result = find_matching_card(current_user=username)
30
- print(json.dumps(result, ensure_ascii=False))
31
- except Exception as e:
32
- print(json.dumps({"error": f"查询匹配卡片异常: {type(e).__name__}: {e}"}))
33
- sys.exit(1)
34
-
35
-
36
- if __name__ == "__main__":
37
- main()
@@ -1,63 +0,0 @@
1
- """命令行工具:通过链接或卡片 ID 识别并获取 iCafe 卡片详情
2
-
3
- 用法:
4
- python3 recognize_card_cli.py --link "DevOps-iScan-35835"
5
- python3 recognize_card_cli.py --link "https://console.cloud.baidu-int.com/devops/icafe/issue/xxxx/show"
6
-
7
- 输出:
8
- JSON 格式的卡片详情,包含 sequence、title、type、status、spacePrefix 等字段。
9
- 失败时输出 {"error": "错误信息"}。
10
- """
11
-
12
- import argparse
13
- import json
14
- import os
15
- import sys
16
-
17
- sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
18
-
19
- from icafe.client import ICafeQueryClient
20
- from icafe.matching import parse_card_id_from_link
21
-
22
-
23
- def main():
24
- """识别 iCafe 卡片的主函数"""
25
- parser = argparse.ArgumentParser(description="识别 iCafe 卡片")
26
- parser.add_argument("--link", required=True,
27
- help="卡片链接或卡片 ID,示例: "
28
- "'DevOps-iScan-35835' 或 "
29
- "'https://console.cloud.baidu-int.com/devops/icafe/issue/DevOps-iScan-35835/show'")
30
- args = parser.parse_args()
31
-
32
- try:
33
- parsed = parse_card_id_from_link(args.link)
34
- if not parsed:
35
- print(json.dumps({"error": "无法解析卡片链接或 ID,请检查格式"}))
36
- sys.exit(1)
37
-
38
- space_prefix = parsed["space_prefix"]
39
- card_id = parsed["card_id"]
40
-
41
- client = ICafeQueryClient()
42
- card_detail = client.get_card_by_id(space_id=space_prefix, card_id=card_id)
43
-
44
- if card_detail and card_detail.get("cards"):
45
- card = card_detail["cards"][0]
46
- print(json.dumps({
47
- "success": True,
48
- "sequence": card_id,
49
- "title": card.get("title", ""),
50
- "type": card.get("type", ""),
51
- "status": card.get("status", ""),
52
- "spacePrefix": space_prefix,
53
- }))
54
- else:
55
- print(json.dumps({"error": "无法获取卡片信息,请检查链接或 ID 是否正确"}))
56
- sys.exit(1)
57
- except Exception as e:
58
- print(json.dumps({"error": f"识别卡片异常: {type(e).__name__}: {e}"}))
59
- sys.exit(1)
60
-
61
-
62
- if __name__ == "__main__":
63
- main()
@@ -1,209 +0,0 @@
1
- # 新版本 IDE 交互指南
2
-
3
- 本文档适用于**新版本 IDE**(IDE 名称占位符已替换、插件版本 ≥ 4.1.0)的交互方式。
4
-
5
- ---
6
-
7
- ## 全局规则
8
-
9
- **⚠️ 全局静默要求:整个流程中 Agent 仅通过 `__interactive:` UI 组件与用户交互。除步骤 9 的最终结果文字外,Agent 禁止向用户输出任何文字内容,包括但不限于:**
10
- - **过渡性话语**:如 "Now I have the data"、"Let me perform matching"、"让我分析一下"
11
- - **内部分析过程**:如 "Card 26: xxx - Score: 95"、"Matching analysis:"、匹配评分细节
12
- - **状态说明**:如 "has_good_match: true"、"Cards sorted by score"
13
- - **JSON 数据或代码片段**
14
-
15
- **Agent 应在内部完成所有思考后,直接调用对应的 `run_command`,不在工具调用之间输出任何文字。**
16
-
17
- **⚠️ 重要:所有 `run_command` 调用(`__interactive:` 除外)必须加 `__silent:` 前缀。唯一例外是步骤 9 的 git commit 命令,需要展示提交结果给用户。**
18
-
19
- **⚠️ 禁止额外命令:Agent 不得在流程步骤之外自行执行任何 shell 命令(如 `git status`、`ls` 等)。iCafe 数据由步骤 1 的 Python 脚本获取,git diff 由步骤 2 中 Agent 按规定命令获取。**
20
-
21
- **⚠️ 工作目录规则:Skill 执行时的工作目录可能不是用户项目目录。当命令需要在用户项目目录下执行时(如 git 操作、Python 脚本),必须在命令中加 `cd <用户项目目录> &&` 切换目录。但 `__silent:` 或 `__interactive:` 前缀必须始终在命令最开头。**
22
-
23
- **⚠️ 多 Workspace 规则:用户可能打开了多个代码库(multi-root workspace)。环境上下文中的 `Workspace Path` 会列出所有 workspace 路径。在步骤 2 和步骤 8 中,Agent 必须对每个 workspace 分别执行 git 命令,不可只处理第一个 workspace 后忽略其余的。**
24
-
25
- 正确格式:
26
- ```
27
- __silent: cd /path/to/project && git add .
28
- __interactive:icafe-cards {...}
29
- ```
30
-
31
- 错误格式(禁止):
32
- ```
33
- cd /path/to/project && __silent: git add .
34
- cd /path/to/project && __interactive:icafe-cards {...}
35
- ```
36
-
37
- ---
38
-
39
- ## 步骤 1:获取 iCafe 数据(新版本命令)
40
-
41
- 使用 SKILL.md 步骤 1 中定义的命令模板,**加 `__silent:` 前缀**执行。
42
-
43
- ---
44
-
45
- ## 步骤 2:获取 git diff(新版本命令)
46
-
47
- 使用 SKILL.md 步骤 2 中定义的命令模板,**加 `__silent:` 前缀**执行。
48
-
49
- ---
50
-
51
- ## 步骤 4:展示卡片选择(交互式 UI)
52
-
53
- 调用 `run_command` 展示卡片选择/新建 UI,**禁止在调用前输出任何文字**:
54
-
55
- ```
56
- run_command(command="__interactive:icafe-cards <payload JSON>")
57
- ```
58
-
59
- payload 构造方法 — 用 `result` 中的字段和匹配结果拼接 JSON:
60
- ```python
61
- import json
62
- payload = json.dumps({
63
- "cards": result["cards"], # 已按匹配度排序
64
- "spacePrefix": result["space_prefix"],
65
- "spaceId": result["space_id"],
66
- "spaceName": result["space_name"],
67
- "availableSpaces": result["available_spaces"],
68
- "viewMode": viewMode, # "list" 或 "create"
69
- "defaults": {
70
- "title": result["defaults"]["title"],
71
- "typeId": result["defaults"]["type_id"],
72
- "typeName": result["defaults"]["type_name"],
73
- "spaceId": result["space_id"]
74
- }
75
- })
76
- command = f"__interactive:icafe-cards {payload}"
77
- ```
78
-
79
- 完整示例 command 值:
80
- ```
81
- __interactive:icafe-cards {"cards":[{"sequence":"200","title":"修复登录问题","type":"Bug","status":"开发中"}],"spacePrefix":"dkx","spaceId":12345,"spaceName":"测试空间","viewMode":"list","availableSpaces":[{"id":12345,"prefix":"dkx","name":"测试空间","types":[{"id":"5009","name":"Bug"},{"id":"5007","name":"Story"}]}],"defaults":{"title":"修复登录验证码刷新问题","typeId":"5009","typeName":"Bug","spaceId":12345}}
82
- ```
83
-
84
- ---
85
-
86
- ## 步骤 5:处理用户操作(新版本 IDE)
87
-
88
- UI 组件返回 JSON,可能的 action 值:
89
-
90
- | action | 含义 | 处理方式 |
91
- |--------|------|----------|
92
- | `select` | 选择已有卡片 | 保存 `card` 中的卡片信息,继续步骤 7 |
93
- | `recognize` | 链接或卡片 ID 识别 | 调用 `recognize_card_cli.py` 获取卡片详情,继续步骤 7 |
94
- | `create` | 新建卡片 | 调用 `create_card_cli.py` 创建卡片,继续步骤 7 |
95
- | `skip` | 跳过 | 输出"已跳过卡片绑定和代码提交。",**结束 skill** |
96
- | `do_not_show_again` | 不再提示 | 输出"已关闭推荐卡片提示。",**结束 skill** |
97
-
98
- **recognize 处理:**
99
- ```
100
- __silent: cd <用户项目目录> && python3 <skill_directory>/scripts/recognize_card_cli.py --link "<用户返回的link>"
101
- ```
102
-
103
- **create 处理:**
104
-
105
- 使用 SKILL.md 步骤 5 中定义的「创建卡片命令模板」,**加 `__silent:` 前缀**执行。
106
-
107
- ---
108
-
109
- ## 步骤 8:展示提交确认(交互式 UI)
110
-
111
- 调用 `run_command` 展示提交确认 UI:
112
-
113
- ```
114
- run_command(command="__interactive:git-commit <payload JSON>")
115
- ```
116
-
117
- Agent 仅对 **`hasChanges: true` 的 workspace** 执行 `git branch -vv` + `git branch -r --sort=-committerdate`(使用 `__silent:` 前缀)。**无变更的 workspace 跳过分支查询,`currentBranch` 和 `remoteBranches` 使用空值。** 多 workspace 时,不同 workspace 的分支查询命令必须在同一次响应中并行发出。然后构造 payload:
118
-
119
- **⚠️ 重要:`workspaces` 数组必须包含环境上下文 `Workspace Path` 中列出的所有 workspace,不可遗漏。** 即使某个 workspace 没有变更(`hasChanges: false`),也必须包含在数组中。
120
-
121
- **⚠️ payload 顶层结构强约束(必须严格遵守):**
122
- - 顶层有且仅有 3 个字段:`commitMessage`、`boundCard`、`workspaces`
123
- - **`workspaces` 是复数(数组),不是单数 `workspace`(字符串)**——即使只有 1 个 workspace 也必须用数组
124
- - 使用 camelCase 命名:`commitMessage` 不是 `commit_message`,`boundCard` 不是 `icafe_card`
125
- - `changed_files` 必须嵌套在 `workspaces[].diffSummary` 内,禁止放在顶层
126
-
127
- **❌ 禁止生成的扁平化结构:**
128
- ```json
129
- {"commit_message":"xxx","workspace":"/path","changed_files":[...],"icafe_card":{...}}
130
- ```
131
-
132
- payload 结构(多 workspace 格式):
133
- ```json
134
- {
135
- "commitMessage": "dkx-200 修复登录问题",
136
- "boundCard": {"sequence": "200", "title": "修复登录问题", "type": "Bug", "status": "开发中", "spacePrefix": "dkx"},
137
- "workspaces": [
138
- {
139
- "workspace": "/path/to/frontend-app",
140
- "repoName": "frontend-app",
141
- "currentBranch": "feature/xxx",
142
- "remoteBranches": [{"name": "feature/xxx", "isCurrent": true}, {"name": "main", "isCurrent": false}],
143
- "hasChanges": true,
144
- "diffSummary": {
145
- "changed_files": [{"file": "src/App.tsx", "insertions": 76, "deletions": 66}],
146
- "stat_summary": "2 files, +100, -78"
147
- }
148
- },
149
- {
150
- "workspace": "/path/to/shared-utils",
151
- "repoName": "shared-utils",
152
- "currentBranch": "",
153
- "remoteBranches": [],
154
- "hasChanges": false,
155
- "diffSummary": null
156
- }
157
- ]
158
- }
159
- ```
160
-
161
- **构造规则:**
162
- - `commitMessage`:基于 diff 和绑定卡片生成的 commit message。iCode 仓库格式为 `"<spacePrefix>-<sequence> <brief_description>"`;非 iCode 仓库不带卡片 ID 前缀,仅生成描述性 message
163
- - `boundCard`:步骤 5 中选定的卡片信息。非 iCode 仓库或无卡片时为 `null`
164
- - `workspaces`:对每个 workspace 目录,使用步骤 2 中构建的 `workspace_diffs` 数据:
165
- - `workspace`:绝对路径
166
- - `repoName`:路径的最后一段
167
- - `currentBranch`:有变更时从 `git branch -vv` 解析当前分支名,无变更时为空字符串
168
- - `remoteBranches`:有变更时从 `git branch -r` 解析远程分支列表;无变更时为空数组。解析规则:
169
- 1. 跳过包含 `->` 的行(如 `origin/HEAD -> origin/master`,这是 HEAD 指针,不是分支)
170
- 2. 对每一行 trim 后去掉 `origin/` 前缀,得到分支名
171
- 3. 从 `git branch -vv` 输出中解析当前分支的远程追踪分支名,将匹配的分支标记为 `isCurrent: true`,其余为 `false`
172
- 4. 最多取 10 个分支(当前追踪分支必须包含在内),按最近活跃排序
173
- - `hasChanges`:该 workspace 是否有变更(`workspace_diffs[path].has_changes`)
174
- - `diffSummary`:有变更时为 `workspace_diffs[path]` 中的 `changed_files` + `stat_summary`,无变更时为 `null`
175
-
176
- **顶层不再有旧的 `currentBranch`/`remoteBranches`/`diffSummary` 字段。**
177
-
178
- 完整示例 command 值:
179
- ```
180
- __interactive:git-commit {"commitMessage":"dkx-200 修复登录验证码刷新问题","boundCard":{"sequence":"200","title":"修复登录问题","type":"Bug","status":"开发中","spacePrefix":"dkx"},"workspaces":[{"workspace":"/home/user/frontend-app","repoName":"frontend-app","currentBranch":"feature/login-fix","remoteBranches":[{"name":"feature/login-fix","isCurrent":true},{"name":"main","isCurrent":false}],"hasChanges":true,"diffSummary":{"changed_files":[{"file":"src/login.ts","insertions":15,"deletions":3}],"stat_summary":"1 file, +15, -3"}}]}
181
- ```
182
-
183
- 用户操作后,tool output 返回 JSON:
184
- - 确认提交:`{"action": "submit", "repos": [{"workspace": "...", "commitMessage": "...", "branch": "..."}]}`
185
- - 取消提交:`{"action": "cancel"}`
186
-
187
- ---
188
-
189
- ## 步骤 9:执行提交(新版本 IDE)
190
-
191
- 从 tool output 解析用户操作:
192
-
193
- **如果是 action === "submit":**
194
-
195
- UI 返回的结果格式:
196
- ```json
197
- {"action": "submit", "repos": [{"workspace": "/path/to/repo", "commitMessage": "dkx-200 修复...", "branch": "feature/xxx"}]}
198
- ```
199
-
200
- Agent 收到后,对 `repos` 数组中的每个仓库自主决定执行方式:
201
- - `cd` 到对应 workspace 目录
202
- - 执行 `git add .`、`git commit -m "<commitMessage>"`(git commit 命令不使用 `__silent:`,展示提交结果给用户)
203
- - 如果用户选择了特定分支且不是当前分支,先 `git checkout` 切换
204
- - **推送方式根据仓库类型区分:**
205
- - 统一使用 `git push origin HEAD:refs/for/<branch>` 推送到 Gerrit 代码评审
206
- - 多仓库时逐个执行,每个仓库独立处理
207
-
208
- **如果是 action === "cancel":**
209
- - 输出"已取消提交"
@@ -1,208 +0,0 @@
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>`
@@ -1,86 +0,0 @@
1
- """
2
- 版本兼容性检测模块
3
-
4
- 用于检测当前 IDE 版本是否支持自定义交互式 UI
5
- """
6
-
7
- # 支持自定义 UI 的最低版本
8
- MIN_INTERACTIVE_VERSION = '1.2.0'
9
-
10
-
11
- def parse_version(version_str: str) -> tuple:
12
- """
13
- 解析版本号字符串为可比较的元组
14
-
15
- Args:
16
- version_str: 版本号字符串,如 "1.2.3"
17
-
18
- Returns:
19
- 版本号元组,如 (1, 2, 3)
20
- """
21
- try:
22
- parts = version_str.split('.')
23
- return tuple(int(p) for p in parts[:3])
24
- except (ValueError, AttributeError):
25
- return (0, 0, 0)
26
-
27
-
28
- def is_interactive_ui_supported(ide_name: str, plugin_version: str) -> bool:
29
- """
30
- 检测当前 IDE 版本是否支持自定义交互式 UI
31
-
32
- Args:
33
- ide_name: 从 ${COMATE_IDE_NAME} 获取的值
34
- plugin_version: 从 ${COMATE_PLUGIN_VERSION} 获取的值
35
-
36
- Returns:
37
- True 如果支持自定义 UI,否则 False
38
- """
39
- # 1. 检测占位符是否被替换
40
- # 旧版本 CLI 不支持这些占位符,值仍为 "${...}" 原样
41
- if not ide_name or ide_name.startswith('${'):
42
- return False
43
- if not plugin_version or plugin_version.startswith('${'):
44
- return False
45
-
46
- # 2. 版本号比较
47
- current = parse_version(plugin_version)
48
- minimum = parse_version(MIN_INTERACTIVE_VERSION)
49
-
50
- return current >= minimum
51
-
52
-
53
- def check_interactive_support(ide_name: str, plugin_version: str) -> str:
54
- """
55
- 检测并返回应使用的流程模式
56
-
57
- Args:
58
- ide_name: 从 ${COMATE_IDE_NAME} 获取的值
59
- plugin_version: 从 ${COMATE_PLUGIN_VERSION} 获取的值
60
-
61
- Returns:
62
- "INTERACTIVE_MODE" 或 "FALLBACK_MODE"
63
- """
64
- if is_interactive_ui_supported(ide_name, plugin_version):
65
- return "INTERACTIVE_MODE"
66
- return "FALLBACK_MODE"
67
-
68
-
69
- if __name__ == "__main__":
70
- # 测试用例
71
- test_cases = [
72
- ("vscode", "1.2.0", "INTERACTIVE_MODE"),
73
- ("vscode", "1.3.5", "INTERACTIVE_MODE"),
74
- ("vscode", "1.1.9", "FALLBACK_MODE"),
75
- ("vscode", "0.9.0", "FALLBACK_MODE"),
76
- ("${COMATE_IDE_NAME}", "1.2.0", "FALLBACK_MODE"),
77
- ("vscode", "${COMATE_PLUGIN_VERSION}", "FALLBACK_MODE"),
78
- ("", "1.2.0", "FALLBACK_MODE"),
79
- ("vscode", "", "FALLBACK_MODE"),
80
- ]
81
-
82
- print("Running compatibility check tests...")
83
- for ide, version, expected in test_cases:
84
- result = check_interactive_support(ide, version)
85
- status = "PASS" if result == expected else "FAIL"
86
- print(f"[{status}] ide={ide!r}, version={version!r} -> {result} (expected: {expected})")