cloneloop 0.1.0__py3-none-any.whl

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 (118) hide show
  1. cloneloop-0.1.0.dist-info/METADATA +392 -0
  2. cloneloop-0.1.0.dist-info/RECORD +118 -0
  3. cloneloop-0.1.0.dist-info/WHEEL +4 -0
  4. cloneloop-0.1.0.dist-info/entry_points.txt +5 -0
  5. mcp_ai_supervisor/__init__.py +52 -0
  6. mcp_ai_supervisor/__main__.py +551 -0
  7. mcp_ai_supervisor/debug.py +15 -0
  8. mcp_ai_supervisor/desktop_app/__init__.py +29 -0
  9. mcp_ai_supervisor/desktop_app/desktop_app.py +390 -0
  10. mcp_ai_supervisor/helpers/__init__.py +4 -0
  11. mcp_ai_supervisor/helpers/feedback_helpers.py +140 -0
  12. mcp_ai_supervisor/helpers/image_helpers.py +73 -0
  13. mcp_ai_supervisor/i18n.py +14 -0
  14. mcp_ai_supervisor/log_writer.py +16 -0
  15. mcp_ai_supervisor/logging/__init__.py +8 -0
  16. mcp_ai_supervisor/logging/log_parser.py +293 -0
  17. mcp_ai_supervisor/logging/log_tailer.py +367 -0
  18. mcp_ai_supervisor/py.typed +0 -0
  19. mcp_ai_supervisor/server.py +654 -0
  20. mcp_ai_supervisor/utils/__init__.py +28 -0
  21. mcp_ai_supervisor/utils/error_handler.py +10 -0
  22. mcp_ai_supervisor/utils/memory_monitor.py +11 -0
  23. mcp_ai_supervisor/utils/paths.py +7 -0
  24. mcp_ai_supervisor/utils/resource_manager.py +15 -0
  25. mcp_ai_supervisor/utils/structure_checker.py +291 -0
  26. mcp_ai_supervisor/web/__init__.py +26 -0
  27. mcp_ai_supervisor/web/constants/__init__.py +8 -0
  28. mcp_ai_supervisor/web/constants/message_codes.py +173 -0
  29. mcp_ai_supervisor/web/core/__init__.py +30 -0
  30. mcp_ai_supervisor/web/core/agent_bridge.py +957 -0
  31. mcp_ai_supervisor/web/core/auto_responder.py +332 -0
  32. mcp_ai_supervisor/web/core/context_collector.py +124 -0
  33. mcp_ai_supervisor/web/core/conversation_recorder.py +751 -0
  34. mcp_ai_supervisor/web/core/delegate_manager.py +1193 -0
  35. mcp_ai_supervisor/web/core/feedback_mediator.py +259 -0
  36. mcp_ai_supervisor/web/core/message_channel.py +551 -0
  37. mcp_ai_supervisor/web/core/response_builder.py +333 -0
  38. mcp_ai_supervisor/web/core/scene_detector.py +184 -0
  39. mcp_ai_supervisor/web/core/task_state.py +194 -0
  40. mcp_ai_supervisor/web/locales/en/translation.json +643 -0
  41. mcp_ai_supervisor/web/locales/zh-CN/translation.json +629 -0
  42. mcp_ai_supervisor/web/locales/zh-TW/translation.json +648 -0
  43. mcp_ai_supervisor/web/main.py +747 -0
  44. mcp_ai_supervisor/web/managers/__init__.py +8 -0
  45. mcp_ai_supervisor/web/managers/desktop_manager.py +228 -0
  46. mcp_ai_supervisor/web/managers/server_manager.py +170 -0
  47. mcp_ai_supervisor/web/managers/session_manager.py +515 -0
  48. mcp_ai_supervisor/web/managers/workbench_connector.py +186 -0
  49. mcp_ai_supervisor/web/models/__init__.py +13 -0
  50. mcp_ai_supervisor/web/models/feedback_result.py +16 -0
  51. mcp_ai_supervisor/web/models/feedback_session.py +938 -0
  52. mcp_ai_supervisor/web/models/session_cleaner.py +245 -0
  53. mcp_ai_supervisor/web/models/session_commands.py +213 -0
  54. mcp_ai_supervisor/web/models/session_resolver.py +158 -0
  55. mcp_ai_supervisor/web/models/session_timer.py +242 -0
  56. mcp_ai_supervisor/web/routes/__init__.py +12 -0
  57. mcp_ai_supervisor/web/routes/main_routes.py +965 -0
  58. mcp_ai_supervisor/web/routes/settings_routes.py +195 -0
  59. mcp_ai_supervisor/web/routes/ws_handlers.py +270 -0
  60. mcp_ai_supervisor/web/static/css/audio-management.css +545 -0
  61. mcp_ai_supervisor/web/static/css/notification-settings.css +152 -0
  62. mcp_ai_supervisor/web/static/css/prompt-management.css +566 -0
  63. mcp_ai_supervisor/web/static/css/session-management.css +1428 -0
  64. mcp_ai_supervisor/web/static/css/styles.css +2267 -0
  65. mcp_ai_supervisor/web/static/favicon.ico +0 -0
  66. mcp_ai_supervisor/web/static/icon-192.png +0 -0
  67. mcp_ai_supervisor/web/static/icon.svg +11 -0
  68. mcp_ai_supervisor/web/static/index.html +37 -0
  69. mcp_ai_supervisor/web/static/js/app.js +1721 -0
  70. mcp_ai_supervisor/web/static/js/i18n.js +376 -0
  71. mcp_ai_supervisor/web/static/js/modules/audio/audio-manager.js +610 -0
  72. mcp_ai_supervisor/web/static/js/modules/audio/audio-settings-ui.js +732 -0
  73. mcp_ai_supervisor/web/static/js/modules/connection-monitor.js +435 -0
  74. mcp_ai_supervisor/web/static/js/modules/constants/message-codes.js +168 -0
  75. mcp_ai_supervisor/web/static/js/modules/countdown-manager.js +273 -0
  76. mcp_ai_supervisor/web/static/js/modules/drag-drop-handler.js +677 -0
  77. mcp_ai_supervisor/web/static/js/modules/file-upload-manager.js +555 -0
  78. mcp_ai_supervisor/web/static/js/modules/image-handler.js +199 -0
  79. mcp_ai_supervisor/web/static/js/modules/logger.js +404 -0
  80. mcp_ai_supervisor/web/static/js/modules/notification/notification-manager.js +360 -0
  81. mcp_ai_supervisor/web/static/js/modules/notification/notification-settings.js +344 -0
  82. mcp_ai_supervisor/web/static/js/modules/prompt/prompt-input-buttons.js +427 -0
  83. mcp_ai_supervisor/web/static/js/modules/prompt/prompt-manager.js +414 -0
  84. mcp_ai_supervisor/web/static/js/modules/prompt/prompt-modal.js +458 -0
  85. mcp_ai_supervisor/web/static/js/modules/prompt/prompt-settings-ui.js +524 -0
  86. mcp_ai_supervisor/web/static/js/modules/session/session-data-manager.js +1042 -0
  87. mcp_ai_supervisor/web/static/js/modules/session/session-details-modal.js +594 -0
  88. mcp_ai_supervisor/web/static/js/modules/session/session-ui-renderer.js +836 -0
  89. mcp_ai_supervisor/web/static/js/modules/session-manager.js +1059 -0
  90. mcp_ai_supervisor/web/static/js/modules/settings-manager.js +1002 -0
  91. mcp_ai_supervisor/web/static/js/modules/tab-manager.js +235 -0
  92. mcp_ai_supervisor/web/static/js/modules/textarea-height-manager.js +267 -0
  93. mcp_ai_supervisor/web/static/js/modules/ui-manager.js +578 -0
  94. mcp_ai_supervisor/web/static/js/modules/utils/dom-utils.js +392 -0
  95. mcp_ai_supervisor/web/static/js/modules/utils/status-utils.js +403 -0
  96. mcp_ai_supervisor/web/static/js/modules/utils/time-utils.js +440 -0
  97. mcp_ai_supervisor/web/static/js/modules/utils.js +557 -0
  98. mcp_ai_supervisor/web/static/js/modules/websocket-manager.js +875 -0
  99. mcp_ai_supervisor/web/static/js/modules/workbench-notification.js +103 -0
  100. mcp_ai_supervisor/web/static/js/vendor/marked.min.js +6 -0
  101. mcp_ai_supervisor/web/static/js/vendor/purify.min.js +3 -0
  102. mcp_ai_supervisor/web/templates/components/image-upload.html +43 -0
  103. mcp_ai_supervisor/web/templates/components/settings-card.html +58 -0
  104. mcp_ai_supervisor/web/templates/components/status-indicator.html +31 -0
  105. mcp_ai_supervisor/web/templates/components/toggle-switch.html +19 -0
  106. mcp_ai_supervisor/web/templates/feedback.html +1198 -0
  107. mcp_ai_supervisor/web/templates/index.html +378 -0
  108. mcp_ai_supervisor/web/utils/__init__.py +12 -0
  109. mcp_ai_supervisor/web/utils/browser.py +35 -0
  110. mcp_ai_supervisor/web/utils/compression_config.py +195 -0
  111. mcp_ai_supervisor/web/utils/compression_monitor.py +314 -0
  112. mcp_ai_supervisor/web/utils/ide_opener.py +286 -0
  113. mcp_ai_supervisor/web/utils/network.py +66 -0
  114. mcp_ai_supervisor/web/utils/port_manager.py +340 -0
  115. mcp_ai_supervisor/web/utils/session_cleanup_manager.py +543 -0
  116. mcp_ai_supervisor/web/utils/workbench_client.py +899 -0
  117. mcp_ai_supervisor/workbench/__init__.py +5 -0
  118. mcp_ai_supervisor/workbench/__main__.py +5 -0
