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.
- open_swarm-0.1.1743362777.dist-info/METADATA +217 -0
- open_swarm-0.1.1743362777.dist-info/RECORD +260 -0
- {open_swarm-0.1.1743070217.dist-info → open_swarm-0.1.1743362777.dist-info}/WHEEL +1 -2
- open_swarm-0.1.1743362777.dist-info/entry_points.txt +2 -0
- swarm/__init__.py +0 -2
- swarm/auth.py +53 -49
- swarm/blueprints/README.md +67 -0
- swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py +412 -0
- swarm/blueprints/chatbot/blueprint_chatbot.py +98 -0
- swarm/blueprints/chatbot/templates/chatbot/chatbot.html +33 -0
- swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +183 -0
- swarm/blueprints/dilbot_universe/blueprint_dilbot_universe.py +285 -0
- swarm/blueprints/divine_code/__init__.py +0 -0
- swarm/blueprints/divine_code/apps.py +11 -0
- swarm/blueprints/divine_code/blueprint_divine_code.py +219 -0
- swarm/blueprints/django_chat/apps.py +6 -0
- swarm/blueprints/django_chat/blueprint_django_chat.py +84 -0
- swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +37 -0
- swarm/blueprints/django_chat/urls.py +8 -0
- swarm/blueprints/django_chat/views.py +32 -0
- swarm/blueprints/echocraft/blueprint_echocraft.py +44 -0
- swarm/blueprints/family_ties/apps.py +11 -0
- swarm/blueprints/family_ties/blueprint_family_ties.py +152 -0
- swarm/blueprints/family_ties/models.py +19 -0
- swarm/blueprints/family_ties/serializers.py +7 -0
- swarm/blueprints/family_ties/settings.py +16 -0
- swarm/blueprints/family_ties/urls.py +10 -0
- swarm/blueprints/family_ties/views.py +26 -0
- swarm/blueprints/flock/__init__.py +0 -0
- swarm/blueprints/gaggle/blueprint_gaggle.py +184 -0
- swarm/blueprints/gotchaman/blueprint_gotchaman.py +232 -0
- swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +133 -0
- swarm/blueprints/messenger/templates/messenger/messenger.html +46 -0
- swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +234 -0
- swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +248 -0
- swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +156 -0
- swarm/blueprints/omniplex/blueprint_omniplex.py +221 -0
- swarm/blueprints/rue_code/__init__.py +0 -0
- swarm/blueprints/rue_code/blueprint_rue_code.py +291 -0
- swarm/blueprints/suggestion/blueprint_suggestion.py +110 -0
- swarm/blueprints/unapologetic_press/blueprint_unapologetic_press.py +298 -0
- swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
- swarm/blueprints/whiskeytango_foxtrot/apps.py +11 -0
- swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +256 -0
- swarm/extensions/blueprint/__init__.py +30 -15
- swarm/extensions/blueprint/agent_utils.py +16 -40
- swarm/extensions/blueprint/blueprint_base.py +141 -543
- swarm/extensions/blueprint/blueprint_discovery.py +112 -98
- swarm/extensions/blueprint/cli_handler.py +185 -0
- swarm/extensions/blueprint/config_loader.py +122 -0
- swarm/extensions/blueprint/django_utils.py +181 -79
- swarm/extensions/blueprint/interactive_mode.py +1 -1
- swarm/extensions/config/config_loader.py +83 -200
- swarm/extensions/launchers/build_swarm_wrapper.py +0 -0
- swarm/extensions/launchers/swarm_cli.py +199 -287
- swarm/llm/chat_completion.py +26 -55
- swarm/management/__init__.py +0 -0
- swarm/management/commands/__init__.py +0 -0
- swarm/management/commands/runserver.py +58 -0
- swarm/permissions.py +38 -0
- swarm/serializers.py +96 -5
- swarm/settings.py +95 -110
- swarm/static/contrib/fonts/fontawesome-webfont.ttf +7 -0
- swarm/static/contrib/fonts/fontawesome-webfont.woff +7 -0
- swarm/static/contrib/fonts/fontawesome-webfont.woff2 +7 -0
- swarm/static/contrib/markedjs/marked.min.js +6 -0
- swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +27 -0
- swarm/static/contrib/tabler-icons/alert-triangle.svg +21 -0
- swarm/static/contrib/tabler-icons/archive.svg +21 -0
- swarm/static/contrib/tabler-icons/artboard.svg +27 -0
- swarm/static/contrib/tabler-icons/automatic-gearbox.svg +23 -0
- swarm/static/contrib/tabler-icons/box-multiple.svg +19 -0
- swarm/static/contrib/tabler-icons/carambola.svg +19 -0
- swarm/static/contrib/tabler-icons/copy.svg +20 -0
- swarm/static/contrib/tabler-icons/download.svg +21 -0
- swarm/static/contrib/tabler-icons/edit.svg +21 -0
- swarm/static/contrib/tabler-icons/filled/carambola.svg +13 -0
- swarm/static/contrib/tabler-icons/filled/paint.svg +13 -0
- swarm/static/contrib/tabler-icons/headset.svg +22 -0
- swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +21 -0
- swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +21 -0
- swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +21 -0
- swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +21 -0
- swarm/static/contrib/tabler-icons/message-chatbot.svg +22 -0
- swarm/static/contrib/tabler-icons/message-star.svg +22 -0
- swarm/static/contrib/tabler-icons/message-x.svg +23 -0
- swarm/static/contrib/tabler-icons/message.svg +21 -0
- swarm/static/contrib/tabler-icons/paperclip.svg +18 -0
- swarm/static/contrib/tabler-icons/playlist-add.svg +22 -0
- swarm/static/contrib/tabler-icons/robot.svg +26 -0
- swarm/static/contrib/tabler-icons/search.svg +19 -0
- swarm/static/contrib/tabler-icons/settings.svg +20 -0
- swarm/static/contrib/tabler-icons/thumb-down.svg +19 -0
- swarm/static/contrib/tabler-icons/thumb-up.svg +19 -0
- swarm/static/css/dropdown.css +22 -0
- swarm/static/htmx/htmx.min.js +0 -0
- swarm/static/js/dropdown.js +23 -0
- swarm/static/rest_mode/css/base.css +470 -0
- swarm/static/rest_mode/css/chat-history.css +286 -0
- swarm/static/rest_mode/css/chat.css +251 -0
- swarm/static/rest_mode/css/chatbot.css +74 -0
- swarm/static/rest_mode/css/chatgpt.css +62 -0
- swarm/static/rest_mode/css/colors/corporate.css +74 -0
- swarm/static/rest_mode/css/colors/pastel.css +81 -0
- swarm/static/rest_mode/css/colors/tropical.css +82 -0
- swarm/static/rest_mode/css/general.css +142 -0
- swarm/static/rest_mode/css/layout.css +167 -0
- swarm/static/rest_mode/css/layouts/messenger-layout.css +17 -0
- swarm/static/rest_mode/css/layouts/minimalist-layout.css +57 -0
- swarm/static/rest_mode/css/layouts/mobile-layout.css +8 -0
- swarm/static/rest_mode/css/messages.css +84 -0
- swarm/static/rest_mode/css/messenger.css +135 -0
- swarm/static/rest_mode/css/settings.css +91 -0
- swarm/static/rest_mode/css/simple.css +44 -0
- swarm/static/rest_mode/css/slack.css +58 -0
- swarm/static/rest_mode/css/style.css +156 -0
- swarm/static/rest_mode/css/theme.css +30 -0
- swarm/static/rest_mode/css/toast.css +40 -0
- swarm/static/rest_mode/js/auth.js +9 -0
- swarm/static/rest_mode/js/blueprint.js +41 -0
- swarm/static/rest_mode/js/blueprintUtils.js +12 -0
- swarm/static/rest_mode/js/chatLogic.js +79 -0
- swarm/static/rest_mode/js/debug.js +63 -0
- swarm/static/rest_mode/js/events.js +98 -0
- swarm/static/rest_mode/js/main.js +19 -0
- swarm/static/rest_mode/js/messages.js +264 -0
- swarm/static/rest_mode/js/messengerLogic.js +355 -0
- swarm/static/rest_mode/js/modules/apiService.js +84 -0
- swarm/static/rest_mode/js/modules/blueprintManager.js +162 -0
- swarm/static/rest_mode/js/modules/chatHistory.js +110 -0
- swarm/static/rest_mode/js/modules/debugLogger.js +14 -0
- swarm/static/rest_mode/js/modules/eventHandlers.js +107 -0
- swarm/static/rest_mode/js/modules/messageProcessor.js +120 -0
- swarm/static/rest_mode/js/modules/state.js +7 -0
- swarm/static/rest_mode/js/modules/userInteractions.js +29 -0
- swarm/static/rest_mode/js/modules/validation.js +23 -0
- swarm/static/rest_mode/js/rendering.js +119 -0
- swarm/static/rest_mode/js/settings.js +130 -0
- swarm/static/rest_mode/js/sidebar.js +94 -0
- swarm/static/rest_mode/js/simpleLogic.js +37 -0
- swarm/static/rest_mode/js/slackLogic.js +66 -0
- swarm/static/rest_mode/js/splash.js +76 -0
- swarm/static/rest_mode/js/theme.js +111 -0
- swarm/static/rest_mode/js/toast.js +36 -0
- swarm/static/rest_mode/js/ui.js +265 -0
- swarm/static/rest_mode/js/validation.js +57 -0
- swarm/static/rest_mode/svg/animated_spinner.svg +12 -0
- swarm/static/rest_mode/svg/arrow_down.svg +5 -0
- swarm/static/rest_mode/svg/arrow_left.svg +5 -0
- swarm/static/rest_mode/svg/arrow_right.svg +5 -0
- swarm/static/rest_mode/svg/arrow_up.svg +5 -0
- swarm/static/rest_mode/svg/attach.svg +8 -0
- swarm/static/rest_mode/svg/avatar.svg +7 -0
- swarm/static/rest_mode/svg/canvas.svg +6 -0
- swarm/static/rest_mode/svg/chat_history.svg +4 -0
- swarm/static/rest_mode/svg/close.svg +5 -0
- swarm/static/rest_mode/svg/copy.svg +4 -0
- swarm/static/rest_mode/svg/dark_mode.svg +3 -0
- swarm/static/rest_mode/svg/edit.svg +5 -0
- swarm/static/rest_mode/svg/layout.svg +9 -0
- swarm/static/rest_mode/svg/logo.svg +29 -0
- swarm/static/rest_mode/svg/logout.svg +5 -0
- swarm/static/rest_mode/svg/mobile.svg +5 -0
- swarm/static/rest_mode/svg/new_chat.svg +4 -0
- swarm/static/rest_mode/svg/not_visible.svg +5 -0
- swarm/static/rest_mode/svg/plus.svg +7 -0
- swarm/static/rest_mode/svg/run_code.svg +6 -0
- swarm/static/rest_mode/svg/save.svg +4 -0
- swarm/static/rest_mode/svg/search.svg +6 -0
- swarm/static/rest_mode/svg/settings.svg +4 -0
- swarm/static/rest_mode/svg/speaker.svg +5 -0
- swarm/static/rest_mode/svg/stop.svg +6 -0
- swarm/static/rest_mode/svg/thumbs_down.svg +3 -0
- swarm/static/rest_mode/svg/thumbs_up.svg +3 -0
- swarm/static/rest_mode/svg/toggle_off.svg +6 -0
- swarm/static/rest_mode/svg/toggle_on.svg +6 -0
- swarm/static/rest_mode/svg/trash.svg +10 -0
- swarm/static/rest_mode/svg/undo.svg +3 -0
- swarm/static/rest_mode/svg/visible.svg +8 -0
- swarm/static/rest_mode/svg/voice.svg +10 -0
- swarm/templates/account/login.html +22 -0
- swarm/templates/account/signup.html +32 -0
- swarm/templates/base.html +30 -0
- swarm/templates/chat.html +43 -0
- swarm/templates/index.html +35 -0
- swarm/templates/rest_mode/components/chat_sidebar.html +55 -0
- swarm/templates/rest_mode/components/header.html +45 -0
- swarm/templates/rest_mode/components/main_chat_pane.html +41 -0
- swarm/templates/rest_mode/components/settings_dialog.html +97 -0
- swarm/templates/rest_mode/components/splash_screen.html +7 -0
- swarm/templates/rest_mode/components/top_bar.html +28 -0
- swarm/templates/rest_mode/message_ui.html +50 -0
- swarm/templates/rest_mode/slackbot.html +30 -0
- swarm/templates/simple_blueprint_page.html +24 -0
- swarm/templates/websocket_partials/final_system_message.html +3 -0
- swarm/templates/websocket_partials/system_message.html +4 -0
- swarm/templates/websocket_partials/user_message.html +5 -0
- swarm/urls.py +57 -74
- swarm/utils/log_utils.py +63 -0
- swarm/views/api_views.py +48 -39
- swarm/views/chat_views.py +156 -70
- swarm/views/core_views.py +85 -90
- swarm/views/model_views.py +64 -121
- swarm/views/utils.py +65 -441
- open_swarm-0.1.1743070217.dist-info/METADATA +0 -258
- open_swarm-0.1.1743070217.dist-info/RECORD +0 -89
- open_swarm-0.1.1743070217.dist-info/entry_points.txt +0 -3
- open_swarm-0.1.1743070217.dist-info/top_level.txt +0 -1
- swarm/agent/agent.py +0 -49
- swarm/core.py +0 -326
- swarm/extensions/mcp/__init__.py +0 -1
- swarm/extensions/mcp/cache_utils.py +0 -36
- swarm/extensions/mcp/mcp_client.py +0 -341
- swarm/extensions/mcp/mcp_constants.py +0 -7
- swarm/extensions/mcp/mcp_tool_provider.py +0 -110
- swarm/types.py +0 -126
- {open_swarm-0.1.1743070217.dist-info → open_swarm-0.1.1743362777.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
// src/swarm/static/rest_mode/js/modules/chatHistory.js
|
2
|
+
|
3
|
+
import { showToast } from '../toast.js';
|
4
|
+
import { appendRawMessage } from '../messages.js';
|
5
|
+
import { deleteChat } from './apiService.js';
|
6
|
+
import { debugLog } from './debugLogger.js';
|
7
|
+
import { chatHistory, contextVariables } from './state.js';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Truncates long messages and adds a "more..." link if needed.
|
11
|
+
* @param {string} content - The message content to truncate.
|
12
|
+
* @param {number} maxLength - The maximum length before truncation.
|
13
|
+
* @returns {string} - The truncated message with a "more..." link if applicable.
|
14
|
+
*/
|
15
|
+
function truncateMessage(content, maxLength = 50) {
|
16
|
+
if (content.length > maxLength) {
|
17
|
+
const truncated = content.slice(0, maxLength);
|
18
|
+
return `<span data-full-content="${content}">${truncated}... <a href="#" class="read-more">more</a></span>`;
|
19
|
+
}
|
20
|
+
return content;
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Creates a new chat history entry in the sidebar.
|
25
|
+
* @param {string} firstMessage - The user's first message in the chat.
|
26
|
+
*/
|
27
|
+
export function createChatHistoryEntry(chatName, firstMessage) {
|
28
|
+
const chatHistoryPane = document.getElementById('chatHistoryPane');
|
29
|
+
if (!chatHistoryPane) {
|
30
|
+
debugLog('Chat history pane element not found.');
|
31
|
+
return;
|
32
|
+
}
|
33
|
+
|
34
|
+
// Create new chat history item
|
35
|
+
const chatItem = document.createElement('li');
|
36
|
+
chatItem.className = 'chat-history-item';
|
37
|
+
|
38
|
+
// Generate truncated message with "more..." link if necessary
|
39
|
+
const truncatedMessage = truncateMessage(firstMessage);
|
40
|
+
|
41
|
+
// Populate the chat history item
|
42
|
+
chatItem.innerHTML = `
|
43
|
+
<details>
|
44
|
+
<summary>${chatName}</summary>
|
45
|
+
<p>${truncatedMessage}</p>
|
46
|
+
<span class="chat-item-time">${new Date().toLocaleString()}</span>
|
47
|
+
<div class="chat-item-tools">
|
48
|
+
<!-- Tag Buttons and Delete Button -->
|
49
|
+
<div class="chat-item-tags">
|
50
|
+
<button class="tag-button" aria-label="Filter by General">General</button>
|
51
|
+
<button class="tag-button" aria-label="Filter by Introduction">Introduction</button>
|
52
|
+
<button class="tag-button" aria-label="Filter by Welcome">Welcome</button>
|
53
|
+
<button class="tag-button add-tag-btn" aria-label="Add Tag">+</button>
|
54
|
+
<!-- Delete Button -->
|
55
|
+
<button class="toolbar-btn delete-chat-btn" title="Delete Chat" aria-label="Delete Chat">
|
56
|
+
<img src="${window.STATIC_URLS.trashIcon}" alt="Delete Chat">
|
57
|
+
</button>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
</details>
|
61
|
+
`;
|
62
|
+
|
63
|
+
// Add the new chat item to the top of the list
|
64
|
+
const chatList = chatHistoryPane.querySelector('.chat-history-list');
|
65
|
+
if (chatList) {
|
66
|
+
chatList.prepend(chatItem); // Insert at the top
|
67
|
+
debugLog('New chat history entry created and added to the list.', chatItem);
|
68
|
+
}
|
69
|
+
|
70
|
+
// Event listener for "more..." links
|
71
|
+
chatItem.querySelectorAll('.read-more').forEach(link => {
|
72
|
+
link.addEventListener('click', (event) => {
|
73
|
+
event.preventDefault();
|
74
|
+
const parent = link.parentElement;
|
75
|
+
if (parent) {
|
76
|
+
parent.innerHTML = parent.getAttribute('data-full-content'); // Reveal full content
|
77
|
+
}
|
78
|
+
});
|
79
|
+
});
|
80
|
+
|
81
|
+
// Event listener for delete button
|
82
|
+
const deleteBtn = chatItem.querySelector('.delete-chat-btn');
|
83
|
+
if (deleteBtn) {
|
84
|
+
deleteBtn.addEventListener('click', () => deleteChat(chatItem));
|
85
|
+
}
|
86
|
+
|
87
|
+
// Event listener for selecting the chat item
|
88
|
+
chatItem.addEventListener('click', (event) => {
|
89
|
+
// Prevent triggering when clicking on "more..." link or delete button
|
90
|
+
if (event.target.classList.contains('read-more') || event.target.closest('.delete-chat-btn')) {
|
91
|
+
return;
|
92
|
+
}
|
93
|
+
handleChatHistoryClick(chatItem);
|
94
|
+
});
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Handles chat history item click.
|
99
|
+
* @param {HTMLElement} item - The clicked chat history item.
|
100
|
+
*/
|
101
|
+
export function handleChatHistoryClick(item) {
|
102
|
+
const chatName = item.querySelector('summary').textContent.trim();
|
103
|
+
showToast(`Selected: "${chatName}"`, 'info');
|
104
|
+
|
105
|
+
const chatHistoryItems = document.querySelectorAll('.chat-history-pane li');
|
106
|
+
chatHistoryItems.forEach((i) => i.classList.remove('active'));
|
107
|
+
item.classList.add('active');
|
108
|
+
|
109
|
+
// Additional logic to load the selected chat can be added here
|
110
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
// src/swarm/static/rest_mode/js/modules/debugLogger.js
|
2
|
+
|
3
|
+
const DEBUG_MODE = true;
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Logs debug messages if debug mode is enabled.
|
7
|
+
* @param {string} message - The message to log.
|
8
|
+
* @param {any} data - Additional data to include in the log.
|
9
|
+
*/
|
10
|
+
export function debugLog(message, data = null) {
|
11
|
+
if (DEBUG_MODE) {
|
12
|
+
console.log(`[DEBUG] ${message}`, data);
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
// src/swarm/static/rest_mode/js/modules/eventHandlers.js
|
2
|
+
|
3
|
+
import { handleLogout } from '../auth.js';
|
4
|
+
import { toggleDebugPane, handleTechSupport } from '../debug.js';
|
5
|
+
import { toggleSidebar } from '../sidebar.js';
|
6
|
+
|
7
|
+
import { handleChatHistoryClick } from './chatHistory.js';
|
8
|
+
import { deleteChat } from './apiService.js';
|
9
|
+
import { handleUpload, handleVoiceRecord } from './userInteractions.js';
|
10
|
+
import { fetchBlueprintMetadata } from './apiService.js';
|
11
|
+
import { handleSubmit } from './messageProcessor.js';
|
12
|
+
import { showToast } from '../toast.js';
|
13
|
+
import { debugLog } from './debugLogger.js';
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Handles "Search" button click.
|
17
|
+
*/
|
18
|
+
function handleSearch() {
|
19
|
+
showToast("🔍 Search feature is under development.", "info");
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Handles "New Chat" button click.
|
24
|
+
*/
|
25
|
+
function handleNewChat() {
|
26
|
+
showToast("📝 Starting a new chat...", "info");
|
27
|
+
// Implement new chat functionality as needed
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Attaches event listeners to chat history items.
|
32
|
+
*/
|
33
|
+
function setupChatHistoryListeners() {
|
34
|
+
const chatHistoryItems = document.querySelectorAll('.chat-history-pane li');
|
35
|
+
chatHistoryItems.forEach((item) => {
|
36
|
+
item.removeEventListener('click', () => handleChatHistoryClick(item));
|
37
|
+
item.addEventListener('click', () => handleChatHistoryClick(item));
|
38
|
+
|
39
|
+
const trashCan = item.querySelector('.trash-can');
|
40
|
+
if (trashCan) {
|
41
|
+
trashCan.addEventListener('click', (e) => {
|
42
|
+
e.stopPropagation();
|
43
|
+
deleteChat(item);
|
44
|
+
});
|
45
|
+
}
|
46
|
+
});
|
47
|
+
}
|
48
|
+
|
49
|
+
/**
|
50
|
+
* Attaches event listeners to main application buttons and elements.
|
51
|
+
*/
|
52
|
+
function setupGlobalEventListeners() {
|
53
|
+
// Sidebar toggles
|
54
|
+
document.getElementById("settingsToggleButton")?.removeEventListener('click', () => toggleSidebar('options', true));
|
55
|
+
document.getElementById("settingsToggleButton")?.addEventListener('click', () => toggleSidebar('options', true));
|
56
|
+
document.getElementById("optionsSidebarHideBtn")?.addEventListener('click', () => toggleSidebar('options', false));
|
57
|
+
// Removed event listeners for chatHistoryToggleButton and leftSidebarHideBtn
|
58
|
+
|
59
|
+
// Top buttons
|
60
|
+
// document.getElementById("searchButton")?.addEventListener('click', handleSearch);
|
61
|
+
document.getElementById("newChatButton")?.addEventListener('click', handleNewChat);
|
62
|
+
|
63
|
+
// Functional buttons
|
64
|
+
document.getElementById("logoutButton")?.addEventListener('click', handleLogout);
|
65
|
+
document.getElementById("uploadButton")?.addEventListener('click', handleUpload);
|
66
|
+
document.getElementById("voiceRecordButton")?.addEventListener('click', handleVoiceRecord);
|
67
|
+
document.getElementById("submitButton")?.addEventListener("click", handleSubmit); // Attached here
|
68
|
+
|
69
|
+
// User input submission with Enter key
|
70
|
+
const userInput = document.getElementById("userInput");
|
71
|
+
userInput?.addEventListener("keypress", (e) => {
|
72
|
+
if (e.key === "Enter") {
|
73
|
+
handleSubmit();
|
74
|
+
}
|
75
|
+
});
|
76
|
+
|
77
|
+
// Debug pane toggles
|
78
|
+
document.getElementById("debugButton")?.addEventListener('click', toggleDebugPane);
|
79
|
+
document.getElementById("techSupportButtonInsideDebug")?.addEventListener('click', handleTechSupport);
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Sets up all event listeners for the application.
|
84
|
+
*/
|
85
|
+
let eventListenersInitialized = false;
|
86
|
+
|
87
|
+
export function setupEventListeners() {
|
88
|
+
if (eventListenersInitialized) {
|
89
|
+
debugLog('Event listeners are already initialized.');
|
90
|
+
return;
|
91
|
+
}
|
92
|
+
|
93
|
+
setupGlobalEventListeners();
|
94
|
+
setupChatHistoryListeners();
|
95
|
+
debugLog('All event listeners have been set up.');
|
96
|
+
eventListenersInitialized = true;
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Initialize the application.
|
101
|
+
*/
|
102
|
+
export function initializeApplication() {
|
103
|
+
debugLog('[DEBUG] Initializing application...');
|
104
|
+
fetchBlueprintMetadata(); // Fetch blueprint metadata and display it
|
105
|
+
setupEventListeners(); // Set up event listeners
|
106
|
+
debugLog('[DEBUG] Application initialized.');
|
107
|
+
}
|
@@ -0,0 +1,120 @@
|
|
1
|
+
// src/swarm/static/rest_mode/js/modules/messageProcessor.js
|
2
|
+
|
3
|
+
import { showToast } from '../toast.js';
|
4
|
+
import { appendRawMessage } from '../messages.js';
|
5
|
+
import { showLoadingIndicator, hideLoadingIndicator } from '../ui.js';
|
6
|
+
|
7
|
+
import { submitMessage } from './apiService.js';
|
8
|
+
import { debugLog } from './debugLogger.js';
|
9
|
+
import { validateMessage } from './validation.js';
|
10
|
+
import { chatHistory, contextVariables } from './state.js'; // Assuming state.js manages shared state
|
11
|
+
import { createChatHistoryEntry } from './chatHistory.js';
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Processes the assistant's response and updates context variables.
|
15
|
+
* @param {Object} data - The response data from the server.
|
16
|
+
* @param {Object} contextVariables - The current context variables.
|
17
|
+
*/
|
18
|
+
export function processAssistantResponse(data, contextVariables) {
|
19
|
+
if (!data.choices || !Array.isArray(data.choices)) {
|
20
|
+
debugLog('Invalid response structure:', data);
|
21
|
+
showToast('⚠️ Invalid response from server.', 'error');
|
22
|
+
return;
|
23
|
+
}
|
24
|
+
|
25
|
+
data.choices.forEach((choice) => {
|
26
|
+
const rawMessage = { ...choice.message };
|
27
|
+
|
28
|
+
const role = rawMessage.role || 'assistant';
|
29
|
+
const content = rawMessage.content || 'No content';
|
30
|
+
const sender = rawMessage.sender || (role === 'user' ? 'User' : 'Assistant');
|
31
|
+
|
32
|
+
appendRawMessage(role, { content }, sender, rawMessage.metadata);
|
33
|
+
});
|
34
|
+
|
35
|
+
debugLog('Assistant response processed successfully.', data);
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Handles user message submission.
|
40
|
+
* @returns {Promise<void>}
|
41
|
+
*/
|
42
|
+
export async function handleSubmit() {
|
43
|
+
const userInput = document.getElementById("userInput");
|
44
|
+
if (!userInput) {
|
45
|
+
debugLog("User input element not found.");
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
|
49
|
+
const userMessageContent = userInput.value.trim();
|
50
|
+
if (!userMessageContent) {
|
51
|
+
showToast("❌ You cannot send an empty message.", "error");
|
52
|
+
debugLog("Empty message submission blocked.");
|
53
|
+
return;
|
54
|
+
}
|
55
|
+
|
56
|
+
// Clear input field
|
57
|
+
userInput.value = "";
|
58
|
+
|
59
|
+
const userMessage = {
|
60
|
+
role: "user",
|
61
|
+
content: userMessageContent,
|
62
|
+
sender: "User",
|
63
|
+
metadata: {},
|
64
|
+
};
|
65
|
+
chatHistory.push(userMessage);
|
66
|
+
debugLog("User message added to chat history.", userMessage);
|
67
|
+
|
68
|
+
const isFirstUserMessage = chatHistory.filter((msg) => msg.role === "user").length === 1;
|
69
|
+
|
70
|
+
// Validate the message
|
71
|
+
const error = validateMessage(userMessage);
|
72
|
+
if (error) return;
|
73
|
+
|
74
|
+
// Render the user message in the UI
|
75
|
+
appendRawMessage(userMessage.role, { content: userMessage.content }, userMessage.sender, userMessage.metadata);
|
76
|
+
|
77
|
+
// If it's the first user message, update the persistent message and create a new chat history entry
|
78
|
+
if (isFirstUserMessage) {
|
79
|
+
const persistentMessageElement = document.getElementById('firstUserMessage');
|
80
|
+
if (persistentMessageElement) {
|
81
|
+
persistentMessageElement.innerHTML = `<b>Persist:</b><p>User: ${userMessageContent}</p>`;
|
82
|
+
debugLog("Persistent message updated with the first user message.");
|
83
|
+
}
|
84
|
+
createChatHistoryEntry("New Chat", userMessageContent);
|
85
|
+
}
|
86
|
+
|
87
|
+
showLoadingIndicator(); // Show loading spinner
|
88
|
+
|
89
|
+
try {
|
90
|
+
const urlPath = window.location.pathname;
|
91
|
+
const modelName = urlPath.split("/").filter(Boolean).pop() || "";
|
92
|
+
debugLog("Submitting message to model.", { modelName, message: userMessageContent });
|
93
|
+
|
94
|
+
const response = await fetch("/v1/chat/completions", {
|
95
|
+
method: "POST",
|
96
|
+
headers: {
|
97
|
+
"Content-Type": "application/json",
|
98
|
+
"X-CSRFToken": document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") || "",
|
99
|
+
},
|
100
|
+
body: JSON.stringify({
|
101
|
+
model: modelName,
|
102
|
+
messages: chatHistory,
|
103
|
+
context_variables: contextVariables,
|
104
|
+
}),
|
105
|
+
});
|
106
|
+
|
107
|
+
if (!response.ok) {
|
108
|
+
throw new Error(`HTTP Error: ${response.status}`);
|
109
|
+
}
|
110
|
+
|
111
|
+
const data = await response.json();
|
112
|
+
debugLog("Message successfully processed by the model.", data);
|
113
|
+
processAssistantResponse(data, contextVariables); // Ensure this matches your function signature
|
114
|
+
} catch (err) {
|
115
|
+
console.error("Error submitting message:", err);
|
116
|
+
showToast("⚠️ Error submitting message. Please try again.", "error");
|
117
|
+
} finally {
|
118
|
+
hideLoadingIndicator(); // Hide loading spinner
|
119
|
+
}
|
120
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
// src/swarm/static/rest_mode/js/modules/userInteractions.js
|
2
|
+
|
3
|
+
import { showToast } from '../toast.js';
|
4
|
+
import { debugLog } from './debugLogger.js';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Handles user logout.
|
8
|
+
*/
|
9
|
+
export function handleLogout() {
|
10
|
+
showToast('🚪 You have been logged out.', 'info');
|
11
|
+
debugLog('User initiated logout.');
|
12
|
+
window.location.href = '/login';
|
13
|
+
}
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Handles file upload.
|
17
|
+
*/
|
18
|
+
export function handleUpload() {
|
19
|
+
showToast('➕ Upload feature is under development.', 'info');
|
20
|
+
debugLog('User attempted to upload a file.');
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Handles voice recording.
|
25
|
+
*/
|
26
|
+
export function handleVoiceRecord() {
|
27
|
+
showToast('🎤 Voice recording is under development.', 'info');
|
28
|
+
debugLog('User attempted to record voice.');
|
29
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
// src/swarm/static/rest_mode/js/modules/validation.js
|
2
|
+
|
3
|
+
import { showToast } from '../toast.js';
|
4
|
+
import { debugLog } from './debugLogger.js';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Validates the user message.
|
8
|
+
* @param {Object} message - The message object to validate.
|
9
|
+
* @returns {string|null} - Error message if invalid, or null if valid.
|
10
|
+
*/
|
11
|
+
export function validateMessage(message) {
|
12
|
+
if (!message.content || message.content.trim() === '') {
|
13
|
+
showToast('❌ Message cannot be empty.', 'error');
|
14
|
+
debugLog('Validation failed: Message is empty.');
|
15
|
+
return 'Message cannot be empty.';
|
16
|
+
}
|
17
|
+
if (message.content.length > 5000) {
|
18
|
+
showToast('❌ Message too long. Please limit to 5000 characters.', 'error');
|
19
|
+
debugLog('Validation failed: Message too long.');
|
20
|
+
return 'Message too long.';
|
21
|
+
}
|
22
|
+
return null; // Valid message
|
23
|
+
}
|
@@ -0,0 +1,119 @@
|
|
1
|
+
/**
|
2
|
+
* rendering.js - Contains functions for rendering messages in the chat area,
|
3
|
+
* and appending raw messages to the debug panel.
|
4
|
+
*/
|
5
|
+
const messageContainerId = "messageHistory";
|
6
|
+
const rawMessagesContainerId = "rawMessagesContent";
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Retrieves the current style theme.
|
10
|
+
* @returns {string} - The current style theme ('pastel', 'tropical', 'corporate').
|
11
|
+
*/
|
12
|
+
function getCurrentStyleTheme() {
|
13
|
+
const container = document.querySelector('.container');
|
14
|
+
return container?.getAttribute('data-theme-color') || 'pastel';
|
15
|
+
}
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Renders a single message in the chat.
|
19
|
+
*/
|
20
|
+
export function renderMessage(role, message, sender = "", metadata = {}, isFirstUser = false) {
|
21
|
+
const messageHistory = document.getElementById(messageContainerId);
|
22
|
+
if (!messageHistory) return;
|
23
|
+
|
24
|
+
const containerDiv = document.createElement("div");
|
25
|
+
containerDiv.classList.add("message", role);
|
26
|
+
if (isFirstUser) containerDiv.classList.add("first-user");
|
27
|
+
|
28
|
+
// For our special "plus" icon on hover (to persist the message), we wrap the messageContent in a container
|
29
|
+
// Then on hover, show a small plus icon in the top-right corner
|
30
|
+
let messageContent = `<strong>${sender}:</strong> ${message.content}`;
|
31
|
+
|
32
|
+
// If role === "assistant" and layout is "minimalist", remove boxes, etc.
|
33
|
+
const containerElement = document.querySelector('.container');
|
34
|
+
if (role === "assistant" && containerElement?.getAttribute('data-theme-layout') === 'minimalist-layout') {
|
35
|
+
messageContent = message.content;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Determine trash can icon based on current style
|
39
|
+
const currentStyle = getCurrentStyleTheme();
|
40
|
+
let trashCanIcon = '';
|
41
|
+
if (currentStyle === 'corporate') {
|
42
|
+
trashCanIcon = '✖️'; // X icon
|
43
|
+
} else if (currentStyle === 'tropical') {
|
44
|
+
trashCanIcon = '🗑️'; // Emoji trashcan
|
45
|
+
} else { // pastel
|
46
|
+
trashCanIcon = '🗑️'; // Smaller slim trash can could use a different emoji or a custom SVG
|
47
|
+
}
|
48
|
+
|
49
|
+
containerDiv.innerHTML = `
|
50
|
+
<div class="message-text">
|
51
|
+
${messageContent}
|
52
|
+
</div>
|
53
|
+
<span class="persist-icon" title="Persist this message to the pinned area">➕</span>
|
54
|
+
<span class="trash-can" title="Delete Chat">${trashCanIcon}</span>
|
55
|
+
`;
|
56
|
+
|
57
|
+
// Add event listener on the plus icon
|
58
|
+
const plusIcon = containerDiv.querySelector('.persist-icon');
|
59
|
+
plusIcon?.addEventListener('click', (event) => {
|
60
|
+
event.stopPropagation();
|
61
|
+
persistMessage(role, message, sender);
|
62
|
+
});
|
63
|
+
|
64
|
+
// Add event listener on the trash can
|
65
|
+
const trashCan = containerDiv.querySelector('.trash-can');
|
66
|
+
trashCan?.addEventListener('click', (event) => {
|
67
|
+
event.stopPropagation();
|
68
|
+
// Implement deletion logic if necessary
|
69
|
+
showToast("��️ Delete feature is under development.", "info");
|
70
|
+
});
|
71
|
+
|
72
|
+
messageHistory.appendChild(containerDiv);
|
73
|
+
messageHistory.scrollTop = messageHistory.scrollHeight;
|
74
|
+
}
|
75
|
+
|
76
|
+
/**
|
77
|
+
* Persists a message in the "first user message" container,
|
78
|
+
* along with any other pinned messages.
|
79
|
+
*/
|
80
|
+
function persistMessage(role, message, sender = "") {
|
81
|
+
const firstUserMessageDiv = document.getElementById("firstUserMessage");
|
82
|
+
if (!firstUserMessageDiv) return;
|
83
|
+
|
84
|
+
// We'll allow multiple pinned messages by just appending
|
85
|
+
const pinned = document.createElement("div");
|
86
|
+
pinned.classList.add("pinned-message");
|
87
|
+
pinned.innerHTML = `<small>${sender}:</small> ${message.content}`;
|
88
|
+
|
89
|
+
firstUserMessageDiv.style.display = "block";
|
90
|
+
firstUserMessageDiv.appendChild(pinned);
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* Appends raw message data to the Raw Messages pane.
|
95
|
+
* @param {string} role - The role of the sender.
|
96
|
+
* @param {object} content - The message content.
|
97
|
+
* @param {string} sender - The display name of the sender.
|
98
|
+
* @param {object} metadata - The metadata associated with the message.
|
99
|
+
*/
|
100
|
+
export function appendRawMessage(role, content, sender, metadata) {
|
101
|
+
const rawMessage = document.createElement("div");
|
102
|
+
rawMessage.className = "raw-message";
|
103
|
+
|
104
|
+
const rawData = {
|
105
|
+
role: role,
|
106
|
+
sender: sender || "Unknown",
|
107
|
+
content: content.content || "No content provided.",
|
108
|
+
metadata: metadata // Retain full metadata for backend processing
|
109
|
+
};
|
110
|
+
|
111
|
+
const pre = document.createElement("pre");
|
112
|
+
pre.textContent = JSON.stringify(rawData, null, 2);
|
113
|
+
rawMessage.appendChild(pre);
|
114
|
+
|
115
|
+
rawMessagesContent.appendChild(rawMessage);
|
116
|
+
rawMessagesContent.scrollTop = rawMessagesContent.scrollHeight;
|
117
|
+
|
118
|
+
console.log("Appended Raw Message:", rawData);
|
119
|
+
}
|
@@ -0,0 +1,130 @@
|
|
1
|
+
const DEBUG_MODE = true;
|
2
|
+
|
3
|
+
import { showToast } from './toast.js';
|
4
|
+
|
5
|
+
export let llmConfig = {};
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Logs debug messages if debug mode is enabled.
|
9
|
+
* @param {string} message - The message to log.
|
10
|
+
* @param {any} data - Additional data to include in the log.
|
11
|
+
*/
|
12
|
+
export function debugLog(message, data = null) {
|
13
|
+
if (DEBUG_MODE) {
|
14
|
+
console.log(`[DEBUG] ${message}`, data);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Fetch and load LLM configuration.
|
20
|
+
*/
|
21
|
+
export async function loadLLMConfig() {
|
22
|
+
debugLog("Attempting to load LLM configuration...");
|
23
|
+
try {
|
24
|
+
const response = await fetch('/config/swarm_config.json');
|
25
|
+
debugLog("Received response from LLM config fetch.", { status: response.status });
|
26
|
+
|
27
|
+
if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);
|
28
|
+
const config = await response.json();
|
29
|
+
debugLog("LLM configuration loaded successfully.", config);
|
30
|
+
|
31
|
+
llmConfig = config.llm || {};
|
32
|
+
updateLLMSettingsPane(llmConfig);
|
33
|
+
} catch (error) {
|
34
|
+
console.error("Error loading LLM config:", error);
|
35
|
+
showToast("⚠️ LLM settings could not be loaded. Please check the server.", "warning");
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
/**
|
40
|
+
* Updates the settings pane with collapsible LLM modes and toggles.
|
41
|
+
* @param {Object} config - The LLM configuration object.
|
42
|
+
*/
|
43
|
+
function updateLLMSettingsPane(config) {
|
44
|
+
debugLog("Updating LLM settings pane...", config);
|
45
|
+
|
46
|
+
const llmContainer = document.getElementById('llmConfiguration');
|
47
|
+
if (!llmContainer) {
|
48
|
+
console.warn("[DEBUG] LLM configuration container not found in the DOM.");
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
|
52
|
+
llmContainer.innerHTML = Object.entries(config)
|
53
|
+
.map(([mode, details]) => {
|
54
|
+
const isDefault = mode === 'default';
|
55
|
+
const toggleHTML = `
|
56
|
+
<div class="svg-toggle ${isDefault ? 'disabled' : ''}" data-state="on" id="toggle-${mode}">
|
57
|
+
<img src="/static/rest_mode/svg/toggle_on.svg" alt="Toggle On">
|
58
|
+
</div>
|
59
|
+
`;
|
60
|
+
|
61
|
+
const fields = Object.entries(details)
|
62
|
+
.map(([key, value]) => `
|
63
|
+
<div class="llm-field">
|
64
|
+
<label>${key}:</label>
|
65
|
+
<input type="text" value="${value}" readonly>
|
66
|
+
</div>
|
67
|
+
`)
|
68
|
+
.join('');
|
69
|
+
|
70
|
+
return `
|
71
|
+
<div class="llm-mode collapsible">
|
72
|
+
<h4 class="collapsible-toggle">
|
73
|
+
${toggleHTML} ${mode.charAt(0).toUpperCase() + mode.slice(1)} Mode
|
74
|
+
<span>▼</span>
|
75
|
+
</h4>
|
76
|
+
<div class="collapsible-content hidden">
|
77
|
+
${fields}
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
`;
|
81
|
+
})
|
82
|
+
.join('');
|
83
|
+
|
84
|
+
initializeLLMModeToggles();
|
85
|
+
initializeCollapsibleSections();
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Initialize toggles for LLM modes.
|
90
|
+
*/
|
91
|
+
function initializeLLMModeToggles() {
|
92
|
+
Object.keys(llmConfig).forEach((mode) => {
|
93
|
+
const toggle = document.getElementById(`toggle-${mode}`);
|
94
|
+
if (toggle && mode !== 'default') {
|
95
|
+
toggle.addEventListener('click', (event) => {
|
96
|
+
event.stopPropagation();
|
97
|
+
const isOn = toggle.dataset.state === 'on';
|
98
|
+
toggle.dataset.state = isOn ? 'off' : 'on';
|
99
|
+
toggle.querySelector('img').src = isOn
|
100
|
+
? '/static/rest_mode/svg/toggle_off.svg'
|
101
|
+
: '/static/rest_mode/svg/toggle_on.svg';
|
102
|
+
showToast(`${mode.charAt(0).toUpperCase() + mode.slice(1)} Mode ${isOn ? 'disabled' : 'enabled'}`);
|
103
|
+
});
|
104
|
+
}
|
105
|
+
});
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Initialize collapsible behavior for LLM modes and sections.
|
110
|
+
*/
|
111
|
+
function initializeCollapsibleSections() {
|
112
|
+
document.querySelectorAll('.collapsible-toggle').forEach((toggle) => {
|
113
|
+
toggle.addEventListener('click', () => {
|
114
|
+
const content = toggle.nextElementSibling;
|
115
|
+
if (content) {
|
116
|
+
content.classList.toggle('hidden');
|
117
|
+
const isOpen = !content.classList.contains('hidden');
|
118
|
+
toggle.querySelector('span').textContent = isOpen ? '▲' : '▼';
|
119
|
+
}
|
120
|
+
});
|
121
|
+
});
|
122
|
+
}
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Initialize settings logic.
|
126
|
+
*/
|
127
|
+
document.addEventListener('DOMContentLoaded', () => {
|
128
|
+
debugLog("Settings page initialized.");
|
129
|
+
loadLLMConfig();
|
130
|
+
});
|