@hirohsu/user-web-feedback 2.6.0 → 2.7.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/dist/cli.cjs +1785 -430
- package/dist/index.cjs +407 -11
- package/dist/static/settings.html +36 -0
- package/dist/static/settings.js +118 -0
- package/package.json +20 -19
package/dist/static/settings.js
CHANGED
|
@@ -63,6 +63,15 @@
|
|
|
63
63
|
confirmBeforeSubmit: document.getElementById("confirmBeforeSubmit"),
|
|
64
64
|
defaultLanguage: document.getElementById("defaultLanguage"),
|
|
65
65
|
savePreferencesBtn: document.getElementById("savePreferencesBtn"),
|
|
66
|
+
// Self-Probe Settings
|
|
67
|
+
enableSelfProbe: document.getElementById("enableSelfProbe"),
|
|
68
|
+
selfProbeInterval: document.getElementById("selfProbeInterval"),
|
|
69
|
+
selfProbeIntervalGroup: document.getElementById("selfProbeIntervalGroup"),
|
|
70
|
+
selfProbeStatus: document.getElementById("selfProbeStatus"),
|
|
71
|
+
selfProbeRunning: document.getElementById("selfProbeRunning"),
|
|
72
|
+
selfProbeCount: document.getElementById("selfProbeCount"),
|
|
73
|
+
selfProbeLastTime: document.getElementById("selfProbeLastTime"),
|
|
74
|
+
saveSelfProbeBtn: document.getElementById("saveSelfProbeBtn"),
|
|
66
75
|
toastContainer: document.getElementById("toastContainer"),
|
|
67
76
|
};
|
|
68
77
|
|
|
@@ -76,6 +85,7 @@
|
|
|
76
85
|
loadAISettings();
|
|
77
86
|
loadCLISettings();
|
|
78
87
|
loadPreferences();
|
|
88
|
+
loadSelfProbeSettings();
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
function setupEventListeners() {
|
|
@@ -92,6 +102,21 @@
|
|
|
92
102
|
|
|
93
103
|
// User Preferences
|
|
94
104
|
elements.savePreferencesBtn.addEventListener("click", savePreferences);
|
|
105
|
+
|
|
106
|
+
// Self-Probe Settings
|
|
107
|
+
if (elements.enableSelfProbe) {
|
|
108
|
+
elements.enableSelfProbe.addEventListener("change", handleSelfProbeToggle);
|
|
109
|
+
}
|
|
110
|
+
if (elements.saveSelfProbeBtn) {
|
|
111
|
+
elements.saveSelfProbeBtn.addEventListener("click", saveSelfProbeSettings);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function handleSelfProbeToggle() {
|
|
116
|
+
const isEnabled = elements.enableSelfProbe.checked;
|
|
117
|
+
if (elements.selfProbeIntervalGroup) {
|
|
118
|
+
elements.selfProbeIntervalGroup.style.opacity = isEnabled ? "1" : "0.5";
|
|
119
|
+
}
|
|
95
120
|
}
|
|
96
121
|
|
|
97
122
|
function handleAIModeChange() {
|
|
@@ -397,6 +422,99 @@
|
|
|
397
422
|
}
|
|
398
423
|
}
|
|
399
424
|
|
|
425
|
+
// ============ Self-Probe Settings ============
|
|
426
|
+
|
|
427
|
+
async function loadSelfProbeSettings() {
|
|
428
|
+
try {
|
|
429
|
+
const response = await fetch(`${API_BASE}/api/settings/self-probe`);
|
|
430
|
+
const data = await response.json();
|
|
431
|
+
|
|
432
|
+
if (data.success) {
|
|
433
|
+
const settings = data.settings || {};
|
|
434
|
+
const stats = data.stats || {};
|
|
435
|
+
|
|
436
|
+
if (elements.enableSelfProbe) {
|
|
437
|
+
elements.enableSelfProbe.checked = settings.enabled || false;
|
|
438
|
+
}
|
|
439
|
+
if (elements.selfProbeInterval) {
|
|
440
|
+
elements.selfProbeInterval.value = settings.intervalSeconds || 300;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// 更新狀態資訊
|
|
444
|
+
updateSelfProbeStatus(stats);
|
|
445
|
+
handleSelfProbeToggle();
|
|
446
|
+
}
|
|
447
|
+
} catch (error) {
|
|
448
|
+
console.error("Failed to load Self-Probe settings:", error);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function updateSelfProbeStatus(stats) {
|
|
453
|
+
if (!elements.selfProbeStatus) return;
|
|
454
|
+
|
|
455
|
+
if (stats.enabled) {
|
|
456
|
+
elements.selfProbeStatus.style.display = "block";
|
|
457
|
+
|
|
458
|
+
if (elements.selfProbeRunning) {
|
|
459
|
+
elements.selfProbeRunning.textContent = `執行狀態: ${stats.isRunning ? "✅ 運行中" : "⏸️ 已停止"}`;
|
|
460
|
+
}
|
|
461
|
+
if (elements.selfProbeCount) {
|
|
462
|
+
elements.selfProbeCount.textContent = `探查次數: ${stats.probeCount || 0}`;
|
|
463
|
+
}
|
|
464
|
+
if (elements.selfProbeLastTime) {
|
|
465
|
+
const lastTime = stats.lastProbeTime
|
|
466
|
+
? new Date(stats.lastProbeTime).toLocaleString()
|
|
467
|
+
: "尚未執行";
|
|
468
|
+
elements.selfProbeLastTime.textContent = `上次探查: ${lastTime}`;
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
elements.selfProbeStatus.style.display = "none";
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function saveSelfProbeSettings() {
|
|
476
|
+
const settings = {
|
|
477
|
+
enabled: elements.enableSelfProbe?.checked || false,
|
|
478
|
+
intervalSeconds: parseInt(elements.selfProbeInterval?.value) || 300,
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// 驗證間隔
|
|
482
|
+
if (settings.intervalSeconds < 60 || settings.intervalSeconds > 600) {
|
|
483
|
+
showToast("探查間隔必須在 60-600 秒之間", "error");
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (elements.saveSelfProbeBtn) {
|
|
488
|
+
elements.saveSelfProbeBtn.disabled = true;
|
|
489
|
+
elements.saveSelfProbeBtn.textContent = "儲存中...";
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
try {
|
|
493
|
+
const response = await fetch(`${API_BASE}/api/settings/self-probe`, {
|
|
494
|
+
method: "POST",
|
|
495
|
+
headers: { "Content-Type": "application/json" },
|
|
496
|
+
body: JSON.stringify(settings),
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
const data = await response.json();
|
|
500
|
+
|
|
501
|
+
if (response.ok && data.success) {
|
|
502
|
+
showToast("Self-Probe 設定已儲存", "success");
|
|
503
|
+
updateSelfProbeStatus(data.stats);
|
|
504
|
+
} else {
|
|
505
|
+
showToast(`儲存失敗: ${data.error || "未知錯誤"}`, "error");
|
|
506
|
+
}
|
|
507
|
+
} catch (error) {
|
|
508
|
+
console.error("Save Self-Probe settings failed:", error);
|
|
509
|
+
showToast("儲存失敗", "error");
|
|
510
|
+
} finally {
|
|
511
|
+
if (elements.saveSelfProbeBtn) {
|
|
512
|
+
elements.saveSelfProbeBtn.disabled = false;
|
|
513
|
+
elements.saveSelfProbeBtn.textContent = "儲存設定";
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
400
518
|
function showToast(message, type = "info") {
|
|
401
519
|
const toast = document.createElement("div");
|
|
402
520
|
toast.className = `toast toast-${type}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hirohsu/user-web-feedback",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "基於Node.js的MCP回饋收集器 - 支持AI工作彙報和用戶回饋收集",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"bin": {
|
|
@@ -24,11 +24,25 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"repository": {
|
|
26
26
|
"type": "git",
|
|
27
|
-
"url": "git+https://github.com/
|
|
27
|
+
"url": "git+https://github.com/HyperHeroX/user-feedback-web.git"
|
|
28
28
|
},
|
|
29
|
-
"homepage": "https://github.com/
|
|
29
|
+
"homepage": "https://github.com/HyperHeroX/user-feedback-web#readme",
|
|
30
30
|
"bugs": {
|
|
31
|
-
"url": "https://github.com/
|
|
31
|
+
"url": "https://github.com/HyperHeroX/user-feedback-web/issues"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsup",
|
|
35
|
+
"dev": "tsx watch --clear-screen=false src/cli.ts",
|
|
36
|
+
"start": "node dist/cli.js",
|
|
37
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
38
|
+
"test:integration": "node --experimental-vm-modules node_modules/jest/bin/jest.js src/__tests__/integration.test.ts --testPathIgnorePatterns=[] --forceExit",
|
|
39
|
+
"test:all": "npm run test && npm run test:integration",
|
|
40
|
+
"test:watch": "jest --watch",
|
|
41
|
+
"lint": "eslint src/ --ext .ts",
|
|
42
|
+
"lint:fix": "eslint src/ --ext .ts --fix",
|
|
43
|
+
"clean": "node -e \"const fs=require('fs'); if(fs.existsSync('dist')){fs.rmSync('dist', {recursive: true, force: true})}\"",
|
|
44
|
+
"prepare-release": "node scripts/prepare-release.cjs",
|
|
45
|
+
"prepublishOnly": "npm run clean && npm run build && node scripts/remove-sourcemaps.cjs"
|
|
32
46
|
},
|
|
33
47
|
"dependencies": {
|
|
34
48
|
"better-sqlite3": "^12.4.1"
|
|
@@ -74,18 +88,5 @@
|
|
|
74
88
|
"dist",
|
|
75
89
|
"README.md",
|
|
76
90
|
"LICENSE"
|
|
77
|
-
]
|
|
78
|
-
|
|
79
|
-
"build": "tsup",
|
|
80
|
-
"dev": "tsx watch --clear-screen=false src/cli.ts",
|
|
81
|
-
"start": "node dist/cli.js",
|
|
82
|
-
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
83
|
-
"test:integration": "node --experimental-vm-modules node_modules/jest/bin/jest.js src/__tests__/integration.test.ts --testPathIgnorePatterns=[] --forceExit",
|
|
84
|
-
"test:all": "npm run test && npm run test:integration",
|
|
85
|
-
"test:watch": "jest --watch",
|
|
86
|
-
"lint": "eslint src/ --ext .ts",
|
|
87
|
-
"lint:fix": "eslint src/ --ext .ts --fix",
|
|
88
|
-
"clean": "node -e \"const fs=require('fs'); if(fs.existsSync('dist')){fs.rmSync('dist', {recursive: true, force: true})}\"",
|
|
89
|
-
"prepare-release": "node scripts/prepare-release.cjs"
|
|
90
|
-
}
|
|
91
|
-
}
|
|
91
|
+
]
|
|
92
|
+
}
|