cursor-feedback 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
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.6.0](https://github.com/jianger666/cursor-feedback-extension/compare/v2.5.0...v2.6.0) (2026-07-06)
6
+
7
+
8
+ ### Features
9
+
10
+ * **diag:** server 日志落盘(按天切割/7天保留)+ 诊断包导出(端点/面板按钮/密钥脱敏/无server降级);/help 去掉计费说明 ([91a0d67](https://github.com/jianger666/cursor-feedback-extension/commit/91a0d67346a207afdab8d2df02278c40674bfbb5))
11
+
5
12
  ## [2.5.0](https://github.com/jianger666/cursor-feedback-extension/compare/v2.4.1...v2.5.0) (2026-07-06)
6
13
 
7
14
 
package/README.md CHANGED
@@ -291,6 +291,10 @@ Normally the server process is spawned by Cursor, so closing Cursor drops the Fe
291
291
  - **How**: the current package is copied to `~/.cursor-feedback/daemon/app` (self-contained, immune to npx cache cleanup); registered as a launchd agent on macOS (auto-restart on crash) or a logon scheduled task on Windows.
292
292
  - **Keep-awake**: while on AC power the daemon prevents system sleep (macOS `caffeinate -s`; Windows power assertion). On battery it does nothing. Lock screen never affects background processes.
293
293
  - **Typical use**: leave the machine plugged in and locked after work; `/new` from your phone anytime.
294
+
295
+ ### Diagnostics export
296
+
297
+ Server logs are also written to `~/.cursor-feedback/logs/` (daily files, 7-day retention). Hit **Export diagnostics** in the extension's notification settings to save a single report — recent logs, environment and sanitized config (secrets are masked) — to attach to bug reports. Works even when no server is running (falls back to reading log files directly).
294
298
  - After upgrading the extension, toggle the switch off/on once to refresh the daemon's copy.
295
299
 
296
300
  ## 🏗️ Architecture
package/README_CN.md CHANGED
@@ -295,6 +295,10 @@ npm install -g cursor-feedback
295
295
  - **实现**:把当前包完整拷贝到 `~/.cursor-feedback/daemon/app`(自包含,不怕 npx 缓存被清),macOS 注册 launchd(崩溃自动拉起),Windows 注册登录计划任务。
296
296
  - **防睡眠**:守护进程在接电源时自动阻止系统睡眠(macOS `caffeinate -s`;Windows 电源断言),电池供电不生效、不偷耗电。锁屏本来就不影响后台进程。
297
297
  - **典型用法**:下班插着电源锁屏走人,手机飞书随时 `/new`。
298
+
299
+ ### 诊断包导出
300
+
301
+ server 日志会同时落盘到 `~/.cursor-feedback/logs/`(按天切割,保留 7 天)。在插件「通知设置」里点**导出诊断包**,一键保存包含最近日志、环境信息和脱敏配置(密钥打码)的报告文件,报 bug 时直接附上。即使 server 全挂了也能导(降级为直接读日志文件)。
298
302
  - 升级插件版本后重新开关一次即可更新守护进程里的拷贝。
299
303
 
300
304
  ## 🏗️ 架构
@@ -52,8 +52,10 @@ const child_process_1 = require("child_process");
52
52
  const fs = __importStar(require("fs"));
53
53
  const os = __importStar(require("os"));
54
54
  const path = __importStar(require("path"));
55
+ const logger_js_1 = require("./logger.js");
55
56
  function clog(message) {
56
57
  console.error(`[${new Date().toISOString()}] [cli-launcher] ${message}`);
58
+ (0, logger_js_1.fileLog)('cli-launcher', message);
57
59
  }
58
60
  class CliLauncher {
59
61
  constructor() {
package/dist/extension.js CHANGED
@@ -38,6 +38,7 @@ exports.deactivate = deactivate;
38
38
  const vscode = __importStar(require("vscode"));
39
39
  const http = __importStar(require("http"));
40
40
  const fs = __importStar(require("fs"));
41
+ const os = __importStar(require("os"));
41
42
  const path = __importStar(require("path"));
42
43
  const child_process_1 = require("child_process");
43
44
  const i18n_1 = require("./i18n");
@@ -303,6 +304,9 @@ class FeedbackViewProvider {
303
304
  case 'toggleDaemon':
304
305
  await this._handleToggleDaemon(!!data.payload?.enabled);
305
306
  break;
307
+ case 'exportDiagnostics':
308
+ await this._handleExportDiagnostics();
309
+ break;
306
310
  case 'feishuRegisterStart':
307
311
  await this._handleFeishuRegisterStart();
308
312
  break;
@@ -1392,6 +1396,63 @@ class FeedbackViewProvider {
1392
1396
  });
1393
1397
  }
1394
1398
  }
1399
+ /**
1400
+ * 导出诊断包:优先从活跃 server 拿完整报告(含运行时状态);server 全挂时降级为
1401
+ * 插件本地拼装(正好覆盖「server 起不来」这种最需要日志的场景)。存为 txt 并打开。
1402
+ */
1403
+ async _handleExportDiagnostics() {
1404
+ let report = null;
1405
+ const port = this._anyServerPort();
1406
+ if (port) {
1407
+ try {
1408
+ report = await this._httpGet(`http://127.0.0.1:${port}/api/diagnostics`);
1409
+ }
1410
+ catch {
1411
+ report = null;
1412
+ }
1413
+ }
1414
+ if (!report) {
1415
+ report = this._buildLocalDiagnostics();
1416
+ }
1417
+ const def = path.join(os.homedir(), 'Downloads', `cursor-feedback-diag-${new Date().toISOString().slice(0, 19).replace(/[T:]/g, '-')}.txt`);
1418
+ const uri = await vscode.window.showSaveDialog({
1419
+ defaultUri: vscode.Uri.file(def),
1420
+ filters: { Text: ['txt'] },
1421
+ });
1422
+ if (!uri)
1423
+ return;
1424
+ await vscode.workspace.fs.writeFile(uri, Buffer.from(report, 'utf-8'));
1425
+ const open = this._t('diagOpenAction');
1426
+ const picked = await vscode.window.showInformationMessage(this._t('diagSaved'), open);
1427
+ if (picked === open) {
1428
+ await vscode.window.showTextDocument(uri);
1429
+ }
1430
+ }
1431
+ /** server 全挂时的降级诊断:插件自己读日志文件 + 基本环境信息(不含 server 运行时状态) */
1432
+ _buildLocalDiagnostics() {
1433
+ const parts = [
1434
+ `cursor-feedback 诊断报告(降级模式:没有活跃的 server,运行时状态缺失) 生成于 ${new Date().toISOString()}`,
1435
+ `===== 环境 =====\nextension version: ${vscode.extensions.getExtension('jianger666.cursor-feedback')?.packageJSON?.version || '?'}\nplatform: ${process.platform} (${process.arch})\nvscode: ${vscode.version}`,
1436
+ ];
1437
+ try {
1438
+ const dir = path.join(os.homedir(), '.cursor-feedback', 'logs');
1439
+ const files = fs
1440
+ .readdirSync(dir)
1441
+ .filter((f) => /^\d{4}-\d{2}-\d{2}\.log$/.test(f))
1442
+ .sort()
1443
+ .slice(-2);
1444
+ let text = '';
1445
+ for (const f of files) {
1446
+ text += `===== ${f} =====\n` + fs.readFileSync(path.join(dir, f), 'utf-8');
1447
+ }
1448
+ const MAX = 256 * 1024;
1449
+ parts.push(text.length > MAX ? '…(前文截断)\n' + text.slice(text.length - MAX) : text || '(没有日志文件)');
1450
+ }
1451
+ catch {
1452
+ parts.push('(没有日志文件)');
1453
+ }
1454
+ return parts.join('\n\n') + '\n';
1455
+ }
1395
1456
  /**
1396
1457
  * HTTP GET 请求
1397
1458
  */
package/dist/feishu.js CHANGED
@@ -50,8 +50,10 @@ exports.FeishuBridge = void 0;
50
50
  const fs = __importStar(require("fs"));
51
51
  const os = __importStar(require("os"));
52
52
  const path = __importStar(require("path"));
53
+ const logger_js_1 = require("./logger.js");
53
54
  function flog(message) {
54
55
  console.error(`[${new Date().toISOString()}] [feishu] ${message}`);
56
+ (0, logger_js_1.fileLog)('feishu', message);
55
57
  }
56
58
  class FeishuBridge {
57
59
  constructor() {
package/dist/i18n/en.json CHANGED
@@ -80,6 +80,11 @@
80
80
  "daemonNotSupported": "Not supported on this platform",
81
81
  "daemonFailed": "Operation failed: {error}",
82
82
  "daemonWorking": "Working…",
83
+ "diagLabel": "Diagnostics",
84
+ "diagDesc": "Export a diagnostic report (recent logs, environment and sanitized config — secrets are masked) to attach to bug reports.",
85
+ "diagExportBtn": "Export diagnostics",
86
+ "diagSaved": "Diagnostic report saved.",
87
+ "diagOpenAction": "Open",
83
88
  "queueSend": "Queue Message",
84
89
  "queuedTitle": "Queued messages",
85
90
  "queueModeHint": "AI is busy — messages sent now are queued and delivered when it next asks for feedback",
@@ -171,6 +171,11 @@ function getDefaultMessages() {
171
171
  daemonNotSupported: "Not supported on this platform",
172
172
  daemonFailed: "Operation failed: {error}",
173
173
  daemonWorking: "Working…",
174
+ diagLabel: "Diagnostics",
175
+ diagDesc: "Export a diagnostic report (recent logs, environment and sanitized config — secrets are masked) to attach to bug reports.",
176
+ diagExportBtn: "Export diagnostics",
177
+ diagSaved: "Diagnostic report saved.",
178
+ diagOpenAction: "Open",
174
179
  queueSend: "Queue Message",
175
180
  queuedTitle: "Queued messages",
176
181
  queueModeHint: "AI is busy — messages sent now are queued and delivered when it next asks for feedback",
@@ -80,6 +80,11 @@
80
80
  "daemonNotSupported": "当前平台暂不支持",
81
81
  "daemonFailed": "操作失败:{error}",
82
82
  "daemonWorking": "处理中…",
83
+ "diagLabel": "诊断信息",
84
+ "diagDesc": "导出诊断报告(最近日志、环境信息、脱敏后的配置——密钥不会包含在内),报 bug 时附上它。",
85
+ "diagExportBtn": "导出诊断包",
86
+ "diagSaved": "诊断报告已保存。",
87
+ "diagOpenAction": "打开",
83
88
  "queueSend": "排队发送",
84
89
  "queuedTitle": "排队中的消息",
85
90
  "queueModeHint": "AI 正忙,现在发送的消息会排队,等它下一轮询问时自动送达",
package/dist/logger.js ADDED
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.fileLog = fileLog;
37
+ exports.readRecentLogs = readRecentLogs;
38
+ /**
39
+ * 落盘日志:server 侧所有日志除了打到 stderr(Cursor 的 MCP 日志),同时写入
40
+ * ~/.cursor-feedback/logs/YYYY-MM-DD.log,供「导出诊断包」排查用户现场问题。
41
+ * 设计约束:绝不能因为日志失败影响主流程(全部吞错);日志量小,直接同步追加(崩溃不丢行)。
42
+ */
43
+ const fs = __importStar(require("fs"));
44
+ const os = __importStar(require("os"));
45
+ const path = __importStar(require("path"));
46
+ /** 日志保留天数:超过的按文件名日期清理 */
47
+ const RETENTION_DAYS = 7;
48
+ function logsDir() {
49
+ return path.join(os.homedir(), '.cursor-feedback', 'logs');
50
+ }
51
+ /** 本地日期 YYYY-MM-DD(日志按用户本地时区的自然日切割) */
52
+ function localDay(d = new Date()) {
53
+ const pad = (n) => String(n).padStart(2, '0');
54
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
55
+ }
56
+ let cleanedForDay = '';
57
+ /** 清理过期日志:每个进程每天最多执行一次 */
58
+ function cleanupOldLogs(today) {
59
+ if (cleanedForDay === today)
60
+ return;
61
+ cleanedForDay = today;
62
+ try {
63
+ const cutoff = new Date();
64
+ cutoff.setDate(cutoff.getDate() - RETENTION_DAYS);
65
+ const cutoffDay = localDay(cutoff);
66
+ for (const f of fs.readdirSync(logsDir())) {
67
+ const m = f.match(/^(\d{4}-\d{2}-\d{2})\.log$/);
68
+ // 文件名日期字典序即时间序;不匹配命名规则的文件不动
69
+ if (m && m[1] < cutoffDay) {
70
+ fs.rmSync(path.join(logsDir(), f), { force: true });
71
+ }
72
+ }
73
+ }
74
+ catch {
75
+ // 目录不存在或不可读,忽略
76
+ }
77
+ }
78
+ /** 追加一行日志到当天的文件。tag 用于区分模块(mcp / feishu / cli-launcher)。 */
79
+ function fileLog(tag, message) {
80
+ try {
81
+ const today = localDay();
82
+ fs.mkdirSync(logsDir(), { recursive: true });
83
+ cleanupOldLogs(today);
84
+ const line = `[${new Date().toISOString()}] [${tag}] ${message}\n`;
85
+ fs.appendFileSync(path.join(logsDir(), `${today}.log`), line);
86
+ }
87
+ catch {
88
+ // 磁盘满/权限问题都不能影响主流程
89
+ }
90
+ }
91
+ /**
92
+ * 读取最近的日志尾部(今天优先,不够再补前一天),用于诊断包。
93
+ * 返回不超过 maxBytes 的文本。
94
+ */
95
+ function readRecentLogs(maxBytes = 256 * 1024) {
96
+ try {
97
+ const files = fs
98
+ .readdirSync(logsDir())
99
+ .filter((f) => /^\d{4}-\d{2}-\d{2}\.log$/.test(f))
100
+ .sort()
101
+ .slice(-2);
102
+ let text = '';
103
+ for (const f of files) {
104
+ text += `===== ${f} =====\n`;
105
+ text += fs.readFileSync(path.join(logsDir(), f), 'utf-8');
106
+ }
107
+ return text.length > maxBytes ? '…(前文截断)\n' + text.slice(text.length - maxBytes) : text;
108
+ }
109
+ catch {
110
+ return '(没有日志文件)';
111
+ }
112
+ }
113
+ //# sourceMappingURL=logger.js.map
@@ -62,6 +62,7 @@ const feishu_js_1 = require("./feishu.js");
62
62
  const cli_launcher_js_1 = require("./cli-launcher.js");
63
63
  const keep_awake_js_1 = require("./keep-awake.js");
64
64
  const daemon_install_js_1 = require("./daemon-install.js");
65
+ const logger_js_1 = require("./logger.js");
65
66
  // ⚠️ MCP stdio 协议要求 stdout 只承载 JSON-RPC 消息。第三方库(尤其飞书 SDK 的内置 logger,
66
67
  // 输出形如 "[info]: [...]")会用 console.log/info/debug 往 stdout 打日志,一旦混入就会让
67
68
  // Cursor 端 JSON 解析失败、连接进入 failed(表现为 "Not connected")。这里在进程最早期把这三个
@@ -74,6 +75,7 @@ console.debug = (...args) => console.error(...args);
74
75
  function debugLog(message) {
75
76
  const timestamp = new Date().toISOString();
76
77
  console.error(`[${timestamp}] ${message}`);
78
+ (0, logger_js_1.fileLog)('mcp', message);
77
79
  }
78
80
  // 包版本真相源:package.json(dist/mcp-server.js 的上一级目录)。读不到时兜底 0.0.0。
79
81
  const PKG_VERSION = (() => {
@@ -513,14 +515,13 @@ class McpFeedbackServer {
513
515
  '· 默认工作目录是主目录;可在任务前指定项目:\n' +
514
516
  ' /new /Users/me/proj 帮我修下测试\n' +
515
517
  ' /new crm-web 帮我修下测试(项目名唯一时自动匹配到完整路径)\n' +
516
- '· 非交互模式 + 强制 maxMode=false,每次会话固定只扣 1 次请求\n' +
517
518
  '· AI 需要沟通时会发反馈卡片,直接回复即可;同时只能跑一个会话\n\n' +
518
519
  '📁 /projects\n' +
519
520
  '列出 Cursor 打开过的项目路径(查路径 / 复制给 /new,也可直接用项目名)\n\n' +
520
521
  '🛑 /stop\n' +
521
522
  '终止运行中的 CLI 会话(任何窗口拉起的都能停)\n\n' +
522
523
  '🧠 /model [模型id]\n' +
523
- '查看 / 设置会话模型(持久化;无论选什么模型都不会走 Max 计费)\n\n' +
524
+ '查看 / 设置会话模型(持久化)\n\n' +
524
525
  '❓ /help\n' +
525
526
  '看这份帮助\n\n' +
526
527
  '💬 不带斜杠的消息照常作为反馈:回复某张卡片就送达那个请求,直接发送则给当前等待中的 AI。');
@@ -627,6 +628,64 @@ class McpFeedbackServer {
627
628
  }
628
629
  return true;
629
630
  }
631
+ /**
632
+ * 组装诊断报告(纯文本)。密钥严格脱敏:appSecret 绝不输出,appId 只留前 8 位。
633
+ * 每个区块独立 try/catch,单块失败不影响整包导出。
634
+ */
635
+ buildDiagnostics() {
636
+ const sections = [];
637
+ const add = (title, fn) => {
638
+ let body;
639
+ try {
640
+ body = fn();
641
+ }
642
+ catch (e) {
643
+ body = `(读取失败:${e})`;
644
+ }
645
+ sections.push(`===== ${title} =====\n${body}`);
646
+ };
647
+ const maskId = (id) => (id.length > 8 ? id.slice(0, 8) + '***' : '***');
648
+ const readJson = (file) => {
649
+ try {
650
+ return JSON.parse(fs.readFileSync(path.join(os.homedir(), '.cursor-feedback', file), 'utf-8'));
651
+ }
652
+ catch {
653
+ return null;
654
+ }
655
+ };
656
+ add('环境', () => [
657
+ `version: ${PKG_VERSION}`,
658
+ `pid: ${process.pid} uptimeSec: ${Math.round(process.uptime())}`,
659
+ `platform: ${process.platform} ${os.release()} (${process.arch})`,
660
+ `node: ${process.version}`,
661
+ `daemonMode: ${this.daemonMode}`,
662
+ `ownerWorkspace: ${this.ownerWorkspace || '(none)'}`,
663
+ `hasCurrentRequest: ${this.currentRequest !== null}`,
664
+ ].join('\n'));
665
+ add('飞书配置(脱敏)', () => {
666
+ const cfg = readJson('feishu-config.json');
667
+ if (!cfg)
668
+ return '(未配置)';
669
+ const safe = { ...cfg };
670
+ if (typeof safe.appId === 'string')
671
+ safe.appId = maskId(safe.appId);
672
+ if ('appSecret' in safe)
673
+ safe.appSecret = '***';
674
+ return JSON.stringify(safe, null, 2);
675
+ });
676
+ add('飞书绑定(appId 脱敏)', () => {
677
+ const bind = readJson('feishu-bind.json');
678
+ if (!bind)
679
+ return '(无)';
680
+ return JSON.stringify(Object.fromEntries(Object.entries(bind).map(([k, v]) => [maskId(k), v])), null, 2);
681
+ });
682
+ add('通用设置 settings.json', () => JSON.stringify(readJson('settings.json') ?? '(无)'));
683
+ add('CLI 设置 cli.json', () => JSON.stringify(readJson('cli.json') ?? '(无)'));
684
+ add('CLI 会话锁', () => JSON.stringify(readJson('cli-session.lock') ?? '(无活跃会话)'));
685
+ add('常驻服务状态', () => JSON.stringify((0, daemon_install_js_1.daemonStatus)(), null, 2));
686
+ add('最近日志(今天 + 昨天,尾部截断)', () => (0, logger_js_1.readRecentLogs)());
687
+ return `cursor-feedback 诊断报告 生成于 ${new Date().toISOString()}\n\n` + sections.join('\n\n') + '\n';
688
+ }
630
689
  /** CLI 会话结束的收尾回执:把 agent 的最终输出(尾部)发回飞书 */
631
690
  onCliSessionDone(result, chatId) {
632
691
  const mins = Math.max(1, Math.round(result.elapsedMs / 60000));
@@ -1936,6 +1995,13 @@ class McpFeedbackServer {
1936
1995
  });
1937
1996
  return;
1938
1997
  }
1998
+ // 诊断包:版本/环境/配置(脱敏)/守护状态/会话锁 + 最近日志尾部,纯文本一把梭。
1999
+ // 插件面板「导出诊断包」按钮请求这里;轻量起见不打 zip,一个 txt 就够排查。
2000
+ if (req.method === 'GET' && req.url === '/api/diagnostics') {
2001
+ res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
2002
+ res.end(this.buildDiagnostics());
2003
+ return;
2004
+ }
1939
2005
  // 健康检查
1940
2006
  if (req.method === 'GET' && req.url === '/api/health') {
1941
2007
  res.writeHead(200, { 'Content-Type': 'application/json' });
@@ -221,6 +221,15 @@
221
221
  <p id="daemonStatusText" class="feishu-modal__desc feishu-modal__desc--sub"></p>
222
222
  </div>
223
223
 
224
+ <!-- 区块③b:诊断信息(导出日志 + 环境 + 脱敏配置,报 bug 用) -->
225
+ <div class="feishu-section">
226
+ <span class="feishu-switch__label feishu-switch__label--strong">{{i18n.diagLabel}}</span>
227
+ <p class="feishu-modal__desc">{{i18n.diagDesc}}</p>
228
+ <div class="feishu-modal__actions">
229
+ <button id="diagExportBtn" class="feishu-link" type="button">{{i18n.diagExportBtn}}</button>
230
+ </div>
231
+ </div>
232
+
224
233
  <!-- 区块④:飞书通知(推送开关 + 凭证 + 绑定状态) -->
225
234
  <div class="feishu-section">
226
235
  <label class="feishu-switch">
@@ -243,6 +243,11 @@
243
243
  daemonStatusText.textContent = i18n.daemonWorking || 'Working…';
244
244
  vscode.postMessage({ type: 'toggleDaemon', payload: { enabled: daemonToggle.checked } });
245
245
  });
246
+ // ---------- 诊断包导出 ----------
247
+ document.getElementById('diagExportBtn').addEventListener('click', () => {
248
+ vscode.postMessage({ type: 'exportDiagnostics' });
249
+ });
250
+
246
251
  function updateDaemonUI(s) {
247
252
  if (!s) return;
248
253
  daemonToggle.disabled = !s.supported;
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.5.0",
5
+ "version": "2.6.0",
6
6
  "icon": "icon.png",
7
7
  "author": "jianger666",
8
8
  "license": "MIT",
@@ -147,7 +147,7 @@
147
147
  "watch": "tsc -watch -p ./",
148
148
  "lint": "eslint src --ext ts",
149
149
  "start:mcp": "node dist/mcp-server.js",
150
- "test:smoke": "npm run compile && node scripts/smoke-queue.js && node scripts/smoke-dup.js && node scripts/smoke-cli-launcher.js && node scripts/smoke-daemon.js",
150
+ "test:smoke": "npm run compile && node scripts/smoke-queue.js && node scripts/smoke-dup.js && node scripts/smoke-cli-launcher.js && node scripts/smoke-daemon.js && node scripts/smoke-logger.js",
151
151
  "prepublishOnly": "npm run check-changelog && npm run compile",
152
152
  "check-changelog": "node scripts/check-changelog.js",
153
153
  "release": "standard-version",