@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
package/README.md CHANGED
@@ -75,11 +75,19 @@ zulu run [args]
75
75
  | `--mode` | | string | 使用模式,默认 `Agent`,可选 `Ask` 或 `Plan` |
76
76
  | `--ripgrep` | | string | `ripgrep` 的路径 |
77
77
  | `--cwd` | | string | 当前工作区路径 |
78
+ | `--retry` | | string | 最大自动重试次数;当最后一轮返回不是文本或执行报错时,CLI 会继续追加一轮重试 |
79
+ | `--retry-query` | | string | 每次自动重试时追加发送的 query,需与 `--retry` 同时使用,例如传 `继续` |
78
80
  | `--display` | `-d` | string | 输出模式,默认 `task`,可选 `legacy`、`record`、`event-stream`、`record-stream` |
79
81
 
82
+ 补充说明:
83
+ - `--retry` 必须是大于等于 `0` 的整数
84
+ - `--retry` 和 `--retry-query` 必须同时传入
85
+ - `--display legacy` 不支持 `--retry`
86
+
80
87
  示例:
81
88
  ```shell
82
89
  zulu run --query="你好" --license=xxxx
90
+ zulu run --query="请总结当前仓库" --license=xxxx --retry=2 --retry-query="继续"
83
91
  ```
84
92
 
85
93
  ### 查询模型
