Spaces:
Running
Running
owenkaplinsky
commited on
Commit
·
2d05ba7
1
Parent(s):
867b451
Use a singular port
Browse files- project/__pycache__/chat.cpython-311.pyc +0 -0
- project/__pycache__/test.cpython-311.pyc +0 -0
- project/chat.py +7 -6
- project/dist/bundle.js +0 -0
- project/dist/bundle.js.LICENSE.txt +5 -0
- project/dist/bundle.js.map +0 -0
- project/dist/index.html +114 -0
- project/package.json +1 -2
- project/src/index.html +2 -2
- project/src/index.js +12 -12
- project/test.py +7 -5
- project/unified_server.py +113 -0
- project/webpack.config.js +0 -9
project/__pycache__/chat.cpython-311.pyc
ADDED
|
Binary file (40.1 kB). View file
|
|
|
project/__pycache__/test.cpython-311.pyc
ADDED
|
Binary file (13.5 kB). View file
|
|
|
project/chat.py
CHANGED
|
@@ -93,7 +93,7 @@ def execute_mcp(mcp_call):
|
|
| 93 |
# Now, retrieve the real generated Python code from test.py
|
| 94 |
blockly_code = ""
|
| 95 |
try:
|
| 96 |
-
resp = requests.get("http://
|
| 97 |
if resp.ok:
|
| 98 |
blockly_code = resp.json().get("code", "")
|
| 99 |
except Exception as e:
|
|
@@ -904,10 +904,11 @@ You will be given the current variables that are in the workspace. Like the bloc
|
|
| 904 |
|
| 905 |
return demo
|
| 906 |
|
| 907 |
-
|
| 908 |
-
|
| 909 |
-
|
|
|
|
| 910 |
|
| 911 |
if __name__ == "__main__":
|
| 912 |
-
|
| 913 |
-
|
|
|
|
| 93 |
# Now, retrieve the real generated Python code from test.py
|
| 94 |
blockly_code = ""
|
| 95 |
try:
|
| 96 |
+
resp = requests.get(f"http://127.0.0.1:{os.getenv('PORT', 8080)}/get_latest_code")
|
| 97 |
if resp.ok:
|
| 98 |
blockly_code = resp.json().get("code", "")
|
| 99 |
except Exception as e:
|
|
|
|
| 904 |
|
| 905 |
return demo
|
| 906 |
|
| 907 |
+
|
| 908 |
+
def get_chat_gradio_interface():
|
| 909 |
+
return create_gradio_interface()
|
| 910 |
+
|
| 911 |
|
| 912 |
if __name__ == "__main__":
|
| 913 |
+
demo = create_gradio_interface()
|
| 914 |
+
app = gr.mount_gradio_app(app, demo, path="/")
|
project/dist/bundle.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
project/dist/bundle.js.LICENSE.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @license
|
| 3 |
+
* Copyright 2019 Google LLC
|
| 4 |
+
* SPDX-License-Identifier: Apache-2.0
|
| 5 |
+
*/
|
project/dist/bundle.js.map
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
project/dist/index.html
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html><html><head><meta charset="utf-8"/><title>Blockly MCP Builder</title><script defer="defer" src="bundle.js"></script></head><body><div id="topBar"><div id="titleSection"><h1>Blockly MCP Builder</h1></div><div id="divider"></div><div id="menuSection"><div class="menuGroup"><button class="menuButton">File</button><div class="dropdown"><a href="#" id="newButton" class="dropdownItem" data-action="new">New</a> <a href="#" id="loadButton" class="dropdownItem" data-action="open">Open</a> <a href="#" id="saveButton" class="dropdownItem" data-action="download">Download Project</a> <a href="#" id="downloadCodeButton" class="dropdownItem" data-action="downloadCode">Download Code</a> <a href="#" id="settingsButton" class="dropdownItem" data-action="downloadCode">API Key</a></div></div><div class="menuGroup"><button class="menuButton">Edit</button><div class="dropdown"><a href="#" id="undoButton" class="dropdownItem" data-action="undo">Undo</a> <a href="#" id="redoButton" class="dropdownItem" data-action="redo">Redo</a> <a href="#" id="cleanWorkspace" class="dropdownItem" data-action="cleanup">Clean up</a></div></div><div class="menuGroup"><button class="menuButton">Examples</button><div class="dropdown"><a href="#" id="weatherButton" class="dropdownItem" data-action="undo">Weather API</a> <a href="#" id="factButton" class="dropdownItem" data-action="undo">Fact Checker</a></div></div></div><div id="githubLink"><a href="https://github.com/owenkaplinsky/mcp-blockly" target="_blank" rel="noopener noreferrer"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v 3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg></a></div></div><div id="pageContainer"><div id="outputPane"><div id="tabBar"><div class="tab active" data-tab="development">Development</div><div class="tab" data-tab="aichat">AI Chat</div></div><div id="developmentTab" class="tabContent active"><div id="chatContainer"><iframe src="/gradio-test" style="width: 100%; height: 100%; border: none;"></iframe></div><div class="verticalResizer"></div><pre id="generatedCode"><code></code></pre></div><div id="aichatTab" class="tabContent"><div id="gradioContainer"><iframe src="/gradio-chat" style="width: 100%; height: 100%; border: none;"></iframe></div><pre id="aichatCode" style="position: absolute; left: -9999px; width: 1px; height: 1px;"><code></code></pre></div></div><div class="resizer"></div><div id="blocklyDiv"></div></div><script>// Tab switching functionality
|
| 2 |
+
const tabs = document.querySelectorAll('.tab');
|
| 3 |
+
const tabContents = document.querySelectorAll('.tabContent');
|
| 4 |
+
|
| 5 |
+
tabs.forEach(tab => {
|
| 6 |
+
tab.addEventListener('click', () => {
|
| 7 |
+
const tabName = tab.getAttribute('data-tab');
|
| 8 |
+
|
| 9 |
+
// Remove active class from all tabs and contents
|
| 10 |
+
tabs.forEach(t => t.classList.remove('active'));
|
| 11 |
+
tabContents.forEach(content => content.classList.remove('active'));
|
| 12 |
+
|
| 13 |
+
// Add active class to clicked tab and corresponding content
|
| 14 |
+
tab.classList.add('active');
|
| 15 |
+
document.getElementById(tabName + 'Tab').classList.add('active');
|
| 16 |
+
});
|
| 17 |
+
});
|
| 18 |
+
|
| 19 |
+
// Horizontal resizer (output pane vs blockly)
|
| 20 |
+
const resizer = document.querySelector('.resizer');
|
| 21 |
+
const outputPane = document.getElementById('outputPane');
|
| 22 |
+
const pageContainer = document.getElementById('pageContainer');
|
| 23 |
+
|
| 24 |
+
let startX = 0;
|
| 25 |
+
let startWidth = 0;
|
| 26 |
+
|
| 27 |
+
function onPointerMove(e) {
|
| 28 |
+
const containerRect = pageContainer.getBoundingClientRect();
|
| 29 |
+
const containerWidth = containerRect.width;
|
| 30 |
+
|
| 31 |
+
const dx = e.clientX - startX;
|
| 32 |
+
let newWidthPx = startWidth + dx;
|
| 33 |
+
|
| 34 |
+
const minWidth = containerWidth * 0.2;
|
| 35 |
+
const maxWidth = containerWidth * 0.59;
|
| 36 |
+
newWidthPx = Math.max(minWidth, Math.min(maxWidth, newWidthPx));
|
| 37 |
+
|
| 38 |
+
const newPercent = (newWidthPx / containerWidth) * 100;
|
| 39 |
+
outputPane.style.flex = `0 0 ${newPercent}%`;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
function onPointerUp() {
|
| 43 |
+
resizer.releasePointerCapture(activePointerId);
|
| 44 |
+
resizer.removeEventListener('pointermove', onPointerMove);
|
| 45 |
+
resizer.removeEventListener('pointerup', onPointerUp);
|
| 46 |
+
resizer.classList.remove('active');
|
| 47 |
+
document.body.style.cursor = '';
|
| 48 |
+
document.body.style.userSelect = '';
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
let activePointerId = null;
|
| 52 |
+
|
| 53 |
+
resizer.addEventListener('pointerdown', (e) => {
|
| 54 |
+
const rect = outputPane.getBoundingClientRect();
|
| 55 |
+
startX = e.clientX;
|
| 56 |
+
startWidth = rect.width;
|
| 57 |
+
activePointerId = e.pointerId;
|
| 58 |
+
|
| 59 |
+
resizer.classList.add('active');
|
| 60 |
+
document.body.style.cursor = 'col-resize';
|
| 61 |
+
document.body.style.userSelect = 'none';
|
| 62 |
+
|
| 63 |
+
resizer.setPointerCapture(activePointerId);
|
| 64 |
+
resizer.addEventListener('pointermove', onPointerMove);
|
| 65 |
+
resizer.addEventListener('pointerup', onPointerUp);
|
| 66 |
+
});
|
| 67 |
+
|
| 68 |
+
// Vertical resizer (gradio vs code)
|
| 69 |
+
const verticalResizer = document.querySelector('.verticalResizer');
|
| 70 |
+
const chatContainer = document.getElementById('chatContainer');
|
| 71 |
+
const generatedCode = document.getElementById('generatedCode');
|
| 72 |
+
|
| 73 |
+
let startY = 0;
|
| 74 |
+
let startHeight = 0;
|
| 75 |
+
let activePointerId2 = null;
|
| 76 |
+
|
| 77 |
+
function onVerticalPointerMove(e) {
|
| 78 |
+
const outputPaneRect = outputPane.getBoundingClientRect();
|
| 79 |
+
const outputPaneHeight = outputPaneRect.height;
|
| 80 |
+
|
| 81 |
+
const dy = e.clientY - startY;
|
| 82 |
+
let newHeightPx = startHeight + dy;
|
| 83 |
+
|
| 84 |
+
const minHeight = outputPaneHeight * 0.4;
|
| 85 |
+
const maxHeight = outputPaneHeight * 0.78;
|
| 86 |
+
newHeightPx = Math.max(minHeight, Math.min(maxHeight, newHeightPx));
|
| 87 |
+
|
| 88 |
+
const newPercent = (newHeightPx / outputPaneHeight) * 100;
|
| 89 |
+
chatContainer.style.flex = `0 0 ${newPercent}%`;
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
function onVerticalPointerUp() {
|
| 93 |
+
verticalResizer.releasePointerCapture(activePointerId2);
|
| 94 |
+
verticalResizer.removeEventListener('pointermove', onVerticalPointerMove);
|
| 95 |
+
verticalResizer.removeEventListener('pointerup', onVerticalPointerUp);
|
| 96 |
+
verticalResizer.classList.remove('active');
|
| 97 |
+
document.body.style.cursor = '';
|
| 98 |
+
document.body.style.userSelect = '';
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
verticalResizer.addEventListener('pointerdown', (e) => {
|
| 102 |
+
const rect = chatContainer.getBoundingClientRect();
|
| 103 |
+
startY = e.clientY;
|
| 104 |
+
startHeight = rect.height;
|
| 105 |
+
activePointerId2 = e.pointerId;
|
| 106 |
+
|
| 107 |
+
verticalResizer.classList.add('active');
|
| 108 |
+
document.body.style.cursor = 'row-resize';
|
| 109 |
+
document.body.style.userSelect = 'none';
|
| 110 |
+
|
| 111 |
+
verticalResizer.setPointerCapture(activePointerId2);
|
| 112 |
+
verticalResizer.addEventListener('pointermove', onVerticalPointerMove);
|
| 113 |
+
verticalResizer.addEventListener('pointerup', onVerticalPointerUp);
|
| 114 |
+
});</script><div id="apiKeyModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 9999; align-items: center; justify-content: center;"><div style="background: white; padding: 30px; border-radius: 10px; width: 90%; max-width: 500px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);"><h2 style="margin-top: 0; margin-bottom: 20px; color: #333;">Settings</h2><label for="apiKeyInput" style="display: block; margin-bottom: 10px; color: #666; font-size: 14px;">OpenAI API Key:</label> <input type="password" id="apiKeyInput" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 14px; box-sizing: border-box;" placeholder="sk-..."><p style="margin-top: 10px; color: #999; font-size: 12px;">Your API key will be stored securely for this session.</p><div style="margin-top: 20px; display: flex; justify-content: flex-end; gap: 10px;"><button id="cancelApiKey" style="padding: 10px 20px; background: #e5e7eb; border: none; border-radius: 5px; cursor: pointer; font-size: 14px;">Cancel</button> <button id="saveApiKey" style="padding: 10px 20px; background: #6366f1; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 14px;">Save</button></div></div></div></body></html>
|
project/package.json
CHANGED
|
@@ -5,9 +5,8 @@
|
|
| 5 |
"main": "index.js",
|
| 6 |
"private": true,
|
| 7 |
"scripts": {
|
| 8 |
-
"test": "echo \"Error: no test specified\" && exit 1",
|
| 9 |
"build": "webpack --mode production",
|
| 10 |
-
"start": "
|
| 11 |
},
|
| 12 |
"keywords": [
|
| 13 |
"blockly"
|
|
|
|
| 5 |
"main": "index.js",
|
| 6 |
"private": true,
|
| 7 |
"scripts": {
|
|
|
|
| 8 |
"build": "webpack --mode production",
|
| 9 |
+
"start": "npm run build && python unified_server.py"
|
| 10 |
},
|
| 11 |
"keywords": [
|
| 12 |
"blockly"
|
project/src/index.html
CHANGED
|
@@ -59,14 +59,14 @@
|
|
| 59 |
</div>
|
| 60 |
<div id="developmentTab" class="tabContent active">
|
| 61 |
<div id="chatContainer">
|
| 62 |
-
<iframe src="
|
| 63 |
</div>
|
| 64 |
<div class="verticalResizer"></div>
|
| 65 |
<pre id="generatedCode"><code></code></pre>
|
| 66 |
</div>
|
| 67 |
<div id="aichatTab" class="tabContent">
|
| 68 |
<div id="gradioContainer">
|
| 69 |
-
<iframe src="
|
| 70 |
</div>
|
| 71 |
<pre id="aichatCode" style="position: absolute; left: -9999px; width: 1px; height: 1px;"><code></code></pre>
|
| 72 |
</div>
|
|
|
|
| 59 |
</div>
|
| 60 |
<div id="developmentTab" class="tabContent active">
|
| 61 |
<div id="chatContainer">
|
| 62 |
+
<iframe src="/gradio-test" style="width: 100%; height: 100%; border: none;"></iframe>
|
| 63 |
</div>
|
| 64 |
<div class="verticalResizer"></div>
|
| 65 |
<pre id="generatedCode"><code></code></pre>
|
| 66 |
</div>
|
| 67 |
<div id="aichatTab" class="tabContent">
|
| 68 |
<div id="gradioContainer">
|
| 69 |
+
<iframe src="/gradio-chat" style="width: 100%; height: 100%; border: none;"></iframe>
|
| 70 |
</div>
|
| 71 |
<pre id="aichatCode" style="position: absolute; left: -9999px; width: 1px; height: 1px;"><code></code></pre>
|
| 72 |
</div>
|
project/src/index.js
CHANGED
|
@@ -160,7 +160,7 @@ settingsButton.addEventListener("click", () => {
|
|
| 160 |
apiKeyModal.style.display = 'flex';
|
| 161 |
|
| 162 |
// Load current API key from backend
|
| 163 |
-
fetch("
|
| 164 |
method: "GET",
|
| 165 |
})
|
| 166 |
.then(response => response.json())
|
|
@@ -183,12 +183,12 @@ saveApiKeyButton.addEventListener("click", () => {
|
|
| 183 |
|
| 184 |
// Save API key to both backend servers (test.py and chat.py)
|
| 185 |
Promise.all([
|
| 186 |
-
fetch("
|
| 187 |
method: "POST",
|
| 188 |
headers: { "Content-Type": "application/json" },
|
| 189 |
body: JSON.stringify({ api_key: apiKey }),
|
| 190 |
}),
|
| 191 |
-
fetch("
|
| 192 |
method: "POST",
|
| 193 |
headers: { "Content-Type": "application/json" },
|
| 194 |
body: JSON.stringify({ api_key: apiKey }),
|
|
@@ -247,7 +247,7 @@ cleanWorkspace.addEventListener("click", () => {
|
|
| 247 |
|
| 248 |
// Set up SSE connection for deletion requests
|
| 249 |
const setupDeletionStream = () => {
|
| 250 |
-
const eventSource = new EventSource('
|
| 251 |
const processedRequests = new Set(); // Track processed deletion requests
|
| 252 |
|
| 253 |
eventSource.onmessage = (event) => {
|
|
@@ -300,7 +300,7 @@ const setupDeletionStream = () => {
|
|
| 300 |
|
| 301 |
// Send result back to backend immediately
|
| 302 |
console.log('[SSE] Sending deletion result:', { block_id: data.block_id, success, error });
|
| 303 |
-
fetch('
|
| 304 |
method: 'POST',
|
| 305 |
headers: { 'Content-Type': 'application/json' },
|
| 306 |
body: JSON.stringify({
|
|
@@ -338,7 +338,7 @@ setupDeletionStream();
|
|
| 338 |
|
| 339 |
// Set up SSE connection for creation requests
|
| 340 |
const setupCreationStream = () => {
|
| 341 |
-
const eventSource = new EventSource('
|
| 342 |
const processedRequests = new Set(); // Track processed creation requests
|
| 343 |
|
| 344 |
eventSource.onmessage = (event) => {
|
|
@@ -712,7 +712,7 @@ const setupCreationStream = () => {
|
|
| 712 |
block_id: blockId
|
| 713 |
});
|
| 714 |
|
| 715 |
-
fetch('
|
| 716 |
method: 'POST',
|
| 717 |
headers: { 'Content-Type': 'application/json' },
|
| 718 |
body: JSON.stringify({
|
|
@@ -750,7 +750,7 @@ const setupCreationStream = () => {
|
|
| 750 |
setupCreationStream();
|
| 751 |
|
| 752 |
const setupVariableStream = () => {
|
| 753 |
-
const eventSource = new EventSource('
|
| 754 |
const processedRequests = new Set(); // Track processed variable requests
|
| 755 |
|
| 756 |
eventSource.onmessage = (event) => {
|
|
@@ -806,7 +806,7 @@ const setupVariableStream = () => {
|
|
| 806 |
variable_id: variableId
|
| 807 |
});
|
| 808 |
|
| 809 |
-
fetch('
|
| 810 |
method: 'POST',
|
| 811 |
headers: { 'Content-Type': 'application/json' },
|
| 812 |
body: JSON.stringify({
|
|
@@ -928,7 +928,7 @@ const updateCode = () => {
|
|
| 928 |
}
|
| 929 |
|
| 930 |
// Send generated Python code to backend
|
| 931 |
-
fetch("
|
| 932 |
method: "POST",
|
| 933 |
headers: { "Content-Type": "application/json" },
|
| 934 |
body: JSON.stringify({ code }),
|
|
@@ -953,7 +953,7 @@ let globalVarString = '';
|
|
| 953 |
// Function to check if chat backend is available
|
| 954 |
const checkChatBackend = async () => {
|
| 955 |
try {
|
| 956 |
-
const response = await fetch("
|
| 957 |
method: "POST",
|
| 958 |
headers: { "Content-Type": "application/json" },
|
| 959 |
body: JSON.stringify({
|
|
@@ -986,7 +986,7 @@ const processChatUpdateQueue = () => {
|
|
| 986 |
// Send chat update with retry logic
|
| 987 |
const sendChatUpdate = async (chatCode, retryCount = 0) => {
|
| 988 |
try {
|
| 989 |
-
const response = await fetch("
|
| 990 |
method: "POST",
|
| 991 |
headers: { "Content-Type": "application/json" },
|
| 992 |
body: JSON.stringify({
|
|
|
|
| 160 |
apiKeyModal.style.display = 'flex';
|
| 161 |
|
| 162 |
// Load current API key from backend
|
| 163 |
+
fetch("/get_api_key", {
|
| 164 |
method: "GET",
|
| 165 |
})
|
| 166 |
.then(response => response.json())
|
|
|
|
| 183 |
|
| 184 |
// Save API key to both backend servers (test.py and chat.py)
|
| 185 |
Promise.all([
|
| 186 |
+
fetch("/set_api_key", {
|
| 187 |
method: "POST",
|
| 188 |
headers: { "Content-Type": "application/json" },
|
| 189 |
body: JSON.stringify({ api_key: apiKey }),
|
| 190 |
}),
|
| 191 |
+
fetch("/set_api_key_chat", {
|
| 192 |
method: "POST",
|
| 193 |
headers: { "Content-Type": "application/json" },
|
| 194 |
body: JSON.stringify({ api_key: apiKey }),
|
|
|
|
| 247 |
|
| 248 |
// Set up SSE connection for deletion requests
|
| 249 |
const setupDeletionStream = () => {
|
| 250 |
+
const eventSource = new EventSource('/delete_stream');
|
| 251 |
const processedRequests = new Set(); // Track processed deletion requests
|
| 252 |
|
| 253 |
eventSource.onmessage = (event) => {
|
|
|
|
| 300 |
|
| 301 |
// Send result back to backend immediately
|
| 302 |
console.log('[SSE] Sending deletion result:', { block_id: data.block_id, success, error });
|
| 303 |
+
fetch('/deletion_result', {
|
| 304 |
method: 'POST',
|
| 305 |
headers: { 'Content-Type': 'application/json' },
|
| 306 |
body: JSON.stringify({
|
|
|
|
| 338 |
|
| 339 |
// Set up SSE connection for creation requests
|
| 340 |
const setupCreationStream = () => {
|
| 341 |
+
const eventSource = new EventSource('/create_stream');
|
| 342 |
const processedRequests = new Set(); // Track processed creation requests
|
| 343 |
|
| 344 |
eventSource.onmessage = (event) => {
|
|
|
|
| 712 |
block_id: blockId
|
| 713 |
});
|
| 714 |
|
| 715 |
+
fetch('/creation_result', {
|
| 716 |
method: 'POST',
|
| 717 |
headers: { 'Content-Type': 'application/json' },
|
| 718 |
body: JSON.stringify({
|
|
|
|
| 750 |
setupCreationStream();
|
| 751 |
|
| 752 |
const setupVariableStream = () => {
|
| 753 |
+
const eventSource = new EventSource('/variable_stream');
|
| 754 |
const processedRequests = new Set(); // Track processed variable requests
|
| 755 |
|
| 756 |
eventSource.onmessage = (event) => {
|
|
|
|
| 806 |
variable_id: variableId
|
| 807 |
});
|
| 808 |
|
| 809 |
+
fetch('/variable_result', {
|
| 810 |
method: 'POST',
|
| 811 |
headers: { 'Content-Type': 'application/json' },
|
| 812 |
body: JSON.stringify({
|
|
|
|
| 928 |
}
|
| 929 |
|
| 930 |
// Send generated Python code to backend
|
| 931 |
+
fetch("/update_code", {
|
| 932 |
method: "POST",
|
| 933 |
headers: { "Content-Type": "application/json" },
|
| 934 |
body: JSON.stringify({ code }),
|
|
|
|
| 953 |
// Function to check if chat backend is available
|
| 954 |
const checkChatBackend = async () => {
|
| 955 |
try {
|
| 956 |
+
const response = await fetch("/update_chat", {
|
| 957 |
method: "POST",
|
| 958 |
headers: { "Content-Type": "application/json" },
|
| 959 |
body: JSON.stringify({
|
|
|
|
| 986 |
// Send chat update with retry logic
|
| 987 |
const sendChatUpdate = async (chatCode, retryCount = 0) => {
|
| 988 |
try {
|
| 989 |
+
const response = await fetch("/update_chat", {
|
| 990 |
method: "POST",
|
| 991 |
headers: { "Content-Type": "application/json" },
|
| 992 |
body: JSON.stringify({
|
project/test.py
CHANGED
|
@@ -293,15 +293,17 @@ def build_interface():
|
|
| 293 |
submit_btn.click(
|
| 294 |
process_input,
|
| 295 |
inputs=input_fields,
|
| 296 |
-
outputs=output_fields
|
|
|
|
| 297 |
)
|
| 298 |
|
| 299 |
return demo
|
| 300 |
|
| 301 |
|
| 302 |
-
|
| 303 |
-
|
|
|
|
| 304 |
|
| 305 |
if __name__ == "__main__":
|
| 306 |
-
|
| 307 |
-
|
|
|
|
| 293 |
submit_btn.click(
|
| 294 |
process_input,
|
| 295 |
inputs=input_fields,
|
| 296 |
+
outputs=output_fields,
|
| 297 |
+
queue=False
|
| 298 |
)
|
| 299 |
|
| 300 |
return demo
|
| 301 |
|
| 302 |
|
| 303 |
+
def get_gradio_interface():
|
| 304 |
+
return build_interface()
|
| 305 |
+
|
| 306 |
|
| 307 |
if __name__ == "__main__":
|
| 308 |
+
demo = build_interface()
|
| 309 |
+
app = gr.mount_gradio_app(app, demo, path="/")
|
project/unified_server.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, Request
|
| 2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
+
from fastapi.staticfiles import StaticFiles
|
| 4 |
+
import gradio as gr
|
| 5 |
+
import uvicorn
|
| 6 |
+
import os
|
| 7 |
+
import sys
|
| 8 |
+
|
| 9 |
+
# Ensure local modules are importable
|
| 10 |
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
| 11 |
+
import test
|
| 12 |
+
import chat
|
| 13 |
+
|
| 14 |
+
app = FastAPI()
|
| 15 |
+
|
| 16 |
+
app.add_middleware(
|
| 17 |
+
CORSMiddleware,
|
| 18 |
+
allow_origins=["*"],
|
| 19 |
+
allow_credentials=True,
|
| 20 |
+
allow_methods=["*"],
|
| 21 |
+
allow_headers=["*"],
|
| 22 |
+
)
|
| 23 |
+
|
| 24 |
+
# -------------------------------------------------------------------
|
| 25 |
+
# Full API Forwarding Layer for chat.py and test.py
|
| 26 |
+
# -------------------------------------------------------------------
|
| 27 |
+
|
| 28 |
+
# === chat.py API endpoints ===
|
| 29 |
+
@app.post("/update_chat")
|
| 30 |
+
async def update_chat_route(request: Request):
|
| 31 |
+
return await chat.update_chat(request)
|
| 32 |
+
|
| 33 |
+
@app.post("/set_api_key_chat")
|
| 34 |
+
async def set_api_key_chat_route(request: Request):
|
| 35 |
+
return await chat.set_api_key_chat(request)
|
| 36 |
+
|
| 37 |
+
@app.get("/create_stream")
|
| 38 |
+
async def create_stream_route():
|
| 39 |
+
return await chat.create_stream()
|
| 40 |
+
|
| 41 |
+
@app.post("/creation_result")
|
| 42 |
+
async def creation_result_route(request: Request):
|
| 43 |
+
return await chat.creation_result(request)
|
| 44 |
+
|
| 45 |
+
@app.get("/delete_stream")
|
| 46 |
+
async def delete_stream_route():
|
| 47 |
+
return await chat.delete_stream()
|
| 48 |
+
|
| 49 |
+
@app.post("/deletion_result")
|
| 50 |
+
async def deletion_result_route(request: Request):
|
| 51 |
+
return await chat.deletion_result(request)
|
| 52 |
+
|
| 53 |
+
@app.get("/variable_stream")
|
| 54 |
+
async def variable_stream_route():
|
| 55 |
+
return await chat.variable_stream()
|
| 56 |
+
|
| 57 |
+
@app.post("/variable_result")
|
| 58 |
+
async def variable_result_route(request: Request):
|
| 59 |
+
return await chat.variable_result(request)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
# === test.py API endpoints ===
|
| 63 |
+
@app.post("/update_code")
|
| 64 |
+
async def update_code_route(request: Request):
|
| 65 |
+
return await test.update_code(request)
|
| 66 |
+
|
| 67 |
+
@app.get("/get_latest_code")
|
| 68 |
+
async def get_latest_code_route():
|
| 69 |
+
return await test.get_latest_code()
|
| 70 |
+
|
| 71 |
+
@app.get("/get_api_key")
|
| 72 |
+
async def get_api_key_route():
|
| 73 |
+
return await test.get_api_key_endpoint()
|
| 74 |
+
|
| 75 |
+
@app.post("/set_api_key")
|
| 76 |
+
async def set_api_key_route(request: Request):
|
| 77 |
+
return await test.set_api_key_endpoint(request)
|
| 78 |
+
|
| 79 |
+
# Serve built frontend WITHOUT shadowing Gradio paths
|
| 80 |
+
from fastapi.responses import FileResponse
|
| 81 |
+
|
| 82 |
+
frontend_dir = os.path.join(os.path.dirname(__file__), "dist")
|
| 83 |
+
if not os.path.exists(frontend_dir):
|
| 84 |
+
os.makedirs(frontend_dir)
|
| 85 |
+
|
| 86 |
+
@app.get("/")
|
| 87 |
+
def serve_index():
|
| 88 |
+
return FileResponse(os.path.join(frontend_dir, "index.html"))
|
| 89 |
+
|
| 90 |
+
@app.get("/bundle.js")
|
| 91 |
+
def serve_bundle():
|
| 92 |
+
return FileResponse(os.path.join(frontend_dir, "bundle.js"))
|
| 93 |
+
|
| 94 |
+
# Optionally serve other built assets if needed
|
| 95 |
+
app.mount("/assets", StaticFiles(directory=frontend_dir), name="assets")
|
| 96 |
+
|
| 97 |
+
# Mount both Gradio interfaces
|
| 98 |
+
test_demo = test.get_gradio_interface()
|
| 99 |
+
chat_demo = chat.get_chat_gradio_interface()
|
| 100 |
+
|
| 101 |
+
# Mount the Gradio apps directly
|
| 102 |
+
app = gr.mount_gradio_app(app, test_demo, path="/gradio-test")
|
| 103 |
+
app = gr.mount_gradio_app(app, chat_demo, path="/gradio-chat")
|
| 104 |
+
|
| 105 |
+
print("new /gradio-test")
|
| 106 |
+
print("new /gradio-chat")
|
| 107 |
+
|
| 108 |
+
if __name__ == "__main__":
|
| 109 |
+
port = int(os.getenv("PORT", 8080))
|
| 110 |
+
print(f"[UNIFIED] running on http://127.0.0.1:{port}")
|
| 111 |
+
print(f"- /gradio-test")
|
| 112 |
+
print(f"- /gradio-chat")
|
| 113 |
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
project/webpack.config.js
CHANGED
|
@@ -27,15 +27,6 @@ module.exports = {
|
|
| 27 |
template: './src/index.html',
|
| 28 |
}),
|
| 29 |
],
|
| 30 |
-
devServer: {
|
| 31 |
-
static: {
|
| 32 |
-
directory: path.join(__dirname, 'public'),
|
| 33 |
-
},
|
| 34 |
-
compress: true,
|
| 35 |
-
port: 8081,
|
| 36 |
-
hot: true,
|
| 37 |
-
open: true,
|
| 38 |
-
},
|
| 39 |
resolve: {
|
| 40 |
extensions: ['.js', '.json', '.css'],
|
| 41 |
},
|
|
|
|
| 27 |
template: './src/index.html',
|
| 28 |
}),
|
| 29 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
resolve: {
|
| 31 |
extensions: ['.js', '.json', '.css'],
|
| 32 |
},
|