@@ -0,0 +1,199 @@
1
+ /**
2
+ * MCP AI Supervisor - 圖片處理模組
3
+ * ==================================
4
+ *
5
+ * 處理圖片上傳、預覽、壓縮和管理功能
6
+ */
7
+
8
+ (function() {
9
+ 'use strict';
10
+
11
+ // 確保命名空間和依賴存在
12
+ window.MCPFeedback = window.MCPFeedback || {};
13
+ const Utils = window.MCPFeedback.Utils;
14
+
15
+ /**
16
+ * 圖片處理器建構函數
17
+ */
18
+ function ImageHandler(options) {
19
+ options = options || {};
20
+
21
+ this.imageSizeLimit = options.imageSizeLimit || 0;
22
+ this.enableBase64Detail = options.enableBase64Detail || false;
23
+ this.layoutMode = options.layoutMode || 'combined-vertical';
24
+ this.currentImagePrefix = '';
25
+
26
+ // UI 元素(保留用於設定同步)
27
+ this.imageSizeLimitSelect = null;
28
+ this.enableBase64DetailCheckbox = null;
29
+
30
+ // 回調函數
31
+ this.onSettingsChange = options.onSettingsChange || null;
32
+
33
+ // 創建檔案上傳管理器
34
+ const self = this;
35
+ this.fileUploadManager = new window.MCPFeedback.FileUploadManager({
36
+ maxFileSize: this.imageSizeLimit,
37
+ enableBase64Detail: this.enableBase64Detail,
38
+ onFileAdd: function(fileData) {
39
+ console.log('📁 檔案已添加:', fileData.name);
40
+ },
41
+ onFileRemove: function(fileData, index) {
42
+ console.log('🗑️ 檔案已移除:', fileData.name);
43
+ },
44
+ onSettingsChange: function() {
45
+ if (self.onSettingsChange) {
46
+ self.onSettingsChange();
47
+ }
48
+ }
49
+ });
50
+
51
+ console.log('🖼️ ImageHandler 建構函數初始化完成');
52
+ }
53
+
54
+ /**
55
+ * 初始化圖片處理器
56
+ */
57
+ ImageHandler.prototype.init = function() {
58
+ console.log('🖼️ 開始初始化圖片處理功能...');
59
+
60
+ // 初始化設定元素
61
+ this.initImageSettingsElements();
62
+
63
+ // 初始化檔案上傳管理器
64
+ this.fileUploadManager.initialize();
65
+
66
+ console.log('✅ 圖片處理功能初始化完成');
67
+ };
68
+
69
+ /**
70
+ * 動態初始化圖片相關元素
71
+ */
72
+ ImageHandler.prototype.initImageSettingsElements = function() {
73
+ // 查找設定頁籤中的圖片設定元素
74
+ this.imageSizeLimitSelect = Utils.safeQuerySelector('#settingsImageSizeLimit');
75
+ this.enableBase64DetailCheckbox = Utils.safeQuerySelector('#settingsEnableBase64Detail');
76
+
77
+ // 初始化設定事件監聽器
78
+ this.initImageSettings();
79
+
80
+ console.log('✅ 圖片設定元素初始化完成');
81
+ };
82
+
83
+
84
+
85
+
86
+
87
+ /**
88
+ * 移除圖片設定事件監聽器
89
+ */
90
+ ImageHandler.prototype.removeImageSettingsListeners = function() {
91
+ if (this.imageSizeLimitSelect && this.imageSizeLimitChangeHandler) {
92
+ this.imageSizeLimitSelect.removeEventListener('change', this.imageSizeLimitChangeHandler);
93
+ this.imageSizeLimitChangeHandler = null;
94
+ }
95
+
96
+ if (this.enableBase64DetailCheckbox && this.enableBase64DetailChangeHandler) {
97
+ this.enableBase64DetailCheckbox.removeEventListener('change', this.enableBase64DetailChangeHandler);
98
+ this.enableBase64DetailChangeHandler = null;
99
+ }
100
+ };
101
+
102
+ /**
103
+ * 初始化圖片設定事件
104
+ */
105
+ ImageHandler.prototype.initImageSettings = function() {
106
+ const self = this;
107
+
108
+ // 移除舊的設定事件監聽器
109
+ this.removeImageSettingsListeners();
110
+
111
+ if (this.imageSizeLimitSelect) {
112
+ this.imageSizeLimitChangeHandler = function(e) {
113
+ self.imageSizeLimit = parseInt(e.target.value);
114
+ if (self.onSettingsChange) {
115
+ self.onSettingsChange();
116
+ }
117
+ };
118
+ this.imageSizeLimitSelect.addEventListener('change', this.imageSizeLimitChangeHandler);
119
+ }
120
+
121
+ if (this.enableBase64DetailCheckbox) {
122
+ this.enableBase64DetailChangeHandler = function(e) {
123
+ self.enableBase64Detail = e.target.checked;
124
+ if (self.onSettingsChange) {
125
+ self.onSettingsChange();
126
+ }
127
+ };
128
+ this.enableBase64DetailCheckbox.addEventListener('change', this.enableBase64DetailChangeHandler);
129
+ }
130
+ };
131
+
132
+
133
+
134
+
135
+
136
+ /**
137
+ * 獲取圖片數據
138
+ */
139
+ ImageHandler.prototype.getImages = function() {
140
+ return this.fileUploadManager.getFiles();
141
+ };
142
+
143
+ /**
144
+ * 清空所有圖片
145
+ */
146
+ ImageHandler.prototype.clearImages = function() {
147
+ this.fileUploadManager.clearFiles();
148
+ };
149
+
150
+ /**
151
+ * 重新初始化(用於佈局模式切換)
152
+ */
153
+ ImageHandler.prototype.reinitialize = function(layoutMode) {
154
+ console.log('🔄 重新初始化圖片處理功能...');
155
+
156
+ this.layoutMode = layoutMode;
157
+
158
+ // 重新初始化設定元素
159
+ this.initImageSettingsElements();
160
+
161
+ console.log('✅ 圖片處理功能重新初始化完成');
162
+ };
163
+
164
+ /**
165
+ * 更新設定
166
+ */
167
+ ImageHandler.prototype.updateSettings = function(settings) {
168
+ this.imageSizeLimit = settings.imageSizeLimit || 0;
169
+ this.enableBase64Detail = settings.enableBase64Detail || false;
170
+
171
+ // 更新檔案上傳管理器設定
172
+ this.fileUploadManager.updateSettings({
173
+ imageSizeLimit: this.imageSizeLimit,
174
+ enableBase64Detail: this.enableBase64Detail
175
+ });
176
+
177
+ // 同步到 UI 元素
178
+ if (this.imageSizeLimitSelect) {
179
+ this.imageSizeLimitSelect.value = this.imageSizeLimit.toString();
180
+ }
181
+ if (this.enableBase64DetailCheckbox) {
182
+ this.enableBase64DetailCheckbox.checked = this.enableBase64Detail;
183
+ }
184
+ };
185
+
186
+ /**
187
+ * 清理資源
188
+ */
189
+ ImageHandler.prototype.cleanup = function() {
190
+ this.removeImageSettingsListeners();
191
+ this.fileUploadManager.cleanup();
192
+ };
193
+
194
+ // 將 ImageHandler 加入命名空間
195
+ window.MCPFeedback.ImageHandler = ImageHandler;
196
+
197
+ console.log('✅ ImageHandler 模組載入完成');
198
+
199
+ })();
@@ -0,0 +1,404 @@
1
+ /**
2
+ * MCP AI Supervisor - 日誌管理模組
3
+ * ===================================
4
+ *
5
+ * 統一的日誌管理系統,支援不同等級的日誌輸出
6
+ * 生產環境可關閉詳細日誌以提升效能
7
+ */
8
+
9
+ (function() {
10
+ 'use strict';
11
+
12
+ // 確保命名空間存在
13
+ window.MCPFeedback = window.MCPFeedback || {};
14
+
15
+ /**
16
+ * 日誌等級枚舉
17
+ */
18
+ const LogLevel = {
19
+ ERROR: 0, // 錯誤:嚴重問題,必須記錄
20
+ WARN: 1, // 警告:潛在問題,建議記錄
21
+ INFO: 2, // 資訊:一般資訊,正常記錄
22
+ DEBUG: 3, // 調試:詳細資訊,開發時記錄
23
+ TRACE: 4 // 追蹤:最詳細資訊,深度調試時記錄
24
+ };
25
+
26
+ /**
27
+ * 日誌等級名稱映射
28
+ */
29
+ const LogLevelNames = {
30
+ [LogLevel.ERROR]: 'ERROR',
31
+ [LogLevel.WARN]: 'WARN',
32
+ [LogLevel.INFO]: 'INFO',
33
+ [LogLevel.DEBUG]: 'DEBUG',
34
+ [LogLevel.TRACE]: 'TRACE'
35
+ };
36
+
37
+ /**
38
+ * 日誌管理器
39
+ */
40
+ function Logger(options) {
41
+ options = options || {};
42
+
43
+ // 當前日誌等級(預設為 INFO)
44
+ this.currentLevel = this.parseLogLevel(options.level) || LogLevel.INFO;
45
+
46
+ // 模組名稱
47
+ this.moduleName = options.moduleName || 'App';
48
+
49
+ // 是否啟用時間戳
50
+ this.enableTimestamp = options.enableTimestamp !== false;
51
+
52
+ // 是否啟用模組名稱
53
+ this.enableModuleName = options.enableModuleName !== false;
54
+
55
+ // 是否啟用顏色(僅在支援的環境中)
56
+ this.enableColors = options.enableColors !== false;
57
+
58
+ // 自訂輸出函數
59
+ this.customOutput = options.customOutput || null;
60
+
61
+ // 日誌緩衝區(用於收集日誌)
62
+ this.logBuffer = [];
63
+ this.maxBufferSize = options.maxBufferSize || 1000;
64
+
65
+ // 顏色映射
66
+ this.colors = {
67
+ [LogLevel.ERROR]: '#f87171',
68
+ [LogLevel.WARN]: '#fbbf24',
69
+ [LogLevel.INFO]: '#6366f1',
70
+ [LogLevel.DEBUG]: '#34d399',
71
+ [LogLevel.TRACE]: '#a78bfa'
72
+ };
73
+ }
74
+
75
+ /**
76
+ * 解析日誌等級
77
+ */
78
+ Logger.prototype.parseLogLevel = function(level) {
79
+ if (typeof level === 'number') {
80
+ return level;
81
+ }
82
+
83
+ if (typeof level === 'string') {
84
+ const upperLevel = level.toUpperCase();
85
+ for (const [value, name] of Object.entries(LogLevelNames)) {
86
+ if (name === upperLevel) {
87
+ return parseInt(value);
88
+ }
89
+ }
90
+ }
91
+
92
+ return null;
93
+ };
94
+
95
+ /**
96
+ * 設置日誌等級
97
+ */
98
+ Logger.prototype.setLevel = function(level) {
99
+ const parsedLevel = this.parseLogLevel(level);
100
+ if (parsedLevel !== null) {
101
+ this.currentLevel = parsedLevel;
102
+ this.info('日誌等級已設置為:', LogLevelNames[this.currentLevel]);
103
+ } else {
104
+ this.warn('無效的日誌等級:', level);
105
+ }
106
+ };
107
+
108
+ /**
109
+ * 獲取當前日誌等級
110
+ */
111
+ Logger.prototype.getLevel = function() {
112
+ return this.currentLevel;
113
+ };
114
+
115
+ /**
116
+ * 檢查是否應該記錄指定等級的日誌
117
+ */
118
+ Logger.prototype.shouldLog = function(level) {
119
+ return level <= this.currentLevel;
120
+ };
121
+
122
+ /**
123
+ * 格式化日誌訊息
124
+ */
125
+ Logger.prototype.formatMessage = function(level, args) {
126
+ const parts = [];
127
+
128
+ // 添加時間戳
129
+ if (this.enableTimestamp) {
130
+ const now = new Date();
131
+ const timestamp = now.toISOString().substr(11, 12); // HH:mm:ss.SSS
132
+ parts.push(`[${timestamp}]`);
133
+ }
134
+
135
+ // 添加等級
136
+ parts.push(`[${LogLevelNames[level]}]`);
137
+
138
+ // 添加模組名稱
139
+ if (this.enableModuleName) {
140
+ parts.push(`[${this.moduleName}]`);
141
+ }
142
+
143
+ // 組合前綴
144
+ const prefix = parts.join(' ');
145
+
146
+ // 轉換參數為字符串
147
+ const messages = Array.from(args).map(arg => {
148
+ if (typeof arg === 'object') {
149
+ try {
150
+ return JSON.stringify(arg, null, 2);
151
+ } catch (e) {
152
+ return String(arg);
153
+ }
154
+ }
155
+ return String(arg);
156
+ });
157
+
158
+ return {
159
+ prefix: prefix,
160
+ message: messages.join(' '),
161
+ fullMessage: prefix + ' ' + messages.join(' ')
162
+ };
163
+ };
164
+
165
+ /**
166
+ * 輸出日誌
167
+ */
168
+ Logger.prototype.output = function(level, formatted) {
169
+ // 添加到緩衝區
170
+ this.addToBuffer(level, formatted);
171
+
172
+ // 如果有自訂輸出函數,使用它
173
+ if (this.customOutput) {
174
+ this.customOutput(level, formatted);
175
+ return;
176
+ }
177
+
178
+ // 使用瀏覽器控制台
179
+ const consoleMethods = {
180
+ [LogLevel.ERROR]: 'error',
181
+ [LogLevel.WARN]: 'warn',
182
+ [LogLevel.INFO]: 'info',
183
+ [LogLevel.DEBUG]: 'log',
184
+ [LogLevel.TRACE]: 'log'
185
+ };
186
+
187
+ const method = consoleMethods[level] || 'log';
188
+
189
+ // 如果支援顏色且啟用
190
+ if (this.enableColors && console.log.toString().indexOf('native') === -1) {
191
+ const color = this.colors[level];
192
+ console[method](`%c${formatted.fullMessage}`, `color: ${color}`);
193
+ } else {
194
+ console[method](formatted.fullMessage);
195
+ }
196
+ };
197
+
198
+ /**
199
+ * 添加到日誌緩衝區
200
+ */
201
+ Logger.prototype.addToBuffer = function(level, formatted) {
202
+ const logEntry = {
203
+ timestamp: Date.now(),
204
+ level: level,
205
+ levelName: LogLevelNames[level],
206
+ moduleName: this.moduleName,
207
+ message: formatted.message,
208
+ fullMessage: formatted.fullMessage
209
+ };
210
+
211
+ this.logBuffer.push(logEntry);
212
+
213
+ // 限制緩衝區大小
214
+ if (this.logBuffer.length > this.maxBufferSize) {
215
+ this.logBuffer.shift();
216
+ }
217
+ };
218
+
219
+ /**
220
+ * 通用日誌方法
221
+ */
222
+ Logger.prototype.log = function(level) {
223
+ if (!this.shouldLog(level)) {
224
+ return;
225
+ }
226
+
227
+ const args = Array.prototype.slice.call(arguments, 1);
228
+ const formatted = this.formatMessage(level, args);
229
+ this.output(level, formatted);
230
+ };
231
+
232
+ /**
233
+ * 錯誤日誌
234
+ */
235
+ Logger.prototype.error = function() {
236
+ this.log.apply(this, [LogLevel.ERROR].concat(Array.prototype.slice.call(arguments)));
237
+ };
238
+
239
+ /**
240
+ * 警告日誌
241
+ */
242
+ Logger.prototype.warn = function() {
243
+ this.log.apply(this, [LogLevel.WARN].concat(Array.prototype.slice.call(arguments)));
244
+ };
245
+
246
+ /**
247
+ * 資訊日誌
248
+ */
249
+ Logger.prototype.info = function() {
250
+ this.log.apply(this, [LogLevel.INFO].concat(Array.prototype.slice.call(arguments)));
251
+ };
252
+
253
+ /**
254
+ * 調試日誌
255
+ */
256
+ Logger.prototype.debug = function() {
257
+ this.log.apply(this, [LogLevel.DEBUG].concat(Array.prototype.slice.call(arguments)));
258
+ };
259
+
260
+ /**
261
+ * 追蹤日誌
262
+ */
263
+ Logger.prototype.trace = function() {
264
+ this.log.apply(this, [LogLevel.TRACE].concat(Array.prototype.slice.call(arguments)));
265
+ };
266
+
267
+ /**
268
+ * 獲取日誌緩衝區
269
+ */
270
+ Logger.prototype.getBuffer = function() {
271
+ return this.logBuffer.slice(); // 返回副本
272
+ };
273
+
274
+ /**
275
+ * 清空日誌緩衝區
276
+ */
277
+ Logger.prototype.clearBuffer = function() {
278
+ this.logBuffer = [];
279
+ };
280
+
281
+ /**
282
+ * 導出日誌
283
+ */
284
+ Logger.prototype.exportLogs = function(options) {
285
+ options = options || {};
286
+ const format = options.format || 'json';
287
+ const minLevel = this.parseLogLevel(options.minLevel) || LogLevel.ERROR;
288
+
289
+ const filteredLogs = this.logBuffer.filter(log => log.level <= minLevel);
290
+
291
+ if (format === 'json') {
292
+ return JSON.stringify(filteredLogs, null, 2);
293
+ } else if (format === 'text') {
294
+ return filteredLogs.map(log => log.fullMessage).join('\n');
295
+ }
296
+
297
+ return filteredLogs;
298
+ };
299
+
300
+ // 全域日誌管理器
301
+ const globalLogger = new Logger({
302
+ moduleName: 'Global',
303
+ level: LogLevel.INFO
304
+ });
305
+
306
+ // 從環境變數或 URL 參數檢測日誌等級
307
+ function detectLogLevel() {
308
+ // 檢查 URL 參數
309
+ const urlParams = new URLSearchParams(window.location.search);
310
+ const urlLogLevel = urlParams.get('logLevel') || urlParams.get('log_level');
311
+ if (urlLogLevel) {
312
+ return urlLogLevel;
313
+ }
314
+
315
+ // 檢查是否為開發環境
316
+ if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
317
+ return LogLevel.DEBUG;
318
+ }
319
+
320
+ return LogLevel.INFO;
321
+ }
322
+
323
+ // 從 API 載入日誌等級
324
+ function loadLogLevelFromAPI() {
325
+ const lang = window.i18nManager ? window.i18nManager.getCurrentLanguage() : 'zh-TW';
326
+ fetch('/api/log-level?lang=' + lang)
327
+ .then(function(response) {
328
+ if (response.ok) {
329
+ return response.json();
330
+ }
331
+ throw new Error('載入日誌等級失敗: ' + response.status);
332
+ })
333
+ .then(function(data) {
334
+ const apiLogLevel = data.logLevel;
335
+ if (apiLogLevel && Object.values(LogLevel).includes(apiLogLevel)) {
336
+ currentLogLevel = apiLogLevel;
337
+ console.log('📋 從 API 載入日誌等級:', apiLogLevel);
338
+ }
339
+ })
340
+ .catch(function(error) {
341
+ console.warn('⚠️ 載入日誌等級失敗,使用預設值:', error);
342
+ });
343
+ }
344
+
345
+ // 保存日誌等級到 API
346
+ function saveLogLevelToAPI(logLevel) {
347
+ const lang = window.i18nManager ? window.i18nManager.getCurrentLanguage() : 'zh-TW';
348
+ fetch('/api/log-level?lang=' + lang, {
349
+ method: 'POST',
350
+ headers: {
351
+ 'Content-Type': 'application/json',
352
+ },
353
+ body: JSON.stringify({
354
+ logLevel: logLevel
355
+ })
356
+ })
357
+ .then(function(response) {
358
+ if (response.ok) {
359
+ return response.json();
360
+ }
361
+ throw new Error('保存日誌等級失敗: ' + response.status);
362
+ })
363
+ .then(function(data) {
364
+ console.log('📋 日誌等級已保存:', data.logLevel);
365
+ // 處理訊息代碼
366
+ if (data.messageCode && window.i18nManager) {
367
+ const message = window.i18nManager.t(data.messageCode, data.params);
368
+ console.log('伺服器回應:', message);
369
+ }
370
+ })
371
+ .catch(function(error) {
372
+ console.warn('⚠️ 保存日誌等級失敗:', error);
373
+ });
374
+ }
375
+
376
+ // 設置全域日誌等級
377
+ globalLogger.setLevel(detectLogLevel());
378
+
379
+ // 頁面載入後從 API 載入日誌等級
380
+ if (document.readyState === 'loading') {
381
+ document.addEventListener('DOMContentLoaded', loadLogLevelFromAPI);
382
+ } else {
383
+ loadLogLevelFromAPI();
384
+ }
385
+
386
+ // 匯出到全域命名空間
387
+ window.MCPFeedback.Logger = Logger;
388
+ window.MCPFeedback.LogLevel = LogLevel;
389
+ window.MCPFeedback.logger = globalLogger;
390
+
391
+ // 匯出設定方法
392
+ window.MCPFeedback.setLogLevel = function(logLevel) {
393
+ if (Object.values(LogLevel).includes(logLevel)) {
394
+ globalLogger.setLevel(logLevel);
395
+ saveLogLevelToAPI(logLevel);
396
+ console.log('📋 日誌等級已更新:', LogLevelNames[logLevel]);
397
+ } else {
398
+ console.warn('⚠️ 無效的日誌等級:', logLevel);
399
+ }
400
+ };
401
+
402
+ console.log('✅ Logger 模組載入完成,當前等級:', LogLevelNames[globalLogger.getLevel()]);
403
+
404
+ })();