cursor-feedback 2.0.0 → 2.0.2
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/.cursor/skills/releasing/SKILL.md +43 -0
- package/CHANGELOG.md +32 -0
- package/README.md +1 -1
- package/README_CN.md +1 -1
- package/dist/feishu.js +23 -2
- package/dist/mcp-server.js +38 -5
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: releasing
|
|
3
|
+
description: 发布 cursor-feedback 新版本到 npm / Open VSX / VS Code Marketplace。当用户要发版、发布新版本、出包、上线、release、publish 时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 发布 cursor-feedback 新版本
|
|
7
|
+
|
|
8
|
+
发版用 `standard-version` 升级版本号,发布由 GitHub Actions(`.github/workflows/release.yml`,推送 `v*.*.*` tag 触发)自动完成三个渠道。**不要手动 `npm publish` / `vsce publish`。**
|
|
9
|
+
|
|
10
|
+
## 发版步骤
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
- [ ] 1. 改动已 commit,且遵循 conventional commits(feat: / fix: / chore:)
|
|
14
|
+
- [ ] 2. 升级版本:npm run release:patch(或 release:minor / release:major)
|
|
15
|
+
- [ ] 3. 推送:git push --follow-tags origin main
|
|
16
|
+
- [ ] 4. 验证三渠道发布成功
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- **第 2 步**:`standard-version` 自动升级 `package.json` 版本、按 commit 生成 CHANGELOG、打 `vX.Y.Z` tag。
|
|
20
|
+
- **第 3 步**:推送 tag 后 GitHub Actions 自动发布,去仓库 Actions 页看进度。
|
|
21
|
+
|
|
22
|
+
## 两个发布渠道
|
|
23
|
+
|
|
24
|
+
| 渠道 | 认证 | 说明 |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| npm | OIDC Trusted Publishing | 免 token、永不过期(已在 npmjs 配 trusted publisher)|
|
|
27
|
+
| Open VSX | `OVSX_PAT` secret | Cursor / Windsurf / VSCodium 用户从这装 |
|
|
28
|
+
|
|
29
|
+
`OVSX_PAT` 在 GitHub 仓库 `Settings → Secrets and variables → Actions` 配置。
|
|
30
|
+
|
|
31
|
+
## 硬约束(踩过的坑,别再犯)
|
|
32
|
+
|
|
33
|
+
- **禁止给 `package.json` 加 `files` 字段**:会与 `.vscodeignore` 冲突,导致 `vsce package` 直接失败。npm 包瘦身只用 `.npmignore`,VS Code 打包只用 `.vscodeignore`,两者各管各的、互不影响。
|
|
34
|
+
- `pre-push` hook 会校验 `package.json` 的 version 已写入 `CHANGELOG.md`,没写会被拦下。
|
|
35
|
+
|
|
36
|
+
## 验证发布
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm view cursor-feedback version
|
|
40
|
+
curl -s https://open-vsx.org/api/jianger666/cursor-feedback | grep -o '"version":"[^"]*"'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
两个版本号都应等于刚发的版本。
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [2.0.2](https://github.com/jianger666/cursor-feedback-extension/compare/v2.0.1...v2.0.2) (2026-06-20)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **feishu:** 消息没送到时引用回复提示,去除虚假「已收到」回执 ([52b107d](https://github.com/jianger666/cursor-feedback-extension/commit/52b107d27ee146dcc10ba1a3aa77d18f3f51bb3c))
|
|
11
|
+
|
|
12
|
+
### [2.0.1](https://github.com/jianger666/cursor-feedback-extension/compare/v2.0.0...v2.0.1) (2026-06-20)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **feishu:** 卡片标题与引导语去掉 Cursor 绑定改为通用文案 ([07857fa](https://github.com/jianger666/cursor-feedback-extension/commit/07857fa07b972c2a7c621c76fadf33870ddbdb61))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Code Refactoring
|
|
21
|
+
|
|
22
|
+
* 发版指引从 rule 改为 skill ([5854980](https://github.com/jianger666/cursor-feedback-extension/commit/58549801b93c37262cca793ceb238d84d2806f2d))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Chores
|
|
26
|
+
|
|
27
|
+
* **ci:** 移除 VS Code Marketplace 发布渠道 ([d58fec1](https://github.com/jianger666/cursor-feedback-extension/commit/d58fec19f9285c6705cb3aebe3aae1e4fc595986))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Documentation
|
|
31
|
+
|
|
32
|
+
* **feishu:** 删掉与开头重复的结尾段 ([bdc9c61](https://github.com/jianger666/cursor-feedback-extension/commit/bdc9c61fa86c9a268d54d2b777ecc1b11cfb849b))
|
|
33
|
+
* **feishu:** 精简事件订阅步骤描述 ([770a486](https://github.com/jianger666/cursor-feedback-extension/commit/770a4869b475a2466c99357b2e8f146582d9e57d))
|
|
34
|
+
* **feishu:** 补充事件订阅(长连接)配置步骤 ([47f5656](https://github.com/jianger666/cursor-feedback-extension/commit/47f5656373bec44ff6d3274c7c46b7bc6fa105b3))
|
|
35
|
+
* 添加发版流程 rule 供后续 AI 参考 ([e6986a4](https://github.com/jianger666/cursor-feedback-extension/commit/e6986a49d54b279fe28e14d1733342b20b64bbf6))
|
|
36
|
+
|
|
5
37
|
## [2.0.0](https://github.com/jianger666/cursor-feedback-extension/compare/v1.1.1...v2.0.0) (2026-06-20)
|
|
6
38
|
|
|
7
39
|
|
package/README.md
CHANGED
|
@@ -201,7 +201,7 @@ Custom timeout (optional, default 5 minutes):
|
|
|
201
201
|
|
|
202
202
|
### Feishu Notifications
|
|
203
203
|
|
|
204
|
-
Either way works (
|
|
204
|
+
Either way works — but you first need to set up the bot in the Feishu console: enable the bot, grant permissions, and turn on **event subscription** (long-connection mode + the `im.message.receive_v1` event). Full walkthrough in the [Feishu setup guide](./docs/feishu-setup.md):
|
|
205
205
|
|
|
206
206
|
- **On Cursor**: fill in Feishu credentials via the "Notification settings" icon at the top of the panel.
|
|
207
207
|
- **On other MCP hosts** (agent tools without this panel): configure through `env` in `mcp.json`:
|
package/README_CN.md
CHANGED
|
@@ -205,7 +205,7 @@ npm install -g cursor-feedback
|
|
|
205
205
|
|
|
206
206
|
### 飞书通知配置
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
两种方式都行——但都要先在飞书后台把机器人配好:开启机器人能力、申请权限、配置**事件订阅**(长连接方式 + `im.message.receive_v1` 事件)。完整步骤见[飞书配置教程](./docs/feishu-setup.md):
|
|
209
209
|
|
|
210
210
|
- **用 Cursor**:在插件面板顶部「通知设置」图标里填飞书凭证。
|
|
211
211
|
- **用其他 MCP host**(没有这个插件面板的 Agent 工具):在 `mcp.json` 的 `env` 里配置:
|
package/dist/feishu.js
CHANGED
|
@@ -583,6 +583,27 @@ class FeishuBridge {
|
|
|
583
583
|
flog('飞书回执失败: ' + e);
|
|
584
584
|
}
|
|
585
585
|
}
|
|
586
|
+
/**
|
|
587
|
+
* 回复(引用)某条消息:用飞书 reply 接口让回执挂在原消息下,用户一眼看出是哪条。
|
|
588
|
+
* messageId 缺失或调用失败时回退普通发送,保证提示一定送达。
|
|
589
|
+
*/
|
|
590
|
+
async replyToMessage(messageId, chatId, text) {
|
|
591
|
+
if (!this.client || !chatId)
|
|
592
|
+
return;
|
|
593
|
+
if (messageId) {
|
|
594
|
+
try {
|
|
595
|
+
await this.client.im.v1.message.reply({
|
|
596
|
+
path: { message_id: messageId },
|
|
597
|
+
data: { content: JSON.stringify({ text }), msg_type: 'text' },
|
|
598
|
+
});
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
catch (e) {
|
|
602
|
+
flog('飞书回复消息失败,回退普通发送: ' + e);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
await this.replyText(chatId, text);
|
|
606
|
+
}
|
|
586
607
|
/**
|
|
587
608
|
* 给某条消息加 Get 表情作为「轻回执」:不产生新消息、不产生未读。
|
|
588
609
|
* 失败(如该消息类型不支持表情)时回退文字回执,保证用户知道已收到。
|
|
@@ -637,7 +658,7 @@ class FeishuBridge {
|
|
|
637
658
|
config: { wide_screen_mode: true },
|
|
638
659
|
header: {
|
|
639
660
|
template: 'carmine',
|
|
640
|
-
title: { tag: 'plain_text', content: `
|
|
661
|
+
title: { tag: 'plain_text', content: `Feedback 请求 · ${projectName}` },
|
|
641
662
|
},
|
|
642
663
|
body: {
|
|
643
664
|
elements: [
|
|
@@ -646,7 +667,7 @@ class FeishuBridge {
|
|
|
646
667
|
{
|
|
647
668
|
tag: 'markdown',
|
|
648
669
|
text_size: 'notation',
|
|
649
|
-
content: '
|
|
670
|
+
content: '直接「回复」本条消息把反馈发回即可(多窗口时请回复对应卡片)',
|
|
650
671
|
},
|
|
651
672
|
],
|
|
652
673
|
},
|
package/dist/mcp-server.js
CHANGED
|
@@ -90,6 +90,8 @@ class McpFeedbackServer {
|
|
|
90
90
|
* 暂存后等下一轮 pending 一注册立即兑现,避免回复石沉大海(修复用户反馈的竞态 bug)。
|
|
91
91
|
*/
|
|
92
92
|
this.stashedInbound = null;
|
|
93
|
+
/** 暂存过期提示定时器:到点仍未被认领则「回复」那条消息告知没送到,避免静默丢弃 */
|
|
94
|
+
this.stashExpiryTimer = null;
|
|
93
95
|
// 最近一次被飞书回复 resolve 的请求:供插件端精确区分「飞书回复」与「超时」,
|
|
94
96
|
// 避免超时续期(request 也会短暂为 null)被误判成飞书回复而错误重置面板。
|
|
95
97
|
this.lastFeishuResolved = null;
|
|
@@ -403,9 +405,11 @@ class McpFeedbackServer {
|
|
|
403
405
|
if (globalCount === 0) {
|
|
404
406
|
// 抢跑兜底:此刻全局无人等待,但很可能 AI 正要发起下一轮(卡片还没注册)。
|
|
405
407
|
// 暂存到收到消息的本实例,等下一轮 pending 注册时立即兑现。
|
|
408
|
+
// 关键:此刻没有任何 AI 在等待,绝不能给「✅ 已收到」回执——那是虚假承诺,会让用户
|
|
409
|
+
// 误以为消息已被接收(实则 AI 这轮可能已结束、永远不会来认领,消息石沉大海)。
|
|
410
|
+
// 回执只在「真正送达某个等待中的请求」时给(见 tryConsumeStash → submitFromFeishu)。
|
|
406
411
|
this.stashedInbound = { text, chatId, images, files, at: Date.now(), messageId };
|
|
407
|
-
|
|
408
|
-
this.feishu.reactDone(messageId || undefined, chatId);
|
|
412
|
+
this.armStashExpiryNotice();
|
|
409
413
|
}
|
|
410
414
|
else if (globalCount === 1) {
|
|
411
415
|
if (localPending.length === 1) {
|
|
@@ -565,6 +569,27 @@ class McpFeedbackServer {
|
|
|
565
569
|
this.tryConsumeStash(requestId);
|
|
566
570
|
});
|
|
567
571
|
}
|
|
572
|
+
/**
|
|
573
|
+
* 暂存「无主消息」后,启动过期提示定时器:到 STASH_TTL_MS 仍没被 AI 认领,就「回复」
|
|
574
|
+
* 那条消息明确告知没送到、引导重发(不再静默丢弃,也不给虚假回执)。
|
|
575
|
+
* 每来一条无主消息都重置,避免连发时多个定时器并存。
|
|
576
|
+
*/
|
|
577
|
+
armStashExpiryNotice() {
|
|
578
|
+
if (this.stashExpiryTimer)
|
|
579
|
+
clearTimeout(this.stashExpiryTimer);
|
|
580
|
+
this.stashExpiryTimer = setTimeout(() => {
|
|
581
|
+
this.stashExpiryTimer = null;
|
|
582
|
+
const stash = this.stashedInbound;
|
|
583
|
+
if (!stash)
|
|
584
|
+
return; // 已被 tryConsumeStash 兑现
|
|
585
|
+
this.stashedInbound = null;
|
|
586
|
+
// 引用回复(锚定到最近这条,方便定位)。文案不带「这条/都/重复」等数量词——
|
|
587
|
+
// 单条已断、多条全丢、第一条已送达后续丢,三种场景下数量词总有一种会误导。
|
|
588
|
+
// 且引导「待 AI 回复后再重发」:AI 只有重新调起 feedback(即回复)时才会等待接收,
|
|
589
|
+
// 此刻立即重发仍会落空。
|
|
590
|
+
this.feishu.replyToMessage(stash.messageId, stash.chatId, '⚠️ 消息未能送达 AI(它可能正忙于上一轮任务,或这轮对话已结束)。需要的话请待 AI 回复后重新发送一次。');
|
|
591
|
+
}, McpFeedbackServer.STASH_TTL_MS);
|
|
592
|
+
}
|
|
568
593
|
/**
|
|
569
594
|
* 抢跑暂存兑现:若存在近期「无主」飞书消息,立即作为指定请求的回复提交。
|
|
570
595
|
* 超过 STASH_TTL_MS 的暂存视为与当前任务无关,直接丢弃。
|
|
@@ -574,12 +599,19 @@ class McpFeedbackServer {
|
|
|
574
599
|
if (!stash)
|
|
575
600
|
return;
|
|
576
601
|
this.stashedInbound = null;
|
|
602
|
+
// 已被 AI 认领,取消「没送到」提示定时器
|
|
603
|
+
if (this.stashExpiryTimer) {
|
|
604
|
+
clearTimeout(this.stashExpiryTimer);
|
|
605
|
+
this.stashExpiryTimer = null;
|
|
606
|
+
}
|
|
577
607
|
if (Date.now() - stash.at > McpFeedbackServer.STASH_TTL_MS) {
|
|
578
608
|
debugLog('Stashed inbound expired, dropped');
|
|
579
609
|
return;
|
|
580
610
|
}
|
|
581
611
|
debugLog(`Consuming stashed inbound for request: ${requestId}`);
|
|
582
|
-
|
|
612
|
+
// 真正送达某个等待中的请求时,才给「✅ 送达回执」(传 messageId 触发 reactDone)。
|
|
613
|
+
// 暂存阶段不再预先回执,避免「没人接却假装已收到」误导用户。
|
|
614
|
+
this.submitFromFeishu(requestId, stash.text, stash.chatId, stash.images, stash.files, stash.messageId);
|
|
583
615
|
}
|
|
584
616
|
/**
|
|
585
617
|
* 处理获取系统信息请求
|
|
@@ -1118,8 +1150,9 @@ class McpFeedbackServer {
|
|
|
1118
1150
|
}
|
|
1119
1151
|
}
|
|
1120
1152
|
McpFeedbackServer.PORT_SCAN_RANGE = 20; // 与插件端扫描范围保持一致
|
|
1121
|
-
/**
|
|
1122
|
-
|
|
1153
|
+
/** 抢跑暂存有效期:覆盖「AI 刚结束、正要调下一轮 feedback」的竞态间隙(通常 1-3s)。
|
|
1154
|
+
* 取 5s——太长会把已脱离语境的旧消息硬塞进很久后才出现的新一轮,造成上下文错乱(像答非所问)。 */
|
|
1155
|
+
McpFeedbackServer.STASH_TTL_MS = 5000;
|
|
1123
1156
|
/**
|
|
1124
1157
|
* 「我的窗口」判定为已关闭的空闲阈值:本实例曾被自己窗口插件轮询,但超过此时长没再收到
|
|
1125
1158
|
*(只剩别的窗口在扫端口)→ 视为我的窗口已关、本实例是僵尸:不再上报 pending,避免污染全局计数。
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "cursor-feedback",
|
|
3
3
|
"displayName": "Cursor Feedback",
|
|
4
4
|
"description": "One Cursor conversation, unlimited AI interactions - Save your monthly request quota! Interactive feedback loop for AI chat via MCP",
|
|
5
|
-
"version": "2.0.
|
|
5
|
+
"version": "2.0.2",
|
|
6
6
|
"icon": "icon.png",
|
|
7
7
|
"author": "jianger666",
|
|
8
8
|
"license": "MIT",
|