@comate/zulu 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +8 -0
  2. package/comate-engine/assets/skills/auto-commit/SKILL.md +386 -0
  3. package/comate-engine/assets/skills/auto-commit/references/issue_type_mapping.json +19 -0
  4. package/comate-engine/assets/skills/auto-commit/references/new_version_instruction.md +196 -0
  5. package/comate-engine/assets/skills/auto-commit/references/old_version_instruction.md +189 -0
  6. package/comate-engine/assets/skills/auto-commit/references/query_reference.md +176 -0
  7. package/comate-engine/assets/skills/auto-commit/scripts/compat.py +86 -0
  8. package/comate-engine/assets/skills/auto-commit/scripts/create_card_cli.py +67 -0
  9. package/comate-engine/assets/skills/auto-commit/scripts/git_diff_cli.py +195 -0
  10. package/comate-engine/assets/skills/auto-commit/scripts/git_utils.py +225 -0
  11. package/comate-engine/assets/skills/auto-commit/scripts/icafe/__init__.py +66 -0
  12. package/comate-engine/assets/skills/auto-commit/scripts/icafe/client.py +444 -0
  13. package/comate-engine/assets/skills/auto-commit/scripts/icafe/farseer.py +53 -0
  14. package/comate-engine/assets/skills/auto-commit/scripts/icafe/matching.py +778 -0
  15. package/comate-engine/assets/skills/auto-commit/scripts/logger.py +32 -0
  16. package/comate-engine/assets/skills/auto-commit/scripts/recognize_card_cli.py +63 -0
  17. package/comate-engine/assets/skills/automation-browser-comate/SKILL.md +193 -90
  18. package/comate-engine/assets/skills/figma2code-comate/SKILL.md +2 -2
  19. package/comate-engine/assets/skills/figma2code-comate/references/codeConnect.md +7 -10
  20. package/comate-engine/assets/skills/smart-commit/SKILL.md +646 -0
  21. package/comate-engine/assets/skills/smart-commit/references/issue_type_mapping.json +19 -0
  22. package/comate-engine/assets/skills/smart-commit/references/query_reference.md +176 -0
  23. package/comate-engine/assets/skills/smart-commit/scripts/compat.py +86 -0
  24. package/comate-engine/assets/skills/smart-commit/scripts/create_card_cli.py +67 -0
  25. package/comate-engine/assets/skills/smart-commit/scripts/git_utils.py +220 -0
  26. package/comate-engine/assets/skills/smart-commit/scripts/icafe/__init__.py +66 -0
  27. package/comate-engine/assets/skills/smart-commit/scripts/icafe/client.py +444 -0
  28. package/comate-engine/assets/skills/smart-commit/scripts/icafe/farseer.py +53 -0
  29. package/comate-engine/assets/skills/smart-commit/scripts/icafe/matching.py +728 -0
  30. package/comate-engine/assets/skills/smart-commit/scripts/logger.py +32 -0
  31. package/comate-engine/assets/skills/smart-commit/scripts/recognize_card_cli.py +63 -0
  32. package/comate-engine/node_modules/@comate/plugin-engine/dist/index.js +7 -7
  33. package/comate-engine/node_modules/@comate/plugin-host/dist/index.js +1 -1
  34. package/comate-engine/node_modules/@comate/plugin-host/dist/main.js +1 -1
  35. package/comate-engine/node_modules/@comate/plugin-shared-internals/dist/index.js +8 -8
  36. package/comate-engine/node_modules/@comate/preview-proxy/package.json +2 -2
  37. package/comate-engine/node_modules/better-sqlite3/build/Release/better_sqlite3.node +0 -0
  38. package/comate-engine/package.json +2 -2
  39. package/comate-engine/server.js +61 -44
  40. package/dist/bundle/index.js +8 -8
  41. package/package.json +1 -1
  42. package/comate-engine/node_modules/@comate/plugin-engine/dist/index.d.ts +0 -188
  43. package/comate-engine/node_modules/@comate/plugin-host/dist/main.d.ts +0 -14
  44. package/comate-engine/node_modules/@comate/plugin-shared-internals/dist/index.d.ts +0 -4817
  45. package/comate-engine/node_modules/better-sqlite3/README.md +0 -99
  46. package/comate-engine/node_modules/bindings/LICENSE.md +0 -22
  47. package/comate-engine/node_modules/bindings/README.md +0 -98
  48. package/comate-engine/node_modules/compare-versions/README.md +0 -133
  49. package/comate-engine/node_modules/compare-versions/lib/esm/compare.d.ts +0 -19
  50. package/comate-engine/node_modules/compare-versions/lib/esm/compareVersions.d.ts +0 -8
  51. package/comate-engine/node_modules/compare-versions/lib/esm/index.d.ts +0 -5
  52. package/comate-engine/node_modules/compare-versions/lib/esm/satisfies.d.ts +0 -14
  53. package/comate-engine/node_modules/compare-versions/lib/esm/utils.d.ts +0 -7
  54. package/comate-engine/node_modules/compare-versions/lib/esm/validate.d.ts +0 -28
  55. package/comate-engine/node_modules/file-uri-to-path/History.md +0 -21
  56. package/comate-engine/node_modules/file-uri-to-path/README.md +0 -74
  57. package/comate-engine/node_modules/file-uri-to-path/index.d.ts +0 -2
  58. package/comate-engine/node_modules/pkce-challenge/README.md +0 -55
  59. package/comate-engine/node_modules/pkce-challenge/dist/index.browser.d.ts +0 -19
  60. package/comate-engine/node_modules/pkce-challenge/dist/index.node.d.ts +0 -19
  61. package/comate-engine/node_modules/sqlite-vec/README.md +0 -1
  62. package/comate-engine/node_modules/sqlite-vec/index.d.ts +0 -17
  63. package/comate-engine/node_modules/sqlite-vec-darwin-arm64/README.md +0 -1
  64. package/comate-engine/node_modules/sqlite-vec-darwin-x64/README.md +0 -1
  65. package/comate-engine/node_modules/sqlite-vec-linux-arm64/README.md +0 -1
  66. package/comate-engine/node_modules/sqlite-vec-linux-x64/README.md +0 -1
  67. package/comate-engine/node_modules/sqlite-vec-windows-x64/README.md +0 -1
  68. package/comate-engine/node_modules/tree-sitter-bash/README.md +0 -44
  69. package/comate-engine/node_modules/tree-sitter-bash/bindings/node/binding_test.js +0 -9
  70. package/comate-engine/node_modules/tree-sitter-bash/bindings/node/index.d.ts +0 -28
  71. package/comate-engine/node_modules/tree-sitter-bash/bindings/node/index.js +0 -11
  72. package/comate-engine/node_modules/tree-sitter-bash/prebuilds/darwin-arm64/tree-sitter-bash.node +0 -0
  73. package/comate-engine/node_modules/tree-sitter-bash/prebuilds/darwin-x64/tree-sitter-bash.node +0 -0
  74. package/comate-engine/node_modules/tree-sitter-bash/prebuilds/linux-arm64/tree-sitter-bash.node +0 -0
  75. package/comate-engine/node_modules/tree-sitter-bash/prebuilds/linux-x64/tree-sitter-bash.node +0 -0
  76. package/comate-engine/node_modules/tree-sitter-bash/prebuilds/win32-arm64/tree-sitter-bash.node +0 -0
  77. package/comate-engine/node_modules/tree-sitter-bash/prebuilds/win32-x64/tree-sitter-bash.node +0 -0
  78. package/comate-engine/node_modules/tree-sitter-bash/src/grammar.json +0 -7145
  79. package/comate-engine/node_modules/tree-sitter-bash/src/node-types.json +0 -2894
  80. package/comate-engine/node_modules/web-streams-polyfill/README.md +0 -119
  81. package/comate-engine/node_modules/web-streams-polyfill/types/polyfill.d.ts +0 -28
  82. package/comate-engine/node_modules/web-streams-polyfill/types/ponyfill.d.ts +0 -809
  83. package/comate-engine/node_modules/web-tree-sitter/README.md +0 -269
  84. package/comate-engine/node_modules/web-tree-sitter/debug/tree-sitter.cjs +0 -4558
  85. package/comate-engine/node_modules/web-tree-sitter/debug/tree-sitter.js +0 -4516
  86. package/comate-engine/node_modules/web-tree-sitter/debug/tree-sitter.wasm +0 -0
  87. package/comate-engine/node_modules/web-tree-sitter/web-tree-sitter.d.ts +0 -1030
  88. package/comate-engine/node_modules/win-ca/README.md +0 -648
