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,458 @@
1
+ /**
2
+ * MCP AI Supervisor - 提示詞彈窗管理模組
3
+ * ==========================================
4
+ *
5
+ * 處理提示詞新增、編輯、選擇的彈窗介面
6
+ */
7
+
8
+ (function() {
9
+ 'use strict';
10
+
11
+ // 確保命名空間存在
12
+ window.MCPFeedback = window.MCPFeedback || {};
13
+ window.MCPFeedback.Prompt = window.MCPFeedback.Prompt || {};
14
+
15
+ const Utils = window.MCPFeedback.Utils;
16
+
17
+ /**
18
+ * 提示詞彈窗管理器
19
+ */
20
+ function PromptModal(options) {
21
+ options = options || {};
22
+
23
+ // 彈窗選項
24
+ this.enableEscapeClose = options.enableEscapeClose !== false;
25
+ this.enableBackdropClose = options.enableBackdropClose !== false;
26
+
27
+ // 當前彈窗引用
28
+ this.currentModal = null;
29
+ this.keydownHandler = null;
30
+
31
+ // 回調函數
32
+ this.onSave = options.onSave || null;
33
+ this.onSelect = options.onSelect || null;
34
+ this.onCancel = options.onCancel || null;
35
+
36
+ console.log('🔍 PromptModal 初始化完成');
37
+ }
38
+
39
+ /**
40
+ * 顯示新增提示詞彈窗
41
+ */
42
+ PromptModal.prototype.showAddModal = function() {
43
+ const modalData = {
44
+ type: 'add',
45
+ title: this.t('prompts.modal.addTitle', '新增提示詞'),
46
+ prompt: {
47
+ name: '',
48
+ content: ''
49
+ }
50
+ };
51
+
52
+ this.createAndShowModal(modalData);
53
+ };
54
+
55
+ /**
56
+ * 顯示編輯提示詞彈窗
57
+ */
58
+ PromptModal.prototype.showEditModal = function(prompt) {
59
+ if (!prompt) {
60
+ console.error('❌ 編輯提示詞時缺少提示詞資料');
61
+ return;
62
+ }
63
+
64
+ const modalData = {
65
+ type: 'edit',
66
+ title: this.t('prompts.modal.editTitle', '編輯提示詞'),
67
+ prompt: {
68
+ id: prompt.id,
69
+ name: prompt.name,
70
+ content: prompt.content
71
+ }
72
+ };
73
+
74
+ this.createAndShowModal(modalData);
75
+ };
76
+
77
+ /**
78
+ * 顯示選擇提示詞彈窗
79
+ */
80
+ PromptModal.prototype.showSelectModal = function(prompts) {
81
+ if (!prompts || !Array.isArray(prompts)) {
82
+ console.error('❌ 選擇提示詞時缺少提示詞列表');
83
+ return;
84
+ }
85
+
86
+ const modalData = {
87
+ type: 'select',
88
+ title: this.t('prompts.select.title', '選擇常用提示詞'),
89
+ prompts: prompts
90
+ };
91
+
92
+ this.createAndShowModal(modalData);
93
+ };
94
+
95
+ /**
96
+ * 創建並顯示彈窗
97
+ */
98
+ PromptModal.prototype.createAndShowModal = function(modalData) {
99
+ // 如果已有彈窗,先關閉
100
+ if (this.currentModal) {
101
+ this.closeModal();
102
+ }
103
+
104
+ // 創建彈窗 HTML
105
+ const modalHtml = this.createModalHTML(modalData);
106
+
107
+ // 插入到頁面中
108
+ document.body.insertAdjacentHTML('beforeend', modalHtml);
109
+
110
+ // 獲取彈窗元素
111
+ this.currentModal = document.getElementById('promptModal');
112
+
113
+ // 設置事件監聽器
114
+ this.setupEventListeners(modalData);
115
+
116
+ // 添加顯示動畫
117
+ this.showModal();
118
+
119
+ // 聚焦到第一個輸入框
120
+ this.focusFirstInput();
121
+ };
122
+
123
+ /**
124
+ * 創建彈窗 HTML
125
+ */
126
+ PromptModal.prototype.createModalHTML = function(modalData) {
127
+ const modalId = 'promptModal';
128
+
129
+ if (modalData.type === 'select') {
130
+ return this.createSelectModalHTML(modalId, modalData);
131
+ } else {
132
+ return this.createEditModalHTML(modalId, modalData);
133
+ }
134
+ };
135
+
136
+ /**
137
+ * 創建編輯彈窗 HTML
138
+ */
139
+ PromptModal.prototype.createEditModalHTML = function(modalId, modalData) {
140
+ return `
141
+ <div id="${modalId}" class="modal-overlay">
142
+ <div class="modal-container">
143
+ <div class="modal-header">
144
+ <h3 class="modal-title">${Utils.escapeHtml(modalData.title)}</h3>
145
+ <button type="button" class="modal-close-btn" aria-label="關閉">×</button>
146
+ </div>
147
+ <div class="modal-body">
148
+ <form id="promptForm" class="prompt-form">
149
+ <div class="input-group">
150
+ <label for="promptName" class="input-label">${this.t('prompts.modal.nameLabel', '提示詞名稱')}</label>
151
+ <input
152
+ type="text"
153
+ id="promptName"
154
+ class="text-input"
155
+ value="${Utils.escapeHtml(modalData.prompt.name)}"
156
+ placeholder="${this.t('prompts.modal.namePlaceholder', '請輸入提示詞名稱...')}"
157
+ required
158
+ maxlength="100"
159
+ />
160
+ </div>
161
+ <div class="input-group">
162
+ <label for="promptContent" class="input-label">${this.t('prompts.modal.contentLabel', '提示詞內容')}</label>
163
+ <textarea
164
+ id="promptContent"
165
+ class="text-input"
166
+ placeholder="${this.t('prompts.modal.contentPlaceholder', '請輸入提示詞內容...')}"
167
+ required
168
+ rows="8"
169
+ style="min-height: 200px; resize: vertical;"
170
+ >${Utils.escapeHtml(modalData.prompt.content)}</textarea>
171
+ </div>
172
+ </form>
173
+ </div>
174
+ <div class="modal-footer">
175
+ <button type="button" class="btn btn-secondary modal-cancel-btn">
176
+ ${this.t('prompts.modal.cancel', '取消')}
177
+ </button>
178
+ <button type="submit" form="promptForm" class="btn btn-primary modal-save-btn">
179
+ ${this.t('prompts.modal.save', '儲存')}
180
+ </button>
181
+ </div>
182
+ </div>
183
+ </div>
184
+ `;
185
+ };
186
+
187
+ /**
188
+ * 創建選擇彈窗 HTML
189
+ */
190
+ PromptModal.prototype.createSelectModalHTML = function(modalId, modalData) {
191
+ const promptsHtml = modalData.prompts.map(prompt => `
192
+ <div class="prompt-item" data-prompt-id="${prompt.id}">
193
+ <div class="prompt-item-header">
194
+ <h4 class="prompt-item-name">${Utils.escapeHtml(prompt.name)}</h4>
195
+ <span class="prompt-item-date">${this.formatDate(prompt.createdAt)}</span>
196
+ </div>
197
+ <div class="prompt-item-content">${Utils.escapeHtml(this.truncateText(prompt.content, 100))}</div>
198
+ ${prompt.lastUsedAt ? `<div class="prompt-item-used">最近使用:${this.formatDate(prompt.lastUsedAt)}</div>` : ''}
199
+ </div>
200
+ `).join('');
201
+
202
+ return `
203
+ <div id="${modalId}" class="modal-overlay">
204
+ <div class="modal-container modal-large">
205
+ <div class="modal-header">
206
+ <h3 class="modal-title">${Utils.escapeHtml(modalData.title)}</h3>
207
+ <button type="button" class="modal-close-btn" aria-label="關閉">×</button>
208
+ </div>
209
+ <div class="modal-body">
210
+ <div class="prompt-list">
211
+ ${promptsHtml || '<div class="empty-state">尚無常用提示詞</div>'}
212
+ </div>
213
+ </div>
214
+ <div class="modal-footer">
215
+ <button type="button" class="btn btn-secondary modal-cancel-btn">
216
+ ${this.t('prompts.modal.cancel', '取消')}
217
+ </button>
218
+ </div>
219
+ </div>
220
+ </div>
221
+ `;
222
+ };
223
+
224
+ /**
225
+ * 設置事件監聽器
226
+ */
227
+ PromptModal.prototype.setupEventListeners = function(modalData) {
228
+ const self = this;
229
+
230
+ // 關閉按鈕
231
+ const closeBtn = this.currentModal.querySelector('.modal-close-btn');
232
+ if (closeBtn) {
233
+ closeBtn.addEventListener('click', function() {
234
+ self.closeModal();
235
+ });
236
+ }
237
+
238
+ // 取消按鈕
239
+ const cancelBtn = this.currentModal.querySelector('.modal-cancel-btn');
240
+ if (cancelBtn) {
241
+ cancelBtn.addEventListener('click', function() {
242
+ self.closeModal();
243
+ });
244
+ }
245
+
246
+ // 背景點擊關閉
247
+ if (this.enableBackdropClose) {
248
+ this.currentModal.addEventListener('click', function(e) {
249
+ if (e.target === self.currentModal) {
250
+ self.closeModal();
251
+ }
252
+ });
253
+ }
254
+
255
+ // ESC 鍵關閉
256
+ if (this.enableEscapeClose) {
257
+ this.keydownHandler = function(e) {
258
+ if (e.key === 'Escape') {
259
+ self.closeModal();
260
+ }
261
+ };
262
+ document.addEventListener('keydown', this.keydownHandler);
263
+ }
264
+
265
+ // 根據彈窗類型設置特定事件
266
+ if (modalData.type === 'select') {
267
+ this.setupSelectModalEvents();
268
+ } else {
269
+ this.setupEditModalEvents(modalData);
270
+ }
271
+ };
272
+
273
+ /**
274
+ * 設置編輯彈窗事件
275
+ */
276
+ PromptModal.prototype.setupEditModalEvents = function(modalData) {
277
+ const self = this;
278
+ const form = this.currentModal.querySelector('#promptForm');
279
+
280
+ if (form) {
281
+ form.addEventListener('submit', function(e) {
282
+ e.preventDefault();
283
+ self.handleFormSubmit(modalData);
284
+ });
285
+ }
286
+ };
287
+
288
+ /**
289
+ * 設置選擇彈窗事件
290
+ */
291
+ PromptModal.prototype.setupSelectModalEvents = function() {
292
+ const self = this;
293
+ const promptItems = this.currentModal.querySelectorAll('.prompt-item');
294
+
295
+ promptItems.forEach(function(item) {
296
+ item.addEventListener('click', function() {
297
+ const promptId = item.getAttribute('data-prompt-id');
298
+ self.handlePromptSelect(promptId);
299
+ });
300
+ });
301
+ };
302
+
303
+ /**
304
+ * 處理表單提交
305
+ */
306
+ PromptModal.prototype.handleFormSubmit = function(modalData) {
307
+ const nameInput = this.currentModal.querySelector('#promptName');
308
+ const contentInput = this.currentModal.querySelector('#promptContent');
309
+
310
+ if (!nameInput || !contentInput) {
311
+ console.error('❌ 找不到表單輸入元素');
312
+ return;
313
+ }
314
+
315
+ const name = nameInput.value.trim();
316
+ const content = contentInput.value.trim();
317
+
318
+ if (!name || !content) {
319
+ this.showError(this.t('prompts.modal.emptyFields', '請填寫所有必填欄位'));
320
+ return;
321
+ }
322
+
323
+ const promptData = {
324
+ name: name,
325
+ content: content
326
+ };
327
+
328
+ if (modalData.type === 'edit') {
329
+ promptData.id = modalData.prompt.id;
330
+ }
331
+
332
+ // 觸發保存回調
333
+ if (this.onSave) {
334
+ try {
335
+ this.onSave(promptData, modalData.type);
336
+ this.closeModal();
337
+ } catch (error) {
338
+ this.showError(error.message);
339
+ }
340
+ }
341
+ };
342
+
343
+ /**
344
+ * 處理提示詞選擇
345
+ */
346
+ PromptModal.prototype.handlePromptSelect = function(promptId) {
347
+ if (this.onSelect) {
348
+ this.onSelect(promptId);
349
+ }
350
+ this.closeModal();
351
+ };
352
+
353
+ /**
354
+ * 顯示彈窗動畫
355
+ */
356
+ PromptModal.prototype.showModal = function() {
357
+ if (!this.currentModal) return;
358
+
359
+ // 添加顯示類觸發動畫
360
+ requestAnimationFrame(() => {
361
+ this.currentModal.classList.add('show');
362
+ });
363
+ };
364
+
365
+ /**
366
+ * 關閉彈窗
367
+ */
368
+ PromptModal.prototype.closeModal = function() {
369
+ if (!this.currentModal) return;
370
+
371
+ // 移除鍵盤事件監聽器
372
+ if (this.keydownHandler) {
373
+ document.removeEventListener('keydown', this.keydownHandler);
374
+ this.keydownHandler = null;
375
+ }
376
+
377
+ // 添加關閉動畫
378
+ this.currentModal.classList.add('hide');
379
+
380
+ // 延遲移除元素
381
+ setTimeout(() => {
382
+ if (this.currentModal) {
383
+ this.currentModal.remove();
384
+ this.currentModal = null;
385
+ }
386
+ }, 300); // 與 CSS 動畫時間一致
387
+
388
+ // 觸發取消回調
389
+ if (this.onCancel) {
390
+ this.onCancel();
391
+ }
392
+ };
393
+
394
+ /**
395
+ * 聚焦到第一個輸入框
396
+ */
397
+ PromptModal.prototype.focusFirstInput = function() {
398
+ if (!this.currentModal) return;
399
+
400
+ const firstInput = this.currentModal.querySelector('input, textarea');
401
+ if (firstInput) {
402
+ setTimeout(() => {
403
+ firstInput.focus();
404
+ }, 100);
405
+ }
406
+ };
407
+
408
+ /**
409
+ * 顯示錯誤訊息
410
+ */
411
+ PromptModal.prototype.showError = function(message) {
412
+ if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
413
+ window.MCPFeedback.Utils.showMessage(message, 'error');
414
+ } else {
415
+ alert(message);
416
+ }
417
+ };
418
+
419
+ /**
420
+ * 翻譯函數
421
+ */
422
+ PromptModal.prototype.t = function(key, fallback) {
423
+ if (window.i18nManager && typeof window.i18nManager.t === 'function') {
424
+ return window.i18nManager.t(key, fallback);
425
+ }
426
+ return fallback || key;
427
+ };
428
+
429
+ /**
430
+ * 格式化日期
431
+ */
432
+ PromptModal.prototype.formatDate = function(dateString) {
433
+ if (!dateString) return '';
434
+
435
+ try {
436
+ const date = new Date(dateString);
437
+ return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
438
+ } catch (error) {
439
+ return dateString;
440
+ }
441
+ };
442
+
443
+ /**
444
+ * 截斷文字
445
+ */
446
+ PromptModal.prototype.truncateText = function(text, maxLength) {
447
+ if (!text || text.length <= maxLength) {
448
+ return text;
449
+ }
450
+ return text.substring(0, maxLength) + '...';
451
+ };
452
+
453
+ // 將 PromptModal 加入命名空間
454
+ window.MCPFeedback.Prompt.PromptModal = PromptModal;
455
+
456
+ console.log('✅ PromptModal 模組載入完成');
457
+
458
+ })();