open-swarm 0.1.1743070217__py3-none-any.whl → 0.1.1743362777__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 (217) hide show
  1. open_swarm-0.1.1743362777.dist-info/METADATA +217 -0
  2. open_swarm-0.1.1743362777.dist-info/RECORD +260 -0
  3. {open_swarm-0.1.1743070217.dist-info → open_swarm-0.1.1743362777.dist-info}/WHEEL +1 -2
  4. open_swarm-0.1.1743362777.dist-info/entry_points.txt +2 -0
  5. swarm/__init__.py +0 -2
  6. swarm/auth.py +53 -49
  7. swarm/blueprints/README.md +67 -0
  8. swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py +412 -0
  9. swarm/blueprints/chatbot/blueprint_chatbot.py +98 -0
  10. swarm/blueprints/chatbot/templates/chatbot/chatbot.html +33 -0
  11. swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +183 -0
  12. swarm/blueprints/dilbot_universe/blueprint_dilbot_universe.py +285 -0
  13. swarm/blueprints/divine_code/__init__.py +0 -0
  14. swarm/blueprints/divine_code/apps.py +11 -0
  15. swarm/blueprints/divine_code/blueprint_divine_code.py +219 -0
  16. swarm/blueprints/django_chat/apps.py +6 -0
  17. swarm/blueprints/django_chat/blueprint_django_chat.py +84 -0
  18. swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +37 -0
  19. swarm/blueprints/django_chat/urls.py +8 -0
  20. swarm/blueprints/django_chat/views.py +32 -0
  21. swarm/blueprints/echocraft/blueprint_echocraft.py +44 -0
  22. swarm/blueprints/family_ties/apps.py +11 -0
  23. swarm/blueprints/family_ties/blueprint_family_ties.py +152 -0
  24. swarm/blueprints/family_ties/models.py +19 -0
  25. swarm/blueprints/family_ties/serializers.py +7 -0
  26. swarm/blueprints/family_ties/settings.py +16 -0
  27. swarm/blueprints/family_ties/urls.py +10 -0
  28. swarm/blueprints/family_ties/views.py +26 -0
  29. swarm/blueprints/flock/__init__.py +0 -0
  30. swarm/blueprints/gaggle/blueprint_gaggle.py +184 -0
  31. swarm/blueprints/gotchaman/blueprint_gotchaman.py +232 -0
  32. swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +133 -0
  33. swarm/blueprints/messenger/templates/messenger/messenger.html +46 -0
  34. swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +234 -0
  35. swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +248 -0
  36. swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +156 -0
  37. swarm/blueprints/omniplex/blueprint_omniplex.py +221 -0
  38. swarm/blueprints/rue_code/__init__.py +0 -0
  39. swarm/blueprints/rue_code/blueprint_rue_code.py +291 -0
  40. swarm/blueprints/suggestion/blueprint_suggestion.py +110 -0
  41. swarm/blueprints/unapologetic_press/blueprint_unapologetic_press.py +298 -0
  42. swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
  43. swarm/blueprints/whiskeytango_foxtrot/apps.py +11 -0
  44. swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +256 -0
  45. swarm/extensions/blueprint/__init__.py +30 -15
  46. swarm/extensions/blueprint/agent_utils.py +16 -40
  47. swarm/extensions/blueprint/blueprint_base.py +141 -543
  48. swarm/extensions/blueprint/blueprint_discovery.py +112 -98
  49. swarm/extensions/blueprint/cli_handler.py +185 -0
  50. swarm/extensions/blueprint/config_loader.py +122 -0
  51. swarm/extensions/blueprint/django_utils.py +181 -79
  52. swarm/extensions/blueprint/interactive_mode.py +1 -1
  53. swarm/extensions/config/config_loader.py +83 -200
  54. swarm/extensions/launchers/build_swarm_wrapper.py +0 -0
  55. swarm/extensions/launchers/swarm_cli.py +199 -287
  56. swarm/llm/chat_completion.py +26 -55
  57. swarm/management/__init__.py +0 -0
  58. swarm/management/commands/__init__.py +0 -0
  59. swarm/management/commands/runserver.py +58 -0
  60. swarm/permissions.py +38 -0
  61. swarm/serializers.py +96 -5
  62. swarm/settings.py +95 -110
  63. swarm/static/contrib/fonts/fontawesome-webfont.ttf +7 -0
  64. swarm/static/contrib/fonts/fontawesome-webfont.woff +7 -0
  65. swarm/static/contrib/fonts/fontawesome-webfont.woff2 +7 -0
  66. swarm/static/contrib/markedjs/marked.min.js +6 -0
  67. swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +27 -0
  68. swarm/static/contrib/tabler-icons/alert-triangle.svg +21 -0
  69. swarm/static/contrib/tabler-icons/archive.svg +21 -0
  70. swarm/static/contrib/tabler-icons/artboard.svg +27 -0
  71. swarm/static/contrib/tabler-icons/automatic-gearbox.svg +23 -0
  72. swarm/static/contrib/tabler-icons/box-multiple.svg +19 -0
  73. swarm/static/contrib/tabler-icons/carambola.svg +19 -0
  74. swarm/static/contrib/tabler-icons/copy.svg +20 -0
  75. swarm/static/contrib/tabler-icons/download.svg +21 -0
  76. swarm/static/contrib/tabler-icons/edit.svg +21 -0
  77. swarm/static/contrib/tabler-icons/filled/carambola.svg +13 -0
  78. swarm/static/contrib/tabler-icons/filled/paint.svg +13 -0
  79. swarm/static/contrib/tabler-icons/headset.svg +22 -0
  80. swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +21 -0
  81. swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +21 -0
  82. swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +21 -0
  83. swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +21 -0
  84. swarm/static/contrib/tabler-icons/message-chatbot.svg +22 -0
  85. swarm/static/contrib/tabler-icons/message-star.svg +22 -0
  86. swarm/static/contrib/tabler-icons/message-x.svg +23 -0
  87. swarm/static/contrib/tabler-icons/message.svg +21 -0
  88. swarm/static/contrib/tabler-icons/paperclip.svg +18 -0
  89. swarm/static/contrib/tabler-icons/playlist-add.svg +22 -0
  90. swarm/static/contrib/tabler-icons/robot.svg +26 -0
  91. swarm/static/contrib/tabler-icons/search.svg +19 -0
  92. swarm/static/contrib/tabler-icons/settings.svg +20 -0
  93. swarm/static/contrib/tabler-icons/thumb-down.svg +19 -0
  94. swarm/static/contrib/tabler-icons/thumb-up.svg +19 -0
  95. swarm/static/css/dropdown.css +22 -0
  96. swarm/static/htmx/htmx.min.js +0 -0
  97. swarm/static/js/dropdown.js +23 -0
  98. swarm/static/rest_mode/css/base.css +470 -0
  99. swarm/static/rest_mode/css/chat-history.css +286 -0
  100. swarm/static/rest_mode/css/chat.css +251 -0
  101. swarm/static/rest_mode/css/chatbot.css +74 -0
  102. swarm/static/rest_mode/css/chatgpt.css +62 -0
  103. swarm/static/rest_mode/css/colors/corporate.css +74 -0
  104. swarm/static/rest_mode/css/colors/pastel.css +81 -0
  105. swarm/static/rest_mode/css/colors/tropical.css +82 -0
  106. swarm/static/rest_mode/css/general.css +142 -0
  107. swarm/static/rest_mode/css/layout.css +167 -0
  108. swarm/static/rest_mode/css/layouts/messenger-layout.css +17 -0
  109. swarm/static/rest_mode/css/layouts/minimalist-layout.css +57 -0
  110. swarm/static/rest_mode/css/layouts/mobile-layout.css +8 -0
  111. swarm/static/rest_mode/css/messages.css +84 -0
  112. swarm/static/rest_mode/css/messenger.css +135 -0
  113. swarm/static/rest_mode/css/settings.css +91 -0
  114. swarm/static/rest_mode/css/simple.css +44 -0
  115. swarm/static/rest_mode/css/slack.css +58 -0
  116. swarm/static/rest_mode/css/style.css +156 -0
  117. swarm/static/rest_mode/css/theme.css +30 -0
  118. swarm/static/rest_mode/css/toast.css +40 -0
  119. swarm/static/rest_mode/js/auth.js +9 -0
  120. swarm/static/rest_mode/js/blueprint.js +41 -0
  121. swarm/static/rest_mode/js/blueprintUtils.js +12 -0
  122. swarm/static/rest_mode/js/chatLogic.js +79 -0
  123. swarm/static/rest_mode/js/debug.js +63 -0
  124. swarm/static/rest_mode/js/events.js +98 -0
  125. swarm/static/rest_mode/js/main.js +19 -0
  126. swarm/static/rest_mode/js/messages.js +264 -0
  127. swarm/static/rest_mode/js/messengerLogic.js +355 -0
  128. swarm/static/rest_mode/js/modules/apiService.js +84 -0
  129. swarm/static/rest_mode/js/modules/blueprintManager.js +162 -0
  130. swarm/static/rest_mode/js/modules/chatHistory.js +110 -0
  131. swarm/static/rest_mode/js/modules/debugLogger.js +14 -0
  132. swarm/static/rest_mode/js/modules/eventHandlers.js +107 -0
  133. swarm/static/rest_mode/js/modules/messageProcessor.js +120 -0
  134. swarm/static/rest_mode/js/modules/state.js +7 -0
  135. swarm/static/rest_mode/js/modules/userInteractions.js +29 -0
  136. swarm/static/rest_mode/js/modules/validation.js +23 -0
  137. swarm/static/rest_mode/js/rendering.js +119 -0
  138. swarm/static/rest_mode/js/settings.js +130 -0
  139. swarm/static/rest_mode/js/sidebar.js +94 -0
  140. swarm/static/rest_mode/js/simpleLogic.js +37 -0
  141. swarm/static/rest_mode/js/slackLogic.js +66 -0
  142. swarm/static/rest_mode/js/splash.js +76 -0
  143. swarm/static/rest_mode/js/theme.js +111 -0
  144. swarm/static/rest_mode/js/toast.js +36 -0
  145. swarm/static/rest_mode/js/ui.js +265 -0
  146. swarm/static/rest_mode/js/validation.js +57 -0
  147. swarm/static/rest_mode/svg/animated_spinner.svg +12 -0
  148. swarm/static/rest_mode/svg/arrow_down.svg +5 -0
  149. swarm/static/rest_mode/svg/arrow_left.svg +5 -0
  150. swarm/static/rest_mode/svg/arrow_right.svg +5 -0
  151. swarm/static/rest_mode/svg/arrow_up.svg +5 -0
  152. swarm/static/rest_mode/svg/attach.svg +8 -0
  153. swarm/static/rest_mode/svg/avatar.svg +7 -0
  154. swarm/static/rest_mode/svg/canvas.svg +6 -0
  155. swarm/static/rest_mode/svg/chat_history.svg +4 -0
  156. swarm/static/rest_mode/svg/close.svg +5 -0
  157. swarm/static/rest_mode/svg/copy.svg +4 -0
  158. swarm/static/rest_mode/svg/dark_mode.svg +3 -0
  159. swarm/static/rest_mode/svg/edit.svg +5 -0
  160. swarm/static/rest_mode/svg/layout.svg +9 -0
  161. swarm/static/rest_mode/svg/logo.svg +29 -0
  162. swarm/static/rest_mode/svg/logout.svg +5 -0
  163. swarm/static/rest_mode/svg/mobile.svg +5 -0
  164. swarm/static/rest_mode/svg/new_chat.svg +4 -0
  165. swarm/static/rest_mode/svg/not_visible.svg +5 -0
  166. swarm/static/rest_mode/svg/plus.svg +7 -0
  167. swarm/static/rest_mode/svg/run_code.svg +6 -0
  168. swarm/static/rest_mode/svg/save.svg +4 -0
  169. swarm/static/rest_mode/svg/search.svg +6 -0
  170. swarm/static/rest_mode/svg/settings.svg +4 -0
  171. swarm/static/rest_mode/svg/speaker.svg +5 -0
  172. swarm/static/rest_mode/svg/stop.svg +6 -0
  173. swarm/static/rest_mode/svg/thumbs_down.svg +3 -0
  174. swarm/static/rest_mode/svg/thumbs_up.svg +3 -0
  175. swarm/static/rest_mode/svg/toggle_off.svg +6 -0
  176. swarm/static/rest_mode/svg/toggle_on.svg +6 -0
  177. swarm/static/rest_mode/svg/trash.svg +10 -0
  178. swarm/static/rest_mode/svg/undo.svg +3 -0
  179. swarm/static/rest_mode/svg/visible.svg +8 -0
  180. swarm/static/rest_mode/svg/voice.svg +10 -0
  181. swarm/templates/account/login.html +22 -0
  182. swarm/templates/account/signup.html +32 -0
  183. swarm/templates/base.html +30 -0
  184. swarm/templates/chat.html +43 -0
  185. swarm/templates/index.html +35 -0
  186. swarm/templates/rest_mode/components/chat_sidebar.html +55 -0
  187. swarm/templates/rest_mode/components/header.html +45 -0
  188. swarm/templates/rest_mode/components/main_chat_pane.html +41 -0
  189. swarm/templates/rest_mode/components/settings_dialog.html +97 -0
  190. swarm/templates/rest_mode/components/splash_screen.html +7 -0
  191. swarm/templates/rest_mode/components/top_bar.html +28 -0
  192. swarm/templates/rest_mode/message_ui.html +50 -0
  193. swarm/templates/rest_mode/slackbot.html +30 -0
  194. swarm/templates/simple_blueprint_page.html +24 -0
  195. swarm/templates/websocket_partials/final_system_message.html +3 -0
  196. swarm/templates/websocket_partials/system_message.html +4 -0
  197. swarm/templates/websocket_partials/user_message.html +5 -0
  198. swarm/urls.py +57 -74
  199. swarm/utils/log_utils.py +63 -0
  200. swarm/views/api_views.py +48 -39
  201. swarm/views/chat_views.py +156 -70
  202. swarm/views/core_views.py +85 -90
  203. swarm/views/model_views.py +64 -121
  204. swarm/views/utils.py +65 -441
  205. open_swarm-0.1.1743070217.dist-info/METADATA +0 -258
  206. open_swarm-0.1.1743070217.dist-info/RECORD +0 -89
  207. open_swarm-0.1.1743070217.dist-info/entry_points.txt +0 -3
  208. open_swarm-0.1.1743070217.dist-info/top_level.txt +0 -1
  209. swarm/agent/agent.py +0 -49
  210. swarm/core.py +0 -326
  211. swarm/extensions/mcp/__init__.py +0 -1
  212. swarm/extensions/mcp/cache_utils.py +0 -36
  213. swarm/extensions/mcp/mcp_client.py +0 -341
  214. swarm/extensions/mcp/mcp_constants.py +0 -7
  215. swarm/extensions/mcp/mcp_tool_provider.py +0 -110
  216. swarm/types.py +0 -126
  217. {open_swarm-0.1.1743070217.dist-info → open_swarm-0.1.1743362777.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,63 @@
1
+ // src/swarm/static/rest_mode/js/debug.js
2
+
3
+ import { showToast } from './toast.js';
4
+ import { chatHistory } from './modules/state.js';
5
+ import { contextVariables } from './modules/state.js';
6
+ export { debugLog } from './modules/debugLogger.js';
7
+
8
+ /**
9
+ * Toggles the Debug pane.
10
+ * Displays raw messages and key info from the most recent message.
11
+ */
12
+ export function toggleDebugPane() {
13
+ const debugPane = document.getElementById("debugPane");
14
+ if (!debugPane) return;
15
+
16
+ if (debugPane.style.display === "block") {
17
+ debugPane.style.display = "none";
18
+ showToast("🐞 Debug pane hidden.", "info");
19
+ } else {
20
+ debugPane.style.display = "block";
21
+ showToast("🐞 Debug pane shown.", "info");
22
+ renderRelevantDebugInfo();
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Handles Tech Support Button Click Inside Debug Pane
28
+ */
29
+ export function handleTechSupport() {
30
+ showToast("🛠️ Tech Support feature coming soon!", "info");
31
+ }
32
+
33
+ /**
34
+ * Renders relevant debug information from the most recent message in chatHistory.
35
+ */
36
+ function renderRelevantDebugInfo() {
37
+ const debugContent = document.getElementById("debugContent");
38
+ if (!debugContent) return;
39
+
40
+ if (chatHistory.length === 0) {
41
+ debugContent.innerHTML = "<p>No messages yet.</p>";
42
+ return;
43
+ }
44
+
45
+ const latestMessage = chatHistory[chatHistory.length - 1];
46
+ const { role, content, sender, metadata } = latestMessage;
47
+
48
+ debugContent.innerHTML = `
49
+ <p><strong>Role:</strong> ${role}</p>
50
+ <p><strong>Sender:</strong> ${sender}</p>
51
+ <p><strong>Content:</strong> ${content || "No content provided."}</p>
52
+ <p><strong>Metadata:</strong> <pre>${JSON.stringify(metadata || {}, null, 2)}</pre></p>
53
+ `;
54
+
55
+ if (contextVariables.active_agent_name) {
56
+ const activeAgentElement = document.createElement("div");
57
+ activeAgentElement.className = "debug-active-agent";
58
+ activeAgentElement.innerHTML = `<strong>Active Agent:</strong> ${contextVariables.active_agent_name}`;
59
+ debugContent.appendChild(activeAgentElement);
60
+ }
61
+
62
+ debugContent.scrollTop = debugContent.scrollHeight;
63
+ }
@@ -0,0 +1,98 @@
1
+ // src/swarm/static/rest_mode/js/events.js
2
+
3
+ import { toggleSidebar } from './sidebar.js';
4
+ import { handleChatHistoryClick } from './modules/chatHistory.js';
5
+ import { deleteChat } from './modules/apiService.js';
6
+ import { handleUpload, handleVoiceRecord } from './modules/userInteractions.js';
7
+ import { fetchBlueprintMetadata } from './modules/apiService.js';
8
+ import { handleSubmit } from './modules/messageProcessor.js';
9
+ import { toggleDebugPane, handleTechSupport } from './debug.js';
10
+ import { showToast } from './toast.js';
11
+ import { handleLogout } from './auth.js';
12
+ import { debugLog } from './modules/debugLogger.js';
13
+
14
+ /**
15
+ * Handles "Search" button click.
16
+ */
17
+ function handleSearch() {
18
+ showToast("🔍 Search feature is under development.", "info");
19
+ }
20
+
21
+ /**
22
+ * Handles "New Chat" button click.
23
+ */
24
+ function handleNewChat() {
25
+ showToast("📝 Starting a new chat...", "info");
26
+ // Implement new chat functionality as needed
27
+ }
28
+
29
+ /**
30
+ * Attaches event listeners to chat history items.
31
+ */
32
+ function setupChatHistoryListeners() {
33
+ const chatHistoryItems = document.querySelectorAll('.chat-history-pane li');
34
+ chatHistoryItems.forEach((item) => {
35
+ item.addEventListener('click', () => handleChatHistoryClick(item));
36
+
37
+ const trashCan = item.querySelector('.trash-can');
38
+ if (trashCan) {
39
+ trashCan.addEventListener('click', (e) => {
40
+ e.stopPropagation();
41
+ deleteChat(item);
42
+ });
43
+ }
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Attaches event listeners to main application buttons and elements.
49
+ */
50
+ function setupGlobalEventListeners() {
51
+ // Sidebar toggles
52
+ document.getElementById("settingsToggleButton")?.addEventListener('click', () => toggleSidebar('options', true));
53
+ document.getElementById("optionsSidebarHideBtn")?.addEventListener('click', () => toggleSidebar('options', false));
54
+ document.getElementById("chatHistoryToggleButton")?.addEventListener('click', () => toggleSidebar('left', true));
55
+ document.getElementById("leftSidebarHideBtn")?.addEventListener('click', () => toggleSidebar('left', false));
56
+
57
+ // Top buttons
58
+ // document.getElementById("searchButton")?.addEventListener('click', handleSearch);
59
+ document.getElementById("newChatButton")?.addEventListener('click', handleNewChat);
60
+
61
+ // Functional buttons
62
+ document.getElementById("logoutButton")?.addEventListener('click', handleLogout);
63
+ document.getElementById("uploadButton")?.addEventListener('click', handleUpload);
64
+ document.getElementById("voiceRecordButton")?.addEventListener('click', handleVoiceRecord);
65
+ document.getElementById("submitButton")?.addEventListener("click", handleSubmit);
66
+
67
+ // User input submission with Enter key
68
+ const userInput = document.getElementById("userInput");
69
+ userInput?.addEventListener("keypress", (e) => {
70
+ if (e.key === "Enter") {
71
+ e.preventDefault();
72
+ handleSubmit();
73
+ }
74
+ });
75
+
76
+ // Debug pane toggles
77
+ document.getElementById("debugButton")?.addEventListener('click', toggleDebugPane);
78
+ document.getElementById("techSupportButtonInsideDebug")?.addEventListener('click', handleTechSupport);
79
+ }
80
+
81
+ /**
82
+ * Sets up all event listeners for the application.
83
+ */
84
+ export function setupEventListeners() {
85
+ setupGlobalEventListeners();
86
+ setupChatHistoryListeners();
87
+ debugLog('All event listeners have been set up.');
88
+ }
89
+
90
+ /**
91
+ * Initialize the application.
92
+ */
93
+ export function initializeApplication() {
94
+ debugLog('[DEBUG] Initializing application...');
95
+ fetchBlueprintMetadata(); // Fetch blueprint metadata and display it
96
+ setupEventListeners(); // Set up event listeners
97
+ debugLog('[DEBUG] Application initialized.');
98
+ }
@@ -0,0 +1,19 @@
1
+ // main.js - Main application entry point
2
+
3
+ import { initializeSplashScreen } from './splash.js';
4
+ import { initializeUI } from './ui.js';
5
+ import { debugLog } from './settings.js';
6
+
7
+ document.addEventListener('DOMContentLoaded', () => {
8
+ debugLog("DOM Content Loaded. Initializing application...");
9
+
10
+ try {
11
+ initializeSplashScreen();
12
+ debugLog("Splash screen initialization complete.");
13
+
14
+ initializeUI();
15
+ debugLog("UI initialization complete.");
16
+ } catch (error) {
17
+ debugLog(`Initialization failed: ${error.message}`, "error");
18
+ }
19
+ });
@@ -0,0 +1,264 @@
1
+ import { debugLog } from './debug.js';
2
+ import { enableSlidingToolbar } from './ui.js';
3
+ // import { marked } from '../../contrib/markedjs/marked.min.js';
4
+ import { marked } from "https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js";
5
+
6
+ let quickPrompts = ["What is Open-Swarm?", "Explain the architecture.", "How do I set up a new blueprint?"];
7
+
8
+ export function renderMessage(role, content, sender, metadata) {
9
+ debugLog('Rendering message...', { role, content, sender, metadata });
10
+
11
+ const messageContainer = document.getElementById('messageHistory');
12
+ if (!messageContainer) {
13
+ debugLog('Message container not found.');
14
+ return;
15
+ }
16
+
17
+ let messageContent = content.content || content.text || '';
18
+
19
+ // 🛑 Ignore empty messages immediately
20
+ if (!messageContent.trim()) {
21
+ debugLog('Skipping empty message.');
22
+ return;
23
+ }
24
+
25
+ // 🔄 Detect assistant handoff JSON
26
+ let isHandoff = false;
27
+ try {
28
+ const parsedContent = JSON.parse(messageContent);
29
+ if (parsedContent.assistant && typeof parsedContent.assistant === 'string') {
30
+ messageContent = `<em>🔄 Handoff to <strong>${parsedContent.assistant}</strong></em>`;
31
+ role = 'system';
32
+ isHandoff = true;
33
+ }
34
+ } catch (e) {
35
+ // Not a JSON object, proceed
36
+ }
37
+
38
+ if (!isHandoff) {
39
+ messageContent = `<strong>${sender}:</strong> ${marked.parse(messageContent)}`;
40
+ }
41
+
42
+ // ❌ Prevent rendering assistant messages with "No content"
43
+ if (role === "assistant" && messageContent.includes("<p>No content</p>")) {
44
+ debugLog("Skipping assistant message with 'No content'.");
45
+ return; // 🛑 Stop execution here
46
+ }
47
+
48
+ // ✅ Create the message
49
+ const messageDiv = document.createElement('div');
50
+ messageDiv.className = `message ${role}`;
51
+
52
+ messageDiv.innerHTML = `
53
+ <div class="message-text">${messageContent}</div>
54
+ <div class="message-toolbar">
55
+ <button class="toolbar-btn" aria-label="Copy Message">
56
+ <img src="/static/rest_mode/svg/copy.svg" alt="Copy Icon" class="icon-svg" />
57
+ </button>
58
+ <button class="toolbar-btn" aria-label="Delete Message">
59
+ <img src="/static/rest_mode/svg/trash.svg" alt="Trash Icon" class="icon-svg" />
60
+ </button>
61
+ </div>
62
+ `;
63
+
64
+ messageContainer.appendChild(messageDiv);
65
+ debugLog('Message rendered successfully.');
66
+ }
67
+
68
+ /**
69
+ * Appends a raw message object into the chat UI.
70
+ */
71
+ let isAppendingMessage = false; // Prevent duplicate appending
72
+
73
+ export function appendRawMessage(role, content, sender, metadata) {
74
+ if (isAppendingMessage) {
75
+ debugLog('Duplicate appendRawMessage call detected. Skipping execution.', { role, content, sender, metadata });
76
+ return;
77
+ }
78
+
79
+ isAppendingMessage = true; // Set the flag
80
+ debugLog('Appending raw message...', { role, content, sender, metadata });
81
+
82
+ renderMessage(role, content, sender, metadata);
83
+
84
+ const messageContainer = document.getElementById('messageHistory');
85
+ if (messageContainer) {
86
+ messageContainer.scrollTop = messageContainer.scrollHeight;
87
+ debugLog('Scrolled to the bottom of the message history.');
88
+ }
89
+
90
+ isAppendingMessage = false; // Reset the flag
91
+ }
92
+
93
+
94
+
95
+ /**
96
+ * Renders quick prompts in the UI.
97
+ */
98
+ export function renderQuickPrompts() {
99
+ const quickPromptsContainer = document.getElementById('quickPrompts');
100
+ if (!quickPromptsContainer) {
101
+ debugLog('Quick prompts container not found.');
102
+ return;
103
+ }
104
+
105
+ quickPromptsContainer.innerHTML = quickPrompts
106
+ .map(
107
+ (prompt, index) => `
108
+ <button class="quick-prompt-button" data-index="${index}">
109
+ ${prompt}
110
+ </button>`
111
+ )
112
+ .join('');
113
+
114
+ document.querySelectorAll('.quick-prompt-button').forEach((button) =>
115
+ button.addEventListener('click', (e) => handleQuickPromptSelection(e))
116
+ );
117
+ debugLog('Quick prompts rendered successfully.');
118
+ }
119
+
120
+ /**
121
+ * Handles quick prompt selection.
122
+ */
123
+ function handleQuickPromptSelection(event) {
124
+ const promptIndex = event.target.getAttribute('data-index');
125
+ const promptText = quickPrompts[promptIndex];
126
+
127
+ appendRawMessage('user', { content: promptText }, 'User', {});
128
+ clearQuickPrompts();
129
+ }
130
+
131
+ /**
132
+ * Clears all quick prompts from the UI.
133
+ */
134
+ function clearQuickPrompts() {
135
+ const quickPromptsContainer = document.getElementById('quickPrompts');
136
+ if (quickPromptsContainer) {
137
+ quickPromptsContainer.innerHTML = '';
138
+ debugLog('Quick prompts cleared.');
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Allows adding a new quick prompt dynamically.
144
+ */
145
+ export function addQuickPrompt(prompt) {
146
+ quickPrompts.push(prompt);
147
+ renderQuickPrompts();
148
+ debugLog('Quick prompt added.', { prompt });
149
+ }
150
+
151
+ /**
152
+ * Removes a quick prompt by index.
153
+ */
154
+ export function removeQuickPrompt(index) {
155
+ if (index < 0 || index >= quickPrompts.length) {
156
+ debugLog('Invalid quick prompt index.', { index });
157
+ return;
158
+ }
159
+ quickPrompts.splice(index, 1);
160
+ renderQuickPrompts();
161
+ debugLog('Quick prompt removed.', { index });
162
+ }
163
+
164
+ /**
165
+ * Clears all messages from the chat history UI.
166
+ */
167
+ export function clearMessages() {
168
+ debugLog('Clearing all messages from the chat history.');
169
+
170
+ const messageContainer = document.getElementById('messageHistory');
171
+ if (messageContainer) {
172
+ messageContainer.innerHTML = '';
173
+ debugLog('Chat history cleared successfully.');
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Attaches toolbar actions to a message element.
179
+ */
180
+ function attachToolbarActions(messageDiv) {
181
+ const persistentMessage = document.getElementById("persistentMessage");
182
+
183
+ messageDiv.addEventListener("click", (event) => {
184
+ const target = event.target.closest('button');
185
+ if (!target) return;
186
+
187
+ const action = target.getAttribute('aria-label');
188
+
189
+ switch (action) {
190
+ case 'Thumbs Up':
191
+ debugLog('Thumbs up clicked.');
192
+ break;
193
+ case 'Thumbs Down':
194
+ debugLog('Thumbs down clicked.');
195
+ break;
196
+ case 'Append to Persistent Message':
197
+ appendToPersistentMessage(messageDiv, persistentMessage);
198
+ break;
199
+ case 'Edit Message':
200
+ editMessage(messageDiv);
201
+ break;
202
+ case 'Copy Message':
203
+ copyMessageToClipboard(messageDiv);
204
+ break;
205
+ case 'Delete Message':
206
+ deleteMessage(messageDiv);
207
+ break;
208
+ }
209
+ });
210
+ }
211
+
212
+ /**
213
+ * Appends the content of a message to the persistent message area.
214
+ */
215
+ function appendToPersistentMessage(messageDiv, persistentMessageElement) {
216
+ if (!persistentMessageElement) {
217
+ console.error("Persistent message element not found (firstUserMessage).");
218
+ return;
219
+ }
220
+
221
+ const content = messageDiv.querySelector('span')?.innerText || "No content";
222
+ const persistentMessageContent = persistentMessageElement.querySelector('.message span');
223
+
224
+ if (persistentMessageContent) {
225
+ persistentMessageContent.innerText = content;
226
+ debugLog('Message appended to persistent message area.', { content });
227
+ } else {
228
+ console.error("Persistent message content element not found.");
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Allows the user to edit a message.
234
+ */
235
+ function editMessage(messageDiv) {
236
+ const span = messageDiv.querySelector('span');
237
+ const content = span.innerText;
238
+ const newContent = prompt('Edit your message:', content);
239
+ if (newContent !== null) {
240
+ span.innerText = newContent;
241
+ debugLog('Message edited successfully.', { newContent });
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Copies a message's content to the clipboard.
247
+ */
248
+ function copyMessageToClipboard(messageDiv) {
249
+ const content = messageDiv.querySelector('span').innerText;
250
+ navigator.clipboard.writeText(content).then(() => {
251
+ alert('Message copied to clipboard!');
252
+ debugLog('Message copied to clipboard.', { content });
253
+ });
254
+ }
255
+
256
+ /**
257
+ * Deletes a message from the chat history.
258
+ */
259
+ function deleteMessage(messageDiv) {
260
+ if (confirm('Are you sure you want to delete this message?')) {
261
+ messageDiv.remove();
262
+ debugLog('Message deleted successfully.');
263
+ }
264
+ }