@@ -0,0 +1,386 @@
1
+ ---
2
+ name: auto-commit
3
+ description: 当用户完成代码修改、需要提交代码时,必须使用此 skill,而非直接执行 git commit。自动获取 git diff、匹配 iCafe 活跃卡片、生成 commit message,并引导用户完成绑定卡片和代码提交。
4
+ metadata:
5
+ enableWhen:
6
+ - isInternalMission
7
+ ---
8
+
9
+ # 智能提交助手
10
+
11
+ ## 版本信息
12
+
13
+ - **IDE 名称**: ${COMATE_IDE_NAME}
14
+ - **插件版本**: ${COMATE_PLUGIN_VERSION}
15
+ - **用户名**: ${COMATE_USERNAME}
16
+
17
+ ## 概述
18
+
19
+ 本技能将当前工作区的 git diff 与用户在 iCafe 上的活跃卡片进行匹配,支持选择已有卡片或新建卡片,自动生成 commit message 并完成提交。
20
+
21
+ **调起即执行,流程完全固定,不做任何意图分析。**
22
+
23
+ ## 步骤 0:前置检查(串行执行,完全静默)
24
+
25
+ **⚠️ 此步骤必须在所有其他步骤之前执行。必须按 0a → 0b 的顺序串行执行,确保每一步都完成后再进入下一步。**
26
+
27
+ **⚠️ 静默要求:整个前置检查过程完全静默,禁止输出任何相关信息,包括但不限于:**
28
+ - "检测到当前 IDE 版本..."
29
+ - "将使用文本交互流程..."
30
+ - "当前版本不支持..."
31
+ - 任何提及"版本"、"降级"、"兼容"、"开关"等字眼
32
+
33
+ ### 0a. 开关检查(本地用户偏好)
34
+
35
+ **说明:此检查读取用户本地配置,是用户个人的开关偏好。步骤 1 中的 `result.disabled` 是服务端/空间级别的开关,两者独立,互不替代。**
36
+
37
+ 通过以下方式进行检查(**必须加 `__silent:` 前缀**):
38
+
39
+ ```
40
+ __silent: cat ~/.comate/settings.json 2>/dev/null || echo '{}'
41
+ ```
42
+
43
+ 解析返回的 JSON,检查 `enableSmartCommit` 字段:
44
+ - 如果 `enableSmartCommit` 为 `false` → **立即结束 skill,不再输出任何内容,不再执行任何后续步骤**
45
+ - 如果 `enableSmartCommit` 为 `true` 或字段不存在(默认开启)→ **继续执行 0b**
46
+
47
+ ### 0b. 版本兼容性检查
48
+
49
+ **⚠️ 必须在 0a 完成后执行此步骤,不可跳过。**
50
+
51
+ 通过检查上方「版本信息」中的占位符是否被替换来判断:
52
+
53
+ **判断逻辑:**
54
+ 1. 如果 IDE 名称仍包含 `COMATE_IDE_NAME`(未替换)→ **旧版本**
55
+ 2. 如果插件版本仍包含 `COMATE_PLUGIN_VERSION`(未替换)→ **旧版本**
56
+ 3. 如果版本号 < `4.1.0` → **旧版本**
57
+ 4. 否则 → **新版本**
58
+
59
+ **版本判断完成后,根据结果选择交互方式,不输出任何解释:**
60
+ - **新版本** → 请参考 `references/new_version_instruction.md`
61
+ - **旧版本** → 请参考 `references/old_version_instruction.md`
62
+
63
+ ---
64
+
65
+ ## 步骤 1:获取 iCafe 数据
66
+
67
+ 通过 `run_command` 执行以下命令获取 iCafe 卡片数据。**新版本加 `__silent:` 前缀,旧版本不加。**
68
+
69
+ ```bash
70
+ [__silent: ]cd <用户项目目录> && PYTHONPATH="<skill_directory>/scripts" python3 -c "
71
+ import sys, json
72
+ sys.path.insert(0, '<skill_directory>/scripts')
73
+ from icafe.matching import find_matching_card
74
+ result = find_matching_card(current_user=sys.argv[1] if len(sys.argv) > 1 else None)
75
+ print(json.dumps(result))
76
+ " '${COMATE_USERNAME}'
77
+ ```
78
+
79
+ 从 stdout 输出的 JSON 解析为 `result` 对象。
80
+
81
+ **⚠️ 开关检查(服务端/空间级别):** 解析 `result` 后,**首先**检查 `result.get("disabled")` 是否为 `True`。如果是,**必须立即结束 skill,不再执行任何后续步骤,不输出任何内容**。此开关与步骤 0a 的本地用户偏好开关独立,由服务端控制。
82
+
83
+ ### iCafe 获取失败降级
84
+
85
+ **如果步骤 1 的命令执行失败(脚本报错、超时、返回非 JSON 等),Agent 不应中断流程,而是进入"无卡片模式":**
86
+ 1. 标记 `icafe_failed = true`
87
+ 2. 步骤 2 正常执行(获取 git diff 和 commit style 不依赖 iCafe)
88
+ 3. **跳过步骤 3(语义匹配)、步骤 4(卡片选择)、步骤 5(处理用户操作)、步骤 6(存储卡片 ID)**
89
+ 4. 直接进入步骤 7,基于 diff 内容和 `commit_style` 生成 commit message(不带卡片 ID 前缀)
90
+ 5. 步骤 8 展示提交确认时,`boundCard` 为 `null`,commit message 中不包含卡片信息
91
+
92
+ `find_matching_card()` 内部自动完成用户获取、空间检测、卡片查询等工作,返回结构化数据。**不再获取 git diff,diff 由 Agent 在步骤 2 中自行获取。**
93
+
94
+ **⚠️ 并行执行:步骤 1 和步骤 2 之间无依赖关系。Agent 必须在同一次响应中同时发出步骤 1 的 iCafe 命令、步骤 2 的所有 git diff 命令(每个 workspace 一条)以及步骤 2 的 git log 命令,由客户端并行执行。** 多 workspace 时,不同 workspace 的 git 命令也一起并行发出。例如 2 个 workspace = 1(iCafe)+ 2(git diff)+ 1(git log)= 4 条并行 `run_command`。
95
+
96
+ ## 步骤 2:获取 git diff(支持多 workspace)
97
+
98
+ **⚠️ 多 Workspace 必须逐一执行:** Agent 必须从环境上下文的 `Workspace Path` 中读取**所有**路径。`Workspace Path` 的格式为:
99
+ ```
100
+ Workspace Path:
101
+ - /path/to/repo1
102
+ - /path/to/repo2
103
+ ```
104
+ Agent 必须对列表中的**每一个路径**分别执行下方的命令。**即使只有部分 workspace 有变更,也必须对所有 workspace 都执行一次**,以确定每个仓库是否有变更。禁止只对第一个 workspace 执行后就跳过其余的。
105
+
106
+ ### 命令格式
107
+
108
+ 对每个 workspace 执行(**新版本加 `__silent:` 前缀,旧版本不加**):
109
+
110
+ ```bash
111
+ [__silent: ]python3 <skill_directory>/scripts/git_diff_cli.py --workspace <workspace_path>
112
+ ```
113
+
114
+ 脚本输出 JSON,直接解析为该 workspace 的 diff 数据:
115
+ ```json
116
+ {
117
+ "workspace": "/path/to/project",
118
+ "changed_files": [
119
+ {"file": "src/App.tsx", "insertions": 76, "deletions": 66},
120
+ {"file": "src/NewFile.tsx", "insertions": 30, "deletions": 0}
121
+ ],
122
+ "untracked_files": ["src/NewFile.tsx"],
123
+ "stat_summary": "2 files, +106, -66",
124
+ "has_changes": true,
125
+ "diff_content": "<tracked diff + untracked diff>",
126
+ "truncated": false
127
+ }
128
+ ```
129
+
130
+ ### 获取历史 commit message 风格
131
+
132
+ **与 git diff 并行执行。** 对**第一个** workspace 执行以下命令获取最近的 commit message 记录(**新版本加 `__silent:` 前缀,旧版本不加**):
133
+
134
+ ```bash
135
+ [__silent: ]cd <第一个workspace_path> && git log --oneline -n 20
136
+ ```
137
+
138
+ Agent 从输出中提取最近 20 条 commit message,分析其格式特征(包括但不限于):
139
+ - **前缀格式**:是否使用卡片 ID 前缀(如 `dkx-200`)、Conventional Commits 前缀(如 `feat:`, `fix:`)、或其他自定义前缀
140
+ - **语言**:commit message 使用中文还是英文
141
+ - **描述风格**:简短描述 vs 详细描述、使用动词开头 vs 名词短语
142
+ - **分隔符**:前缀与描述之间使用空格、冒号还是其他分隔符
143
+
144
+ 将分析结果记为 `commit_style`,供步骤 3 生成 `recommended_commit_message` 时参考。**不输出任何内容。**
145
+
146
+ ### 构建数据结构
147
+
148
+ Agent 从各 workspace 的 JSON 输出构建两级数据结构,**不输出任何内容**:
149
+
150
+ #### 1) `workspace_diffs` — 按 workspace 独立存储
151
+
152
+ 直接使用脚本输出的 `changed_files`、`stat_summary`、`has_changes` 字段:
153
+
154
+ ```
155
+ workspace_diffs = {
156
+ "<workspace_path>": {
157
+ "changed_files": [...], // 脚本输出的 changed_files
158
+ "stat_summary": "...", // 脚本输出的 stat_summary
159
+ "has_changes": true/false // 脚本输出的 has_changes
160
+ }
161
+ }
162
+ ```
163
+
164
+ #### 2) `diff_summary` — 合并后用于步骤 3 语义匹配
165
+
166
+ ```
167
+ diff_summary = {
168
+ "changed_files": [...], # 所有 workspace 的变更文件路径字符串列表(含 workspace 标识)
169
+ "stat_summary": "...", # 合并后的统计摘要
170
+ "diff_content": "...", # 各 workspace 的 diff_content 拼接,超过 500 行截断
171
+ "truncated": true/false
172
+ }
173
+ ```
174
+
175
+ **合并规则:**
176
+ 1. `changed_files`:所有 workspace 的文件路径,多 workspace 时加 workspace 标识
177
+ 2. `diff_content`:各 workspace 的 `diff_content` 按 workspace 分段拼接,总计超过 500 行则截断
178
+ 3. 多 workspace 时,`stat_summary` 为各 workspace 统计的汇总
179
+
180
+ **如果所有 workspace 均无变更(所有 `has_changes` 为 false),`diff_summary` 设为 `null`。**
181
+
182
+ ### 无变更提前退出
183
+
184
+ **如果 `diff_summary` 为 `null`(即所有 workspace 均无变更),Agent 必须立即输出以下提示并结束 skill,不再执行步骤 3-9:**
185
+
186
+ ```
187
+ ℹ️ 当前工作区没有检测到代码变更,无需提交。
188
+
189
+ 你可以先修改代码,之后再使用 /auto-commit 提交。
190
+ ```
191
+
192
+ **新版本和旧版本均直接输出上述文本(不走 `__interactive` UI),输出后立即结束,禁止继续执行后续步骤。**
193
+
194
+ ---
195
+
196
+ 同时,Agent 内部基于 diff 内容生成 `defaults.title`(建卡默认标题):取前 3 个变更文件名,生成格式为 `"优化 xxx, yyy 相关功能"`。将生成的标题写入 `result["defaults"]["title"]`。
197
+
198
+ Agent 内部分析 git diff 内容,总结代码变更的语义(修改了哪些模块、变更目的、涉及的业务领域),**不输出任何内容**,仅用于后续生成 commit message。
199
+
200
+ ## 步骤 3:语义匹配(内部完成,禁止输出)
201
+
202
+ 在展示 UI 或文本**之前**,Agent 需要在内部(不输出)完成语义匹配:
203
+ **注意:执行到此步骤时,`diff_summary` 一定不为 `null`(无变更已在步骤 2 提前退出)。**
204
+
205
+ - 如果 `result["cards"]` 非空:
206
+ 1. 根据 `diff_summary` 中的变更文件、diff 内容,对每张卡片进行语义匹配度评分(0-100 分)
207
+ - **语义相关性**(主要):diff 修改的模块、函数、业务逻辑是否与卡片标题描述的任务相关
208
+ - **类型匹配度**(次要):diff 的变更性质(修复 bug、新增功能、重构等)是否与卡片类型吻合
209
+ 2. 按 `score` 降序对 `result["cards"]` 重新排序
210
+ 3. **过滤低分卡片**:仅保留 score >= 30 的卡片,score < 30 的卡片从 `result["cards"]` 中移除
211
+ 4. 确定 `viewMode`:过滤后卡片非空 → `"list"`,过滤后卡片为空 → `"create"`
212
+ 5. **生成 `recommended_commit_message`**:基于 diff 内容和匹配卡片生成 commit message,**必须参考步骤 2 中获取的 `commit_style`(历史 commit message 风格)**,确保生成的 message 与项目历史提交风格保持一致。具体规则:
213
+ - 如果历史 message 使用了特定的前缀格式(如 `feat:`, `fix:`, `chore:` 等 Conventional Commits 格式),生成的 message 也应使用相同格式
214
+ - 如果历史 message 使用中文描述,生成的 message 也应使用中文;反之使用英文
215
+ - 如果历史 message 使用 `<卡片ID> <描述>` 格式,则沿用该格式
216
+ - 如果历史记录中无法识别出明确的风格模式,则使用默认格式 `<spacePrefix>-<sequence> <简要描述>`
217
+ 6. 记住 `recommended_commit_message` 供后续步骤使用
218
+ - 如果 `result["cards"]` 为空:`viewMode` 默认为 `"create"`
219
+
220
+ ## 步骤 4:展示卡片选择
221
+
222
+ **上下文快捷匹配:** 如果当前对话上下文中用户已明确指定了卡片(如提到了卡片 ID "dkx-200"、iCafe 链接、或说"用上次的卡片"),Agent 可直接将该卡片作为 `selected_card`,跳过展示选择 UI,直接进入步骤 6。
223
+
224
+ **否则,必须展示卡片选择 UI,禁止自行替用户选择或创建卡片。**
225
+
226
+ 根据版本使用对应的交互方式:
227
+ - **新版本**:请参考 `references/new_version_instruction.md`
228
+ - **旧版本**:请参考 `references/old_version_instruction.md`
229
+
230
+ ## 步骤 5:处理用户操作
231
+
232
+ 根据版本使用对应的处理方式:
233
+ - **新版本**:请参考 `references/new_version_instruction.md`
234
+ - **旧版本**:请参考 `references/old_version_instruction.md`
235
+
236
+ ### 创建卡片命令模板
237
+
238
+ 当用户操作需要新建卡片时(新版本 action=create,旧版本输入 "new"),使用以下命令(**新版本加 `__silent:` 前缀,旧版本不加**):
239
+
240
+ ```
241
+ [__silent: ]cd <用户项目目录> && python3 <skill_directory>/scripts/create_card_cli.py --title "<card.title>" --space-prefix "<card.spacePrefix>" --type-name "<card.typeName>" --username "${COMATE_USERNAME}"
242
+ ```
243
+
244
+ ## 步骤 6:存储关联的 iCafe 卡片 ID(必须执行)
245
+
246
+ 在步骤 5 处理完用户操作、拿到 `selected_card` 后,**必须**立即调用 `run_command` 将卡片 ID 保存到会话中:
247
+
248
+ ```
249
+ run_command(command="__interactive:set-icafe-issue-id {\"issueId\":\"<spacePrefix>-<sequence>\"}")
250
+ ```
251
+
252
+ 例如,如果 `selected_card` 是 `{"sequence": "200", "spacePrefix": "dkx", ...}`,则执行:
253
+
254
+ ```
255
+ run_command(command='__interactive:set-icafe-issue-id {"issueId":"dkx-200"}')
256
+ ```
257
+
258
+ ## 步骤 7:判断是否展示提交确认
259
+
260
+ Agent 内部分析以下信号判断是否展示提交确认,**不输出任何内容**:
261
+
262
+ **展示的信号(满足任意一条):**
263
+ - 当前对话中用户明确表示"完成了"、"可以提交"等意图
264
+ - git diff 的代码变更是完整的、可独立运行的
265
+ - 对话上下文表明任务已结束
266
+
267
+ **不展示(仅输出 message):**
268
+ - 用户表示还有后续修改
269
+ - 代码变更不完整
270
+ - 对话上下文表明任务仍在进行
271
+
272
+ ## 步骤 8:展示提交确认
273
+
274
+ 根据版本使用对应的交互方式:
275
+ - **新版本**:请参考 `references/new_version_instruction.md`
276
+ - **旧版本**:请参考 `references/old_version_instruction.md`
277
+
278
+ ## 步骤 9:执行提交 + 输出结果
279
+
280
+ 根据版本使用对应的处理方式:
281
+ - **新版本**:请参考 `references/new_version_instruction.md`
282
+ - **旧版本**:请参考 `references/old_version_instruction.md`
283
+
284
+ ### 最终输出格式
285
+
286
+ **提交成功:**
287
+ ```
288
+ ✅ 已完成提交
289
+
290
+ 提交信息:
291
+ - Commit: <commit_hash>
292
+ - Message: <commit_message>
293
+ - 绑定卡片: <space_prefix>-<sequence>
294
+ - 分支: <branch_name>
295
+ ```
296
+
297
+ **取消提交:**
298
+ ```
299
+ ⏸️ 提交已取消
300
+
301
+ 建议 commit message 已准备好:
302
+ <commit_message>
303
+
304
+ 绑定卡片:<space_prefix>-<sequence> (<card_title>)
305
+
306
+ 你可以稍后使用 `git commit -m "<message>"` 手动提交
307
+ ```
308
+
309
+ **判断不展示 UI(直接输出 message):**
310
+ ```
311
+ 📝 Commit message 已准备好
312
+
313
+ 建议 commit message:
314
+ <commit_message>
315
+
316
+ 绑定卡片:<space_prefix>-<sequence> (<card_title>)
317
+
318
+ 代码变更未完成,请确认后再提交
319
+ ```
320
+
321
+ 旧版本 IDE 提交成功后额外提示:`如需推送到远程,请执行:git push`
322
+
323
+ ---
324
+
325
+ ## 返回值说明
326
+
327
+ ### `find_matching_card()` 返回字典
328
+
329
+ | 字段 | 说明 |
330
+ |------|------|
331
+ | cards | 简化卡片列表:sequence, title, type, status |
332
+ | space_prefix | 空间前缀(如 "dkx") |
333
+ | space_id | 空间数字 ID |
334
+ | space_name | 空间名称 |
335
+ | final_iql | 实际执行的完整 IQL |
336
+ | available_types | 可绑定卡片类型列表:[{id, name}, ...] |
337
+ | available_spaces | 可访问空间列表:[{id, prefix, name}, ...] |
338
+ | defaults | 默认表单值:{title, type_id, space_id}(title 由 Agent 在步骤 2 中生成) |
339
+
340
+ ### `diff_summary`(Agent 在步骤 2 中构建)
341
+
342
+ | 字段 | 说明 |
343
+ |------|------|
344
+ | changed_files | 所有 workspace 的变更文件路径字符串列表(用于步骤 3 语义匹配) |
345
+ | stat_summary | 合并后的 git diff --stat 统计行 |
346
+ | diff_content | 合并后的 diff 全文(超过 500 行截断) |
347
+ | truncated | 是否被截断 |
348
+
349
+ ### `workspace_diffs`(Agent 在步骤 2 中构建,用于步骤 8 构造 payload)
350
+
351
+ | 字段 | 说明 |
352
+ |------|------|
353
+ | \<workspace_path\>.changed_files | 该 workspace 的 `[{file, insertions, deletions}]` 列表 |
354
+ | \<workspace_path\>.stat_summary | 该 workspace 的统计摘要(如 "2 files, +100, -78") |
355
+ | \<workspace_path\>.has_changes | 该 workspace 是否有变更 |
356
+
357
+ ## 卡片链接
358
+
359
+ ```
360
+ https://console.cloud.baidu-int.com/devops/icafe/issue/{space_prefix}-{card_sequence}/show
361
+ ```
362
+
363
+ ## 配置
364
+
365
+ ### 认证
366
+
367
+ token 按优先级读取:
368
+ 1. 环境变量 `COMATE_AUTH_TOKEN`
369
+ 2. 文件 `~/.comate/login`
370
+
371
+ ### 资源
372
+
373
+ - **scripts/icafe/** — 核心实现包
374
+ - `client.py` — ICafeQueryClient、常量、配置、API 客户端
375
+ - `matching.py` — `find_matching_card()` 主入口、匹配逻辑
376
+ - `farseer.py` — `get_binding_card_types()` 获取可绑定卡片类型
377
+ - **scripts/git_utils.py** — diff 摘要、用户获取、git log 提取
378
+ - **scripts/git_diff_cli.py** — git diff 摘要命令行工具(步骤 2)
379
+ - **scripts/create_card_cli.py** — 创建卡片命令行工具
380
+ - **scripts/recognize_card_cli.py** — 识别卡片命令行工具
381
+ - **scripts/compat.py** — 版本兼容性检测模块
382
+ - **scripts/logger.py** — 统一日志模块
383
+ - **references/query_reference.md** — IQL 语法参考
384
+ - **references/issue_type_mapping.json** — 卡片类型 ID 映射
385
+ - **references/new_version_instruction.md** — 新版本 IDE 交互指南
386
+ - **references/old_version_instruction.md** — 旧版本 IDE 交互指南
@@ -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
+ }
@@ -0,0 +1,196 @@
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
+ "spaceId": result["space_id"]
73
+ }
74
+ })
75
+ command = f"__interactive:icafe-cards {payload}"
76
+ ```
77
+
78
+ 完整示例 command 值:
79
+ ```
80
+ __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}}
81
+ ```
82
+
83
+ ---
84
+
85
+ ## 步骤 5:处理用户操作(新版本 IDE)
86
+
87
+ UI 组件返回 JSON,可能的 action 值:
88
+
89
+ | action | 含义 | 处理方式 |
90
+ |--------|------|----------|
91
+ | `select` | 选择已有卡片 | 保存 `card` 中的卡片信息,继续步骤 7 |
92
+ | `recognize` | 链接或卡片 ID 识别 | 调用 `recognize_card_cli.py` 获取卡片详情,继续步骤 7 |
93
+ | `create` | 新建卡片 | 调用 `create_card_cli.py` 创建卡片,继续步骤 7 |
94
+ | `skip` | 跳过 | 输出"已跳过卡片绑定和代码提交。",**结束 skill** |
95
+ | `do_not_show_again` | 不再提示 | 输出"已关闭推荐卡片提示。",**结束 skill** |
96
+
97
+ **recognize 处理:**
98
+ ```
99
+ __silent: cd <用户项目目录> && python3 <skill_directory>/scripts/recognize_card_cli.py --link "<用户返回的link>"
100
+ ```
101
+
102
+ **create 处理:**
103
+
104
+ 使用 SKILL.md 步骤 5 中定义的「创建卡片命令模板」,**加 `__silent:` 前缀**执行。
105
+
106
+ ---
107
+
108
+ ## 步骤 8:展示提交确认(交互式 UI)
109
+
110
+ 调用 `run_command` 展示提交确认 UI:
111
+
112
+ ```
113
+ run_command(command="__interactive:git-commit <payload JSON>")
114
+ ```
115
+
116
+ Agent 仅对 **`hasChanges: true` 的 workspace** 执行 `git branch -vv` + `git branch -r --sort=-committerdate`(使用 `__silent:` 前缀)。**无变更的 workspace 跳过分支查询,`currentBranch` 和 `remoteBranches` 使用空值。** 多 workspace 时,不同 workspace 的分支查询命令必须在同一次响应中并行发出。然后构造 payload:
117
+
118
+ **⚠️ 重要:`workspaces` 数组必须包含环境上下文 `Workspace Path` 中列出的所有 workspace,不可遗漏。** 即使某个 workspace 没有变更(`hasChanges: false`),也必须包含在数组中。
119
+
120
+ payload 结构(多 workspace 格式):
121
+ ```json
122
+ {
123
+ "commitMessage": "dkx-200 修复登录问题",
124
+ "boundCard": {"sequence": "200", "title": "修复登录问题", "type": "Bug", "status": "开发中", "spacePrefix": "dkx"},
125
+ "workspaces": [
126
+ {
127
+ "workspace": "/path/to/frontend-app",
128
+ "repoName": "frontend-app",
129
+ "currentBranch": "feature/xxx",
130
+ "remoteBranches": [{"name": "feature/xxx", "isCurrent": true}, {"name": "main", "isCurrent": false}],
131
+ "hasChanges": true,
132
+ "diffSummary": {
133
+ "changed_files": [{"file": "src/App.tsx", "insertions": 76, "deletions": 66}],
134
+ "stat_summary": "2 files, +100, -78"
135
+ }
136
+ },
137
+ {
138
+ "workspace": "/path/to/shared-utils",
139
+ "repoName": "shared-utils",
140
+ "currentBranch": "",
141
+ "remoteBranches": [],
142
+ "hasChanges": false,
143
+ "diffSummary": null
144
+ }
145
+ ]
146
+ }
147
+ ```
148
+
149
+ **构造规则:**
150
+ - `commitMessage`:基于 diff 和绑定卡片生成的 commit message(格式 `"<spacePrefix>-<sequence> <brief_description>"`)
151
+ - `boundCard`:步骤 5 中选定的卡片信息
152
+ - `workspaces`:对每个 workspace 目录,使用步骤 2 中构建的 `workspace_diffs` 数据:
153
+ - `workspace`:绝对路径
154
+ - `repoName`:路径的最后一段
155
+ - `currentBranch`:有变更时从 `git branch -vv` 解析当前分支名,无变更时为空字符串
156
+ - `remoteBranches`:有变更时从 `git branch -r` 解析远程分支列表;无变更时为空数组。解析规则:
157
+ 1. 跳过包含 `->` 的行(如 `origin/HEAD -> origin/master`,这是 HEAD 指针,不是分支)
158
+ 2. 对每一行 trim 后去掉 `origin/` 前缀,得到分支名
159
+ 3. 从 `git branch -vv` 输出中解析当前分支的远程追踪分支名,将匹配的分支标记为 `isCurrent: true`,其余为 `false`
160
+ 4. 最多取 10 个分支(当前追踪分支必须包含在内),按最近活跃排序
161
+ - `hasChanges`:该 workspace 是否有变更(`workspace_diffs[path].has_changes`)
162
+ - `diffSummary`:有变更时为 `workspace_diffs[path]` 中的 `changed_files` + `stat_summary`,无变更时为 `null`
163
+
164
+ **顶层不再有旧的 `currentBranch`/`remoteBranches`/`diffSummary` 字段。**
165
+
166
+ 完整示例 command 值:
167
+ ```
168
+ __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"}}]}
169
+ ```
170
+
171
+ 用户操作后,tool output 返回 JSON:
172
+ - 确认提交:`{"action": "submit", "repos": [{"workspace": "...", "commitMessage": "...", "branch": "..."}]}`
173
+ - 取消提交:`{"action": "cancel"}`
174
+
175
+ ---
176
+
177
+ ## 步骤 9:执行提交(新版本 IDE)
178
+
179
+ 从 tool output 解析用户操作:
180
+
181
+ **如果是 action === "submit":**
182
+
183
+ UI 返回的结果格式:
184
+ ```json
185
+ {"action": "submit", "repos": [{"workspace": "/path/to/repo", "commitMessage": "dkx-200 修复...", "branch": "feature/xxx"}]}
186
+ ```
187
+
188
+ Agent 收到后,对 `repos` 数组中的每个仓库自主决定执行方式:
189
+ - `cd` 到对应 workspace 目录
190
+ - 执行 `git add .`、`git commit -m "<commitMessage>"`(git commit 命令不使用 `__silent:`,展示提交结果给用户)
191
+ - 如果用户选择了特定分支且不是当前分支,先 `git checkout` 切换
192
+ - 执行 `git push origin HEAD:refs/for/<branch>` 推送到远程
193
+ - 多仓库时逐个执行,每个仓库独立处理
194
+
195
+ **如果是 action === "cancel":**
196
+ - 输出"已取消提交"