@@ -0,0 +1,646 @@
1
+ ---
2
+ name: smart-commit
3
+ description: 当完成一定量的代码修改后,考虑是否应该提交一个 commit message。如果需要,则使用此 skill 而非直接 git commit。
4
+ ---
5
+
6
+ # 智能提交助手
7
+
8
+ ## 版本信息
9
+
10
+ - **IDE 名称**: ${COMATE_IDE_NAME}
11
+ - **插件版本**: ${COMATE_PLUGIN_VERSION}
12
+ - **用户名**: ${COMATE_USERNAME}
13
+
14
+ ## 概述
15
+
16
+ 本技能将当前工作区的 git diff 与用户在 iCafe 上的活跃卡片进行匹配,支持选择已有卡片或新建卡片,自动生成 commit message 并完成提交。
17
+
18
+ **调起即执行,流程完全固定,不做任何意图分析。**
19
+
20
+ ## ⛔ 前置开关检查(最高优先级,必须在一切操作之前执行)
21
+
22
+ **此检查的优先级高于所有后续步骤。如果开关关闭,禁止执行任何后续操作。**
23
+
24
+ 通过以下方式进行检查(在调用 Python 脚本之前,**必须加 `__silent:` 前缀**):
25
+
26
+ ```
27
+ __silent: cat ~/.comate/settings.json 2>/dev/null || echo '{}'
28
+ ```
29
+
30
+ 解析返回的 JSON,检查 `enableSmartCommit` 字段:
31
+ - 如果值为 `false` → **立即结束 skill,不再输出任何内容,不再执行任何后续步骤**
32
+ - 如果值为 `true` 或字段不存在(默认开启)→ 继续执行后续步骤
33
+
34
+ ## 步骤 0:检测 IDE 版本兼容性(必须首先执行,完全静默)
35
+
36
+ **⚠️ 重要:此步骤必须在所有其他步骤之前执行,决定后续使用哪套交互方式。**
37
+
38
+ **⚠️ 静默要求:版本检测过程完全静默,禁止输出任何与版本检测相关的信息,包括但不限于:**
39
+ - "检测到当前 IDE 版本..."
40
+ - "将使用文本交互流程..."
41
+ - "当前版本不支持..."
42
+ - 任何提及"版本"、"降级"、"兼容"等字眼
43
+
44
+ 通过检查上方「版本信息」中的占位符是否被替换来判断:
45
+
46
+ **判断逻辑:**
47
+ 1. 如果 IDE 名称仍包含 `COMATE_IDE_NAME`(未替换)→ **旧版本**
48
+ 2. 如果插件版本仍包含 `COMATE_PLUGIN_VERSION`(未替换)→ **旧版本**
49
+ 3. 如果版本号 < `4.1.0` → **旧版本**
50
+ 4. 否则 → **新版本**
51
+
52
+ 根据判断结果**直接**选择交互方式,**不输出任何解释**:
53
+ - **新版本** → 使用 `__interactive:` UI 组件交互
54
+ - **旧版本** → 使用纯文本交互(不支持 `__silent:` 和 `__interactive:` 前缀)
55
+
56
+ ---
57
+
58
+ ## 全局规则
59
+
60
+ ### 新版本 IDE 规则
61
+
62
+ **⚠️ 全局静默要求:整个流程中 Agent 仅通过 `__interactive:` UI 组件与用户交互。除步骤 7 的最终结果文字外,Agent 禁止向用户输出任何文字内容,包括但不限于:**
63
+ - **过渡性话语**:如 "Now I have the data"、"Let me perform matching"、"让我分析一下"
64
+ - **内部分析过程**:如 "Card 26: xxx - Score: 95"、"Matching analysis:"、匹配评分细节
65
+ - **状态说明**:如 "has_good_match: true"、"Cards sorted by score"
66
+ - **JSON 数据或代码片段**
67
+
68
+ **Agent 应在内部完成所有思考后,直接调用对应的 `run_command`,不在工具调用之间输出任何文字。**
69
+
70
+ **⚠️ 重要:所有 `run_command` 调用(`__interactive:` 除外)必须加 `__silent:` 前缀。唯一例外是步骤 6 的 git commit 命令,需要展示提交结果给用户。**
71
+
72
+ **⚠️ 禁止额外命令:Agent 不得在流程步骤之外自行执行任何 shell 命令(如 `git status`、`ls` 等)。iCafe 数据由步骤 1 的 Python 脚本获取,git diff 由步骤 1.5 中 Agent 按规定命令获取。**
73
+
74
+ **⚠️ 工作目录规则:Skill 执行时的工作目录可能不是用户项目目录。当命令需要在用户项目目录下执行时(如 git 操作、Python 脚本),必须在命令中加 `cd <用户项目目录> &&` 切换目录。但 `__silent:` 或 `__interactive:` 前缀必须始终在命令最开头。**
75
+
76
+ **⚠️ 多 Workspace 规则:用户可能打开了多个代码库(multi-root workspace)。环境上下文中的 `Workspace Path` 会列出所有 workspace 路径。在步骤 1.5 和步骤 6 中,Agent 必须对每个 workspace 分别执行 git 命令,不可只处理第一个 workspace 后忽略其余的。**
77
+
78
+ 正确格式:
79
+ ```
80
+ __silent: cd /path/to/project && git add .
81
+ __interactive:icafe-cards {...}
82
+ ```
83
+
84
+ 错误格式(禁止):
85
+ ```
86
+ cd /path/to/project && __silent: git add .
87
+ cd /path/to/project && __interactive:icafe-cards {...}
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 步骤 1:获取 iCafe 数据
93
+
94
+ 通过 `run_command` 执行以下命令获取 iCafe 卡片数据。**新版本 IDE 必须使用带 `__silent:` 前缀的命令;旧版本 IDE 不支持 `__silent:` 前缀,去掉前缀后直接执行。**
95
+
96
+ **新版本 IDE 完整命令(直接复制执行,包含 `__silent:` 前缀):**
97
+
98
+ ```bash
99
+ __silent: cd <用户项目目录> && PYTHONPATH="<skill_directory>/scripts" python3 -c "
100
+ import sys, json
101
+ sys.path.insert(0, '<skill_directory>/scripts')
102
+ from icafe.matching import find_matching_card
103
+ result = find_matching_card(current_user=sys.argv[1] if len(sys.argv) > 1 else None)
104
+ print(json.dumps(result))
105
+ " '${COMATE_USERNAME}'
106
+ ```
107
+
108
+ **旧版本 IDE 命令(去掉 `__silent:` 前缀):**
109
+
110
+ ```bash
111
+ cd <用户项目目录> && PYTHONPATH="<skill_directory>/scripts" python3 -c "
112
+ import sys, json
113
+ sys.path.insert(0, '<skill_directory>/scripts')
114
+ from icafe.matching import find_matching_card
115
+ result = find_matching_card(current_user=sys.argv[1] if len(sys.argv) > 1 else None)
116
+ print(json.dumps(result))
117
+ " '${COMATE_USERNAME}'
118
+ ```
119
+
120
+ 从 stdout 输出的 JSON 解析为 `result` 对象。
121
+
122
+ **⚠️ 开关检查:** 解析 `result` 后,**首先**检查 `result.get("disabled")` 是否为 `True`。如果是,**必须立即结束 skill,不再执行任何后续步骤,不输出任何内容**。
123
+
124
+ `find_matching_card()` 内部自动完成用户获取、空间检测、卡片查询等工作,返回结构化数据。**不再获取 git diff,diff 由 Agent 在步骤 1.5 中自行获取。**
125
+
126
+ ## 步骤 1.5:获取 git diff(Agent 执行,支持多 workspace,per-file 统计)
127
+
128
+ **⚠️ 多 Workspace 必须逐一执行:** Agent 必须从环境上下文的 `Workspace Path` 中读取**所有**路径。`Workspace Path` 的格式为:
129
+ ```
130
+ Workspace Path:
131
+ - /path/to/repo1
132
+ - /path/to/repo2
133
+ ```
134
+ Agent 必须对列表中的**每一个路径**分别执行下方的 git diff 命令。**即使只有部分 workspace 有变更,也必须对所有 workspace 都执行一次**,以确定每个仓库是否有变更。禁止只对第一个 workspace 执行后就跳过其余的。
135
+
136
+ **新版本 IDE 命令必须加 `__silent:` 前缀。**
137
+
138
+ 对每个 workspace 目录依次执行(**每个 workspace 单独一次 `run_command` 调用**):
139
+
140
+ ```
141
+ __silent: cd <workspace_path> && git diff HEAD --stat 2>/dev/null; echo "---DIFF_CONTENT_SEPARATOR---"; git diff HEAD --numstat 2>/dev/null; echo "---DIFF_CONTENT_SEPARATOR---"; git diff HEAD 2>/dev/null
142
+ ```
143
+
144
+ Agent 从每个 workspace 的输出中解析并在内部构建两级数据结构,**不输出任何内容**:
145
+
146
+ ### 1) `workspace_diffs` — 按 workspace 独立存储
147
+
148
+ ```
149
+ workspace_diffs = {
150
+ "<workspace_path>": {
151
+ "changed_files": [
152
+ {"file": "src/App.tsx", "insertions": 76, "deletions": 66},
153
+ {"file": "src/components/Header.tsx", "insertions": 24, "deletions": 12}
154
+ ],
155
+ "stat_summary": "2 files, +100, -78",
156
+ "has_changes": true
157
+ },
158
+ "<workspace_path_2>": {
159
+ "changed_files": [],
160
+ "stat_summary": "",
161
+ "has_changes": false
162
+ }
163
+ }
164
+ ```
165
+
166
+ ### 2) `diff_summary` — 合并后用于步骤 2 语义匹配
167
+
168
+ ```
169
+ diff_summary = {
170
+ "changed_files": [...], # 所有 workspace 的变更文件路径字符串列表(含 workspace 标识)
171
+ "stat_summary": "...", # 合并后的统计摘要
172
+ "diff_content": "...", # 合并后的 diff 全文(超过 500 行截断)
173
+ "truncated": true/false
174
+ }
175
+ ```
176
+
177
+ **解析规则:**
178
+ 1. 第一个 `---DIFF_CONTENT_SEPARATOR---` 之前是 `git diff HEAD --stat` 的输出:
179
+ - 每行 `|` 前的部分是文件路径
180
+ - 最后一行(如 "2 files changed, 15 insertions, 3 deletions")为该 workspace 的 `stat_summary`
181
+ 2. 两个 `---DIFF_CONTENT_SEPARATOR---` 之间是 `git diff HEAD --numstat` 的输出:
182
+ - 每行格式:`<insertions>\t<deletions>\t<file>`,解析为 `{"file": ..., "insertions": ..., "deletions": ...}` 加入该 workspace 的 `changed_files`
183
+ - 据此生成该 workspace 的 `stat_summary`,格式 `"N files, +X, -Y"`
184
+ 3. 第二个 `---DIFF_CONTENT_SEPARATOR---` 之后是完整 diff 内容
185
+ 4. 如果 diff 内容超过 500 行,截断并设置 `truncated = true`
186
+ 5. 多 workspace 时,合并 `diff_summary` 将各 workspace 的文件路径加上 workspace 标识,diff 内容按 workspace 分段拼接
187
+
188
+ **如果所有 workspace 均无变更(所有 `changed_files` 为空),`diff_summary` 设为 `null`。**
189
+
190
+ 同时,Agent 内部基于 diff 内容生成 `defaults.title`(建卡默认标题):取前 3 个变更文件名,生成格式为 `"优化 xxx, yyy 相关功能"`。将生成的标题写入 `result["defaults"]["title"]`。
191
+
192
+ Agent 内部分析 git diff 内容,总结代码变更的语义(修改了哪些模块、变更目的、涉及的业务领域),**不输出任何内容**,仅用于后续生成 commit message。
193
+
194
+ ## 步骤 2:语义匹配(内部完成,禁止输出)
195
+
196
+ 在展示 UI 或文本**之前**,Agent 需要在内部(不输出)完成语义匹配:
197
+ - 如果 `diff_summary` 不为 `null` 且 `result["cards"]` 非空:
198
+ 1. 根据 `diff_summary` 中的变更文件、diff 内容,对每张卡片进行语义匹配度评分(0-100 分)
199
+ - **语义相关性**(主要):diff 修改的模块、函数、业务逻辑是否与卡片标题描述的任务相关
200
+ - **类型匹配度**(次要):diff 的变更性质(修复 bug、新增功能、重构等)是否与卡片类型吻合
201
+ 2. 按 `score` 降序对 `result["cards"]` 重新排序
202
+ 3. **过滤低分卡片**:仅保留 score >= 30 的卡片,score < 30 的卡片从 `result["cards"]` 中移除
203
+ 4. 确定 `viewMode`:过滤后卡片非空 → `"list"`,过滤后卡片为空 → `"create"`
204
+ 5. 记住 `recommended_commit_message` 供后续步骤使用
205
+ - 如果 `diff_summary` 为 `null` 或卡片为空:`viewMode` 默认为 `"create"`
206
+
207
+ ## 步骤 3:展示卡片选择
208
+
209
+ **禁止跳过此步骤,禁止自行替用户选择或创建卡片。**
210
+
211
+ ### 新版本 IDE(交互式 UI)
212
+
213
+ 调用 `run_command` 展示卡片选择/新建 UI,**禁止在调用前输出任何文字**:
214
+
215
+ ```
216
+ run_command(command="__interactive:icafe-cards <payload JSON>")
217
+ ```
218
+
219
+ payload 构造方法 — 用 `result` 中的字段和匹配结果拼接 JSON:
220
+ ```python
221
+ import json
222
+ payload = json.dumps({
223
+ "cards": result["cards"], # 已按匹配度排序
224
+ "spacePrefix": result["space_prefix"],
225
+ "spaceId": result["space_id"],
226
+ "spaceName": result["space_name"],
227
+ "availableSpaces": result["available_spaces"],
228
+ "viewMode": viewMode, # "list" 或 "create"
229
+ "defaults": {
230
+ "title": result["defaults"]["title"],
231
+ "typeId": result["defaults"]["type_id"],
232
+ "spaceId": result["space_id"]
233
+ }
234
+ })
235
+ command = f"__interactive:icafe-cards {payload}"
236
+ ```
237
+
238
+ 完整示例 command 值:
239
+ ```
240
+ __interactive:icafe-cards {"cards":[{"sequence":"200","title":"修复登录问题","type":"Bug","status":"开发中"}],"spacePrefix":"dkx","spaceId":12345,"spaceName":"测试空间","viewMode":"list","availableSpaces":[{"id":12345,"prefix":"dkx","name":"测试空间"}],"defaults":{"title":"修复登录验证码刷新问题","typeId":"5009","spaceId":12345}}
241
+ ```
242
+
243
+ ### 旧版本 IDE(文本交互)
244
+
245
+ 根据 `viewMode` 输出文本列表。
246
+
247
+ **当 `viewMode == "list"`(有高匹配卡片)时:**
248
+
249
+ 先展示卡片列表(已按匹配度排序,标注匹配理由),再展示新建选项:
250
+
251
+ ```
252
+ 📋 根据代码变更,找到以下匹配的 iCafe 卡片:
253
+
254
+ 1. ⭐ [${spacePrefix}-${card1.sequence}] ${card1.title}
255
+ 类型: ${card1.type} | 状态: ${card1.status}
256
+ 匹配理由: ${reason}
257
+
258
+ 2. [${spacePrefix}-${card2.sequence}] ${card2.title}
259
+ 类型: ${card2.type} | 状态: ${card2.status}
260
+
261
+ (最多显示 10 张卡片,⭐ 标记匹配度较高的卡片)
262
+
263
+ ---
264
+ 🆕 如需新建卡片,为你推荐以下信息:
265
+ - 推荐标题:${result.defaults.title}
266
+ - 推荐空间:${spaceName} (${spacePrefix})
267
+ - 推荐类型:${推荐的类型名称}(类型 ID: ${result.defaults.type_id})
268
+
269
+ ---
270
+ 请回复:
271
+ - 输入序号(如 "1")选择对应卡片
272
+ - 输入卡片 ID(如 "DevOps-iScan-35835")直接关联
273
+ - 输入 "new" 使用推荐信息直接新建卡片
274
+ - 输入 "new 自定义标题" 使用推荐空间和类型、但自定义标题新建
275
+ - 输入 "new?" 查看所有可选空间和类型枚举
276
+ ```
277
+
278
+ **当 `viewMode == "create"`(无高匹配卡片)时:**
279
+
280
+ 先展示新建卡片推荐(突出位置),再附上已有卡片作为备选:
281
+
282
+ ```
283
+ 💡 当前代码变更与已有卡片匹配度较低,建议新建卡片:
284
+
285
+ 🆕 推荐新建卡片信息:
286
+ - 推荐标题:${result.defaults.title}
287
+ - 推荐空间:${spaceName} (${spacePrefix})
288
+ - 推荐类型:${推荐的类型名称}(类型 ID: ${result.defaults.type_id})
289
+
290
+ ---
291
+ 📋 以下是你当前活跃的卡片(供参考):
292
+
293
+ 1. [${spacePrefix}-${card1.sequence}] ${card1.title}
294
+ 类型: ${card1.type} | 状态: ${card1.status}
295
+
296
+ (最多显示 10 张卡片)
297
+
298
+ ---
299
+ 请回复:
300
+ - 输入 "new" 使用推荐信息直接新建卡片
301
+ - 输入 "new 自定义标题" 使用推荐空间和类型、但自定义标题新建
302
+ - 输入序号(如 "1")选择对应卡片
303
+ - 输入卡片 ID(如 "DevOps-iScan-35835")直接关联
304
+ - 输入 "new?" 查看所有可选空间和类型枚举
305
+ ```
306
+
307
+ 如果没有找到卡片,输出:
308
+
309
+ ```
310
+ 📋 未找到可关联的 iCafe 卡片
311
+
312
+ 🆕 为你推荐以下建卡信息:
313
+ - 推荐标题:${result.defaults.title}
314
+ - 推荐空间:${spaceName} (${spacePrefix})
315
+ - 推荐类型:${推荐的类型名称}
316
+
317
+ ---
318
+ 请回复:
319
+ - 输入卡片 ID(如 "DevOps-iScan-35835")直接关联
320
+ - 输入 "new" 使用推荐信息直接新建卡片
321
+ - 输入 "new 自定义标题" 使用推荐空间和类型、但自定义标题新建
322
+ - 输入 "new?" 查看所有可选空间和类型枚举
323
+ ```
324
+
325
+ **推荐类型名称的获取方式:** 从 `result.available_spaces` 中找到当前空间(匹配 `space_prefix`),取其 `types` 列表中 `id` 等于 `result.defaults.type_id` 的类型的 `name`。如果找不到,取该空间 `types` 列表第一个的 `name`。
326
+
327
+ ## 步骤 4:处理用户操作
328
+
329
+ ### 新版本 IDE
330
+
331
+ UI 组件返回 JSON,可能的 action 值:
332
+
333
+ | action | 含义 | 处理方式 |
334
+ |--------|------|----------|
335
+ | `select` | 选择已有卡片 | 保存 `card` 中的卡片信息,继续步骤 5 |
336
+ | `recognize` | 链接或卡片 ID 识别 | 调用 `recognize_card_cli.py` 获取卡片详情,继续步骤 5 |
337
+ | `create` | 新建卡片 | 调用 `create_card_cli.py` 创建卡片,继续步骤 5 |
338
+ | `skip` | 跳过 | 输出"已跳过卡片绑定和代码提交。",**结束 skill** |
339
+ | `do_not_show_again` | 不再提示 | 输出"已关闭推荐卡片提示。",**结束 skill** |
340
+
341
+ **recognize 处理:**
342
+ ```
343
+ __silent: cd <用户项目目录> && python3 <skill_directory>/scripts/recognize_card_cli.py --link "<用户返回的link>"
344
+ ```
345
+
346
+ **create 处理:**
347
+ ```
348
+ __silent: cd <用户项目目录> && python3 <skill_directory>/scripts/create_card_cli.py --title "<card.title>" --space-prefix "<card.spacePrefix>" --type-name "<card.typeName>" --username "${COMATE_USERNAME}"
349
+ ```
350
+
351
+ ### 旧版本 IDE
352
+
353
+ 根据用户在对话中的文本回复:
354
+
355
+ **如果用户输入序号(如 "1"、"2"):**
356
+ - 解析用户选择的卡片,保存 `selected_card` 信息,继续步骤 5
357
+
358
+ **如果用户输入卡片 ID(如 "DevOps-iScan-35835"):**
359
+ - 调用 `recognize_card_cli.py` 获取卡片详情:
360
+ ```
361
+ cd <用户项目目录> && python3 <skill_directory>/scripts/recognize_card_cli.py --link "<卡片ID>"
362
+ ```
363
+ - 保存 `selected_card` 信息,继续步骤 5
364
+
365
+ **如果用户输入 "new"(使用推荐信息直接新建):**
366
+ - 使用 `result` 中的推荐信息调用 `create_card_cli.py` 创建卡片
367
+ - 标题 = `result.defaults.title`,空间 = `result.space_prefix`
368
+ - 类型 = 从 `result.available_spaces` 中匹配当前空间,取 `types` 中 `id` 等于 `result.defaults.type_id` 的类型名称
369
+
370
+ **如果用户输入 "new 自定义标题":**
371
+ - 与 "new" 逻辑相同,但标题使用用户输入的自定义标题(去掉 "new " 前缀后的部分)
372
+
373
+ **如果用户输入 "new?"(查看空间和类型枚举):**
374
+
375
+ 从 `result.available_spaces` 输出完整枚举:
376
+
377
+ ```
378
+ 📋 可选空间和类型:
379
+
380
+ 空间 1: ${space1.name} (${space1.prefix})
381
+ 可选类型:
382
+ - ${type1.name} (ID: ${type1.id})
383
+ - ${type2.name} (ID: ${type2.id})
384
+
385
+ ---
386
+ 请回复以下格式新建卡片:
387
+ new [标题] | [空间前缀] | [类型名称]
388
+ 例如:new 修复登录问题 | dkx | Bug
389
+
390
+ 也可以只指定部分:
391
+ new 修复登录问题 | dkx → 使用指定空间 + 该空间默认类型
392
+ new 修复登录问题 | | Story → 使用推荐空间 + 指定类型
393
+ ```
394
+
395
+ **如果用户输入 "new 标题 | 空间 | 类型"(完整指定):**
396
+ - 按 `|` 分割解析,第一段为标题,第二段(可选)为空间前缀,第三段(可选)为类型名称
397
+ - 为空的部分使用推荐值,调用 `create_card_cli.py` 创建卡片
398
+
399
+ ## 步骤 4.5:存储关联的 iCafe 卡片 ID(必须执行)
400
+
401
+ 在步骤 4 处理完用户操作、拿到 `selected_card` 后,**必须**立即调用 `run_command` 将卡片 ID 保存到会话中:
402
+
403
+ ```
404
+ run_command(command="__interactive:set-icafe-issue-id {\"issueId\":\"<spacePrefix>-<sequence>\"}")
405
+ ```
406
+
407
+ 例如,如果 `selected_card` 是 `{"sequence": "200", "spacePrefix": "dkx", ...}`,则执行:
408
+
409
+ ```
410
+ run_command(command='__interactive:set-icafe-issue-id {"issueId":"dkx-200"}')
411
+ ```
412
+
413
+ ## 步骤 5:判断是否展示提交确认
414
+
415
+ Agent 内部分析以下信号判断是否展示提交确认,**不输出任何内容**:
416
+
417
+ **展示的信号(满足任意一条):**
418
+ - 当前对话中用户明确表示"完成了"、"可以提交"等意图
419
+ - git diff 的代码变更是完整的、可独立运行的
420
+ - 对话上下文表明任务已结束
421
+
422
+ **不展示(仅输出 message):**
423
+ - 用户表示还有后续修改
424
+ - 代码变更不完整
425
+ - 对话上下文表明任务仍在进行
426
+
427
+ ## 步骤 6:展示提交确认
428
+
429
+ ### 新版本 IDE(交互式 UI)
430
+
431
+ 调用 `run_command` 展示提交确认 UI:
432
+
433
+ ```
434
+ run_command(command="__interactive:git-commit <payload JSON>")
435
+ ```
436
+
437
+ Agent 对**每个 workspace** 分别执行 `git branch -vv` + `git branch -r`(使用 `__silent:` 前缀,每个 workspace 单独一次 `run_command`),解析各自的分支信息。然后构造 payload:
438
+
439
+ **⚠️ 重要:`workspaces` 数组必须包含环境上下文 `Workspace Path` 中列出的所有 workspace,不可遗漏。** 即使某个 workspace 没有变更(`hasChanges: false`),也必须包含在数组中。
440
+
441
+ payload 结构(多 workspace 格式):
442
+ ```json
443
+ {
444
+ "commitMessage": "dkx-200 修复登录问题",
445
+ "boundCard": {"sequence": "200", "title": "修复登录问题", "type": "Bug", "status": "开发中", "spacePrefix": "dkx"},
446
+ "workspaces": [
447
+ {
448
+ "workspace": "/path/to/frontend-app",
449
+ "repoName": "frontend-app",
450
+ "currentBranch": "feature/xxx",
451
+ "remoteBranches": [{"name": "feature/xxx", "isCurrent": true}, {"name": "main", "isCurrent": false}],
452
+ "hasChanges": true,
453
+ "diffSummary": {
454
+ "changed_files": [{"file": "src/App.tsx", "insertions": 76, "deletions": 66}],
455
+ "stat_summary": "2 files, +100, -78"
456
+ }
457
+ },
458
+ {
459
+ "workspace": "/path/to/shared-utils",
460
+ "repoName": "shared-utils",
461
+ "currentBranch": "main",
462
+ "remoteBranches": [{"name": "main", "isCurrent": true}],
463
+ "hasChanges": false,
464
+ "diffSummary": null
465
+ }
466
+ ]
467
+ }
468
+ ```
469
+
470
+ **构造规则:**
471
+ - `commitMessage`:基于 diff 和绑定卡片生成的 commit message(格式 `"<spacePrefix>-<sequence> <brief_description>"`)
472
+ - `boundCard`:步骤 4 中选定的卡片信息
473
+ - `workspaces`:对每个 workspace 目录,使用步骤 1.5 中构建的 `workspace_diffs` 数据:
474
+ - `workspace`:绝对路径
475
+ - `repoName`:路径的最后一段
476
+ - `currentBranch`:从 `git branch -vv` 解析当前分支名
477
+ - `remoteBranches`:从 `git branch -r` 解析远程分支列表,标记当前远程追踪分支为 `isCurrent: true`
478
+ - `hasChanges`:该 workspace 是否有变更(`workspace_diffs[path].has_changes`)
479
+ - `diffSummary`:有变更时为 `workspace_diffs[path]` 中的 `changed_files` + `stat_summary`,无变更时为 `null`
480
+
481
+ **顶层不再有旧的 `currentBranch`/`remoteBranches`/`diffSummary` 字段。**
482
+
483
+ 完整示例 command 值:
484
+ ```
485
+ __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"}}]}
486
+ ```
487
+
488
+ 用户操作后,tool output 返回 JSON:
489
+ - 确认提交:`{"action": "submit", "repos": [{"workspace": "...", "commitMessage": "...", "branch": "..."}]}`
490
+ - 取消提交:`{"action": "cancel"}`
491
+
492
+ ### 旧版本 IDE(文本确认)
493
+
494
+ 输出:
495
+
496
+ ```
497
+ ✅ 已关联卡片: ${spacePrefix}-${sequence}
498
+ 标题: ${title}
499
+ 类型: ${type} | 状态: ${status}
500
+
501
+ ---
502
+ 📝 建议的 commit message:
503
+
504
+ ${spacePrefix}-${sequence} ${brief_description}
505
+
506
+ ---
507
+ 请确认:
508
+ - 回复 "ok" 或 "确认" 使用此 message 提交
509
+ - 回复 "edit: <新message>" 修改后提交(如 "edit: dkx-200 修复登录bug")
510
+ - 回复 "no" 或 "取消" 放弃提交
511
+ ```
512
+
513
+ ## 步骤 7:执行提交 + 输出结果
514
+
515
+ ### 新版本 IDE
516
+
517
+ 从 tool output 解析用户操作:
518
+
519
+ **如果是 action === "submit":**
520
+
521
+ UI 返回的结果格式:
522
+ ```json
523
+ {"action": "submit", "repos": [{"workspace": "/path/to/repo", "commitMessage": "dkx-200 修复...", "branch": "feature/xxx"}]}
524
+ ```
525
+
526
+ Agent 收到后,对 `repos` 数组中的每个仓库自主决定执行方式:
527
+ - `cd` 到对应 workspace 目录
528
+ - 执行 `git add .`、`git commit -m "<commitMessage>"`(git commit 命令不使用 `__silent:`,展示提交结果给用户)
529
+ - 如果用户选择了特定分支且不是当前分支,先 `git checkout` 切换
530
+ - 执行 `git push origin <branch>` 推送到远程
531
+ - 多仓库时逐个执行,每个仓库独立处理
532
+
533
+ **如果是 action === "cancel":**
534
+ - 输出"已取消提交"
535
+
536
+ ### 旧版本 IDE
537
+
538
+ **如果用户确认提交(回复 "ok"、"确认"、"yes"):**
539
+ - 执行 `git add . && git commit -m "${commit_message}"`
540
+
541
+ **如果用户修改后提交(回复 "edit: <新message>"):**
542
+ - 使用用户提供的新 message 执行提交
543
+
544
+ **如果用户取消(回复 "no"、"取消"):**
545
+ - 输出取消信息
546
+
547
+ ### 最终输出格式
548
+
549
+ **提交成功:**
550
+ ```
551
+ ✅ 已完成提交
552
+
553
+ 提交信息:
554
+ - Commit: <commit_hash>
555
+ - Message: <commit_message>
556
+ - 绑定卡片: <space_prefix>-<sequence>
557
+ - 分支: <branch_name>
558
+ ```
559
+
560
+ **取消提交:**
561
+ ```
562
+ ⏸️ 提交已取消
563
+
564
+ 建议 commit message 已准备好:
565
+ <commit_message>
566
+
567
+ 绑定卡片:<space_prefix>-<sequence> (<card_title>)
568
+
569
+ 你可以稍后使用 `git commit -m "<message>"` 手动提交
570
+ ```
571
+
572
+ **判断不展示 UI(直接输出 message):**
573
+ ```
574
+ 📝 Commit message 已准备好
575
+
576
+ 建议 commit message:
577
+ <commit_message>
578
+
579
+ 绑定卡片:<space_prefix>-<sequence> (<card_title>)
580
+
581
+ 代码变更未完成,请确认后再提交
582
+ ```
583
+
584
+ 旧版本 IDE 提交成功后额外提示:`如需推送到远程,请执行:git push`
585
+
586
+ ---
587
+
588
+ ## 返回值说明
589
+
590
+ ### `find_matching_card()` 返回字典
591
+
592
+ | 字段 | 说明 |
593
+ |------|------|
594
+ | cards | 简化卡片列表:sequence, title, type, status |
595
+ | space_prefix | 空间前缀(如 "dkx") |
596
+ | space_id | 空间数字 ID |
597
+ | space_name | 空间名称 |
598
+ | final_iql | 实际执行的完整 IQL |
599
+ | available_types | 可绑定卡片类型列表:[{id, name}, ...] |
600
+ | available_spaces | 可访问空间列表:[{id, prefix, name}, ...] |
601
+ | defaults | 默认表单值:{title, type_id, space_id}(title 由 Agent 在步骤 1.5 中生成) |
602
+
603
+ ### `diff_summary`(Agent 在步骤 1.5 中构建)
604
+
605
+ | 字段 | 说明 |
606
+ |------|------|
607
+ | changed_files | 所有 workspace 的变更文件路径字符串列表(用于步骤 2 语义匹配) |
608
+ | stat_summary | 合并后的 git diff --stat 统计行 |
609
+ | diff_content | 合并后的 diff 全文(超过 500 行截断) |
610
+ | truncated | 是否被截断 |
611
+
612
+ ### `workspace_diffs`(Agent 在步骤 1.5 中构建,用于步骤 6 构造 payload)
613
+
614
+ | 字段 | 说明 |
615
+ |------|------|
616
+ | \<workspace_path\>.changed_files | 该 workspace 的 `[{file, insertions, deletions}]` 列表 |
617
+ | \<workspace_path\>.stat_summary | 该 workspace 的统计摘要(如 "2 files, +100, -78") |
618
+ | \<workspace_path\>.has_changes | 该 workspace 是否有变更 |
619
+
620
+ ## 卡片链接
621
+
622
+ ```
623
+ https://console.cloud.baidu-int.com/devops/icafe/issue/{space_prefix}-{card_sequence}/show
624
+ ```
625
+
626
+ ## 配置
627
+
628
+ ### 认证
629
+
630
+ token 按优先级读取:
631
+ 1. 环境变量 `COMATE_AUTH_TOKEN`
632
+ 2. 文件 `~/.comate/login`
633
+
634
+ ### 资源
635
+
636
+ - **scripts/icafe/** — 核心实现包
637
+ - `client.py` — ICafeQueryClient、常量、配置、API 客户端
638
+ - `matching.py` — `find_matching_card()` 主入口、匹配逻辑
639
+ - `farseer.py` — `get_binding_card_types()` 获取可绑定卡片类型
640
+ - **scripts/git_utils.py** — diff 摘要、用户获取、git log 提取
641
+ - **scripts/create_card_cli.py** — 创建卡片命令行工具
642
+ - **scripts/recognize_card_cli.py** — 识别卡片命令行工具
643
+ - **scripts/compat.py** — 版本兼容性检测模块
644
+ - **scripts/logger.py** — 统一日志模块
645
+ - **references/query_reference.md** — IQL 语法参考
646
+ - **references/issue_type_mapping.json** — 卡片类型 ID 映射
@@ -0,0 +1,19 @@
1
+ {
2
+ "56075": "Epic",
3
+ "54443": "Feature",
4
+ "5007": "Story",
5
+ "54444": "Task",
6
+ "54621": "Tech Feature",
7
+ "54622": "Tech Task",
8
+ "5009": "Bug",
9
+ "5811": "Bug(线上)",
10
+ "5011": "Case",
11
+ "65085": "非研发任务",
12
+ "49460": "项目",
13
+ "5008": "需求",
14
+ "5010": "任务",
15
+ "88805": "Prompt Story",
16
+ "88806": "Prompt Task",
17
+ "88807": "GenAI Data Story",
18
+ "88808": "GenAI Data Task"
19
+ }