Spaces:
Running
Running
mas eu nao faç ideia, qual arquivo, a IA mesmo vai ter que escolher e saber ual vai ser editado, eu so vou dar o problema
Browse files- index.html +3 -33
- script.js +168 -277
index.html
CHANGED
|
@@ -49,33 +49,6 @@
|
|
| 49 |
<input type="file" id="file-input" webkitdirectory directory multiple class="hidden">
|
| 50 |
</div>
|
| 51 |
</div>
|
| 52 |
-
<!-- File Tree -->
|
| 53 |
-
<div id="file-tree-container" class="mb-6 hidden">
|
| 54 |
-
<h3 class="text-lg font-medium text-gray-700 mb-2">Select Files to Process</h3>
|
| 55 |
-
<div id="file-tree" class="bg-gray-50 rounded-lg p-4 max-h-60 overflow-y-auto"></div>
|
| 56 |
-
<button id="process-selected" class="mt-3 bg-secondary text-white px-4 py-2 rounded-lg hover:bg-purple-600 transition-colors">
|
| 57 |
-
Process Selected Files
|
| 58 |
-
</button>
|
| 59 |
-
</div>
|
| 60 |
-
|
| 61 |
-
<!-- File Editor -->
|
| 62 |
-
<div id="editor-container" class="mb-6 hidden">
|
| 63 |
-
<h3 class="text-lg font-medium text-gray-700 mb-2">File Editor</h3>
|
| 64 |
-
<div class="mb-2">
|
| 65 |
-
<select id="file-selector" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary">
|
| 66 |
-
<option value="">Select a file to edit</option>
|
| 67 |
-
</select>
|
| 68 |
-
</div>
|
| 69 |
-
<textarea id="code-editor" class="w-full h-64 border border-gray-300 rounded-lg px-3 py-2 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-primary" placeholder="Select a file to view/edit its content..."></textarea>
|
| 70 |
-
<div class="mt-2 flex gap-2">
|
| 71 |
-
<button id="save-file" class="bg-primary text-white px-4 py-2 rounded-lg hover:bg-indigo-600 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
|
| 72 |
-
Save Changes
|
| 73 |
-
</button>
|
| 74 |
-
<button id="run-code" class="bg-green-500 text-white px-4 py-2 rounded-lg hover:bg-green-600 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
|
| 75 |
-
Run Code
|
| 76 |
-
</button>
|
| 77 |
-
</div>
|
| 78 |
-
</div>
|
| 79 |
<!-- Problem Description -->
|
| 80 |
<div class="mb-6">
|
| 81 |
<label class="block text-gray-700 mb-2">Problem Description</label>
|
|
@@ -86,12 +59,11 @@
|
|
| 86 |
</button>
|
| 87 |
</div>
|
| 88 |
</div>
|
| 89 |
-
|
| 90 |
<!-- Start Analysis Button -->
|
| 91 |
<button id="start-analysis" class="w-full bg-primary text-white py-3 rounded-lg font-medium hover:bg-indigo-600 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
|
| 92 |
-
|
| 93 |
</button>
|
| 94 |
-
|
| 95 |
|
| 96 |
<!-- Results Section -->
|
| 97 |
<div class="bg-white rounded-xl shadow-md p-6">
|
|
@@ -143,9 +115,7 @@
|
|
| 143 |
</div>
|
| 144 |
</div>
|
| 145 |
</div>
|
| 146 |
-
|
| 147 |
-
<script src="components/file-tree.js"></script>
|
| 148 |
-
<script src="script.js"></script>
|
| 149 |
<script>feather.replace();</script>
|
| 150 |
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 151 |
</body>
|
|
|
|
| 49 |
<input type="file" id="file-input" webkitdirectory directory multiple class="hidden">
|
| 50 |
</div>
|
| 51 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
<!-- Problem Description -->
|
| 53 |
<div class="mb-6">
|
| 54 |
<label class="block text-gray-700 mb-2">Problem Description</label>
|
|
|
|
| 59 |
</button>
|
| 60 |
</div>
|
| 61 |
</div>
|
|
|
|
| 62 |
<!-- Start Analysis Button -->
|
| 63 |
<button id="start-analysis" class="w-full bg-primary text-white py-3 rounded-lg font-medium hover:bg-indigo-600 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
|
| 64 |
+
AI Automatic Analysis & Fix
|
| 65 |
</button>
|
| 66 |
+
</div>
|
| 67 |
|
| 68 |
<!-- Results Section -->
|
| 69 |
<div class="bg-white rounded-xl shadow-md p-6">
|
|
|
|
| 115 |
</div>
|
| 116 |
</div>
|
| 117 |
</div>
|
| 118 |
+
<script src="script.js"></script>
|
|
|
|
|
|
|
| 119 |
<script>feather.replace();</script>
|
| 120 |
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 121 |
</body>
|
script.js
CHANGED
|
@@ -7,7 +7,6 @@ const state = {
|
|
| 7 |
qwenResponse: '',
|
| 8 |
zaiResponse: '',
|
| 9 |
correctedFiles: [],
|
| 10 |
-
currentFile: null,
|
| 11 |
isProcessing: false
|
| 12 |
};
|
| 13 |
// DOM Elements
|
|
@@ -15,14 +14,6 @@ const elements = {
|
|
| 15 |
dropZone: document.getElementById('drop-zone'),
|
| 16 |
fileInput: document.getElementById('file-input'),
|
| 17 |
browseBtn: document.getElementById('browse-btn'),
|
| 18 |
-
fileTreeContainer: document.getElementById('file-tree-container'),
|
| 19 |
-
fileTree: document.getElementById('file-tree'),
|
| 20 |
-
processSelected: document.getElementById('process-selected'),
|
| 21 |
-
editorContainer: document.getElementById('editor-container'),
|
| 22 |
-
fileSelector: document.getElementById('file-selector'),
|
| 23 |
-
codeEditor: document.getElementById('code-editor'),
|
| 24 |
-
saveFile: document.getElementById('save-file'),
|
| 25 |
-
runCode: document.getElementById('run-code'),
|
| 26 |
problemInput: document.getElementById('problem-input'),
|
| 27 |
voiceBtn: document.getElementById('voice-btn'),
|
| 28 |
startAnalysis: document.getElementById('start-analysis'),
|
|
@@ -34,15 +25,12 @@ const elements = {
|
|
| 34 |
fileList: document.getElementById('file-list'),
|
| 35 |
downloadAll: document.getElementById('download-all'),
|
| 36 |
applyChanges: document.getElementById('apply-changes'),
|
| 37 |
-
outputContainer: document.getElementById('output-container'),
|
| 38 |
-
codeOutput: document.getElementById('code-output'),
|
| 39 |
errorContainer: document.getElementById('error-container')
|
| 40 |
};
|
| 41 |
// Initialize the app
|
| 42 |
document.addEventListener('DOMContentLoaded', () => {
|
| 43 |
setupEventListeners();
|
| 44 |
});
|
| 45 |
-
|
| 46 |
// Set up event listeners
|
| 47 |
function setupEventListeners() {
|
| 48 |
// File upload
|
|
@@ -50,13 +38,6 @@ function setupEventListeners() {
|
|
| 50 |
elements.dropZone.addEventListener('dragover', handleDragOver);
|
| 51 |
elements.dropZone.addEventListener('drop', handleDrop);
|
| 52 |
elements.fileInput.addEventListener('change', handleFileSelect);
|
| 53 |
-
// Process files
|
| 54 |
-
elements.processSelected.addEventListener('click', processSelectedFiles);
|
| 55 |
-
|
| 56 |
-
// File editor
|
| 57 |
-
elements.fileSelector.addEventListener('change', loadFileContent);
|
| 58 |
-
elements.saveFile.addEventListener('click', saveCurrentFile);
|
| 59 |
-
elements.runCode.addEventListener('click', runCurrentCode);
|
| 60 |
|
| 61 |
// Voice input
|
| 62 |
elements.voiceBtn.addEventListener('click', startVoiceInput);
|
|
@@ -68,7 +49,6 @@ function setupEventListeners() {
|
|
| 68 |
elements.downloadAll.addEventListener('click', downloadAllFiles);
|
| 69 |
elements.applyChanges.addEventListener('click', applyChangesToProject);
|
| 70 |
}
|
| 71 |
-
|
| 72 |
// File handling functions
|
| 73 |
function handleDragOver(e) {
|
| 74 |
e.preventDefault();
|
|
@@ -93,7 +73,6 @@ function handleFileSelect(e) {
|
|
| 93 |
processDirectoryFiles(files);
|
| 94 |
}
|
| 95 |
}
|
| 96 |
-
|
| 97 |
// Process directory items from drag and drop
|
| 98 |
function processDirectoryItems(items) {
|
| 99 |
state.files = [];
|
|
@@ -105,13 +84,11 @@ function processDirectoryItems(items) {
|
|
| 105 |
}
|
| 106 |
}
|
| 107 |
|
| 108 |
-
//
|
| 109 |
setTimeout(() => {
|
| 110 |
-
|
| 111 |
-
elements.fileTreeContainer.classList.remove('hidden');
|
| 112 |
}, 500);
|
| 113 |
}
|
| 114 |
-
|
| 115 |
// Process directory files from file input
|
| 116 |
function processDirectoryFiles(files) {
|
| 117 |
state.files = Array.from(files).map(file => ({
|
|
@@ -121,10 +98,9 @@ function processDirectoryFiles(files) {
|
|
| 121 |
selected: true
|
| 122 |
}));
|
| 123 |
|
| 124 |
-
|
| 125 |
-
|
| 126 |
}
|
| 127 |
-
|
| 128 |
// Traverse file tree (for drag and drop)
|
| 129 |
function traverseFileTree(item, path = '') {
|
| 130 |
if (item.isFile) {
|
|
@@ -146,73 +122,18 @@ function traverseFileTree(item, path = '') {
|
|
| 146 |
});
|
| 147 |
}
|
| 148 |
}
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
function renderFileTree() {
|
| 152 |
-
// Group files by directory
|
| 153 |
-
const fileStructure = {};
|
| 154 |
-
|
| 155 |
-
state.files.forEach(fileObj => {
|
| 156 |
-
const parts = fileObj.name.split('/');
|
| 157 |
-
let current = fileStructure;
|
| 158 |
-
|
| 159 |
-
for (let i = 0; i < parts.length; i++) {
|
| 160 |
-
const part = parts[i];
|
| 161 |
-
if (i === parts.length - 1) {
|
| 162 |
-
// File
|
| 163 |
-
if (!current[part]) {
|
| 164 |
-
current[part] = {
|
| 165 |
-
type: 'file',
|
| 166 |
-
name: part,
|
| 167 |
-
path: fileObj.name,
|
| 168 |
-
file: fileObj.file,
|
| 169 |
-
selected: true
|
| 170 |
-
};
|
| 171 |
-
}
|
| 172 |
-
} else {
|
| 173 |
-
// Directory
|
| 174 |
-
if (!current[part]) {
|
| 175 |
-
current[part] = {
|
| 176 |
-
type: 'directory',
|
| 177 |
-
name: part,
|
| 178 |
-
children: {}
|
| 179 |
-
};
|
| 180 |
-
}
|
| 181 |
-
current = current[part].children;
|
| 182 |
-
}
|
| 183 |
-
}
|
| 184 |
-
});
|
| 185 |
-
|
| 186 |
-
// Render using web component
|
| 187 |
-
elements.fileTree.innerHTML = '';
|
| 188 |
-
const fileTreeElement = document.createElement('file-tree');
|
| 189 |
-
fileTreeElement.fileStructure = fileStructure;
|
| 190 |
-
fileTreeElement.addEventListener('selection-change', (e) => {
|
| 191 |
-
// Update selections in state
|
| 192 |
-
state.files.forEach(fileObj => {
|
| 193 |
-
const matchingFile = e.detail.find(f => f.path === fileObj.name);
|
| 194 |
-
if (matchingFile) {
|
| 195 |
-
fileObj.selected = matchingFile.selected;
|
| 196 |
-
}
|
| 197 |
-
});
|
| 198 |
-
});
|
| 199 |
-
elements.fileTree.appendChild(fileTreeElement);
|
| 200 |
-
}
|
| 201 |
-
// Process selected files into text format
|
| 202 |
-
async function processSelectedFiles() {
|
| 203 |
-
elements.processSelected.disabled = true;
|
| 204 |
-
elements.processSelected.textContent = 'Processing...';
|
| 205 |
-
|
| 206 |
try {
|
| 207 |
-
// Filter
|
| 208 |
-
const
|
| 209 |
|
| 210 |
// Sort files alphabetically
|
| 211 |
-
|
| 212 |
|
| 213 |
// Process each file
|
| 214 |
const fileContents = [];
|
| 215 |
-
for (const fileObj of
|
| 216 |
try {
|
| 217 |
const content = await readFileAsText(fileObj.file);
|
| 218 |
fileContents.push({
|
|
@@ -226,141 +147,18 @@ async function processSelectedFiles() {
|
|
| 226 |
}
|
| 227 |
}
|
| 228 |
|
| 229 |
-
// Generate structured text output
|
| 230 |
let output = '';
|
| 231 |
for (const fileContent of fileContents) {
|
| 232 |
output += `${fileContent.path}\n"${fileContent.content}"\n\n`;
|
| 233 |
}
|
| 234 |
|
| 235 |
state.processedText = output;
|
| 236 |
-
|
| 237 |
-
// Setup file selector
|
| 238 |
-
setupFileSelector(selectedFiles);
|
| 239 |
-
|
| 240 |
-
// Show editor
|
| 241 |
-
elements.editorContainer.classList.remove('hidden');
|
| 242 |
-
|
| 243 |
-
showNotification('Files processed successfully!', 'success');
|
| 244 |
} catch (error) {
|
| 245 |
showError('Error processing files: ' + error.message);
|
| 246 |
-
} finally {
|
| 247 |
-
elements.processSelected.disabled = false;
|
| 248 |
-
elements.processSelected.textContent = 'Process Selected Files';
|
| 249 |
-
}
|
| 250 |
-
}
|
| 251 |
-
|
| 252 |
-
// Setup file selector dropdown
|
| 253 |
-
function setupFileSelector(files) {
|
| 254 |
-
elements.fileSelector.innerHTML = '<option value="">Select a file to edit</option>';
|
| 255 |
-
|
| 256 |
-
files.forEach(fileObj => {
|
| 257 |
-
const option = document.createElement('option');
|
| 258 |
-
option.value = fileObj.name;
|
| 259 |
-
option.textContent = fileObj.name;
|
| 260 |
-
elements.fileSelector.appendChild(option);
|
| 261 |
-
});
|
| 262 |
-
|
| 263 |
-
elements.saveFile.disabled = true;
|
| 264 |
-
elements.runCode.disabled = true;
|
| 265 |
-
}
|
| 266 |
-
|
| 267 |
-
// Load file content into editor
|
| 268 |
-
function loadFileContent() {
|
| 269 |
-
const selectedPath = elements.fileSelector.value;
|
| 270 |
-
|
| 271 |
-
if (!selectedPath) {
|
| 272 |
-
elements.codeEditor.value = '';
|
| 273 |
-
elements.saveFile.disabled = true;
|
| 274 |
-
elements.runCode.disabled = true;
|
| 275 |
-
state.currentFile = null;
|
| 276 |
-
return;
|
| 277 |
-
}
|
| 278 |
-
|
| 279 |
-
const content = state.fileContents.get(selectedPath) || '';
|
| 280 |
-
elements.codeEditor.value = content;
|
| 281 |
-
state.currentFile = selectedPath;
|
| 282 |
-
|
| 283 |
-
// Enable buttons for certain file types
|
| 284 |
-
const isRunnable = /\.(js|ts|py|html|css)$/.test(selectedPath);
|
| 285 |
-
elements.saveFile.disabled = false;
|
| 286 |
-
elements.runCode.disabled = !isRunnable;
|
| 287 |
-
}
|
| 288 |
-
|
| 289 |
-
// Save current file changes
|
| 290 |
-
function saveCurrentFile() {
|
| 291 |
-
if (!state.currentFile) return;
|
| 292 |
-
|
| 293 |
-
const newContent = elements.codeEditor.value;
|
| 294 |
-
state.fileContents.set(state.currentFile, newContent);
|
| 295 |
-
|
| 296 |
-
showNotification(`File ${state.currentFile} saved!`, 'success');
|
| 297 |
-
}
|
| 298 |
-
|
| 299 |
-
// Run current code
|
| 300 |
-
function runCurrentCode() {
|
| 301 |
-
if (!state.currentFile) return;
|
| 302 |
-
|
| 303 |
-
const content = elements.codeEditor.value;
|
| 304 |
-
const fileExt = state.currentFile.split('.').pop().toLowerCase();
|
| 305 |
-
|
| 306 |
-
elements.outputContainer.classList.remove('hidden');
|
| 307 |
-
elements.codeOutput.innerHTML = 'Running...\n';
|
| 308 |
-
|
| 309 |
-
try {
|
| 310 |
-
switch(fileExt) {
|
| 311 |
-
case 'js':
|
| 312 |
-
runJavaScript(content);
|
| 313 |
-
break;
|
| 314 |
-
case 'py':
|
| 315 |
-
runPython(content);
|
| 316 |
-
break;
|
| 317 |
-
case 'html':
|
| 318 |
-
runHTML(content);
|
| 319 |
-
break;
|
| 320 |
-
default:
|
| 321 |
-
elements.codeOutput.innerHTML = `Running ${fileExt} files is not supported in this demo.\n`;
|
| 322 |
-
}
|
| 323 |
-
} catch (error) {
|
| 324 |
-
elements.codeOutput.innerHTML = `Error: ${error.message}\n`;
|
| 325 |
-
}
|
| 326 |
-
}
|
| 327 |
-
|
| 328 |
-
// Run JavaScript code
|
| 329 |
-
function runJavaScript(code) {
|
| 330 |
-
try {
|
| 331 |
-
// Capture console.log output
|
| 332 |
-
const originalLog = console.log;
|
| 333 |
-
const output = [];
|
| 334 |
-
console.log = (...args) => {
|
| 335 |
-
output.push(args.join(' '));
|
| 336 |
-
};
|
| 337 |
-
|
| 338 |
-
// Execute code
|
| 339 |
-
eval(code);
|
| 340 |
-
|
| 341 |
-
// Restore console.log
|
| 342 |
-
console.log = originalLog;
|
| 343 |
-
|
| 344 |
-
elements.codeOutput.innerHTML = output.length > 0
|
| 345 |
-
? output.join('\n')
|
| 346 |
-
: 'Code executed successfully (no output)';
|
| 347 |
-
} catch (error) {
|
| 348 |
-
elements.codeOutput.innerHTML = `Error: ${error.message}`;
|
| 349 |
}
|
| 350 |
}
|
| 351 |
-
|
| 352 |
-
// Run Python code (mock)
|
| 353 |
-
function runPython(code) {
|
| 354 |
-
elements.codeOutput.innerHTML = `Python execution would require a backend server.\n\nCode to run:\n${code}`;
|
| 355 |
-
}
|
| 356 |
-
|
| 357 |
-
// Run HTML code
|
| 358 |
-
function runHTML(code) {
|
| 359 |
-
const newWindow = window.open('', '_blank');
|
| 360 |
-
newWindow.document.write(code);
|
| 361 |
-
newWindow.document.close();
|
| 362 |
-
elements.codeOutput.innerHTML = 'HTML opened in new window';
|
| 363 |
-
}
|
| 364 |
// Read file as text
|
| 365 |
function readFileAsText(file) {
|
| 366 |
return new Promise((resolve, reject) => {
|
|
@@ -394,25 +192,24 @@ function startVoiceInput() {
|
|
| 394 |
showError('Voice input error: ' + event.error);
|
| 395 |
};
|
| 396 |
}
|
| 397 |
-
|
| 398 |
// Start analysis workflow
|
| 399 |
async function startAnalysis() {
|
| 400 |
if (state.isProcessing) return;
|
| 401 |
|
| 402 |
if (!state.processedText) {
|
| 403 |
-
showError('Please
|
| 404 |
return;
|
| 405 |
}
|
| 406 |
|
| 407 |
const problem = elements.problemInput.value.trim();
|
| 408 |
if (!problem) {
|
| 409 |
-
showError('Please describe the problem.');
|
| 410 |
return;
|
| 411 |
}
|
| 412 |
|
| 413 |
state.isProcessing = true;
|
| 414 |
elements.startAnalysis.disabled = true;
|
| 415 |
-
elements.startAnalysis.textContent = 'Analyzing...';
|
| 416 |
|
| 417 |
try {
|
| 418 |
// Reset progress
|
|
@@ -421,79 +218,195 @@ async function startAnalysis() {
|
|
| 421 |
elements.resultsContainer.classList.add('hidden');
|
| 422 |
elements.errorContainer.classList.add('hidden');
|
| 423 |
|
| 424 |
-
// Phase 1:
|
| 425 |
-
updateProgress('qwen', 30, 'Analyzing...');
|
| 426 |
state.qwenResponse = await simulateQwenAnalysis(problem, state.processedText);
|
| 427 |
-
updateProgress('qwen', 100, '
|
| 428 |
|
| 429 |
-
// Phase 2:
|
| 430 |
-
updateProgress('zai', 30, '
|
| 431 |
state.zaiResponse = await simulateZAICorrection(state.qwenResponse);
|
| 432 |
-
updateProgress('zai', 100, '
|
| 433 |
|
| 434 |
-
// Parse
|
| 435 |
const correctedFiles = parseZAIFiles(state.zaiResponse);
|
| 436 |
renderResults(correctedFiles);
|
| 437 |
|
| 438 |
-
showNotification(
|
| 439 |
} catch (error) {
|
| 440 |
showError('Analysis failed: ' + error.message);
|
| 441 |
} finally {
|
| 442 |
state.isProcessing = false;
|
| 443 |
elements.startAnalysis.disabled = false;
|
| 444 |
-
elements.startAnalysis.textContent = '
|
| 445 |
}
|
| 446 |
}
|
| 447 |
-
|
| 448 |
-
// Simulate Qwen analysis (in a real app, this would interact with the AI)
|
| 449 |
function simulateQwenAnalysis(problem, projectText) {
|
| 450 |
return new Promise((resolve) => {
|
| 451 |
setTimeout(() => {
|
| 452 |
-
|
|
|
|
|
|
|
| 453 |
Problem: ${problem}
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 457 |
});
|
| 458 |
}
|
| 459 |
|
| 460 |
-
// Simulate
|
| 461 |
-
function simulateZAICorrection(
|
| 462 |
return new Promise((resolve) => {
|
| 463 |
setTimeout(() => {
|
| 464 |
-
|
| 465 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 466 |
|
| 467 |
-
function
|
| 468 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 469 |
}
|
| 470 |
|
| 471 |
-
//
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 475 |
}
|
| 476 |
-
|
| 477 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 478 |
|
| 479 |
src/utils.js
|
| 480 |
-
"//
|
| 481 |
-
function
|
| 482 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 483 |
}
|
| 484 |
|
| 485 |
function debounce(func, wait) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 486 |
let timeout;
|
| 487 |
return function executedFunction(...args) {
|
| 488 |
const later = () => {
|
| 489 |
clearTimeout(timeout);
|
| 490 |
-
func(
|
| 491 |
};
|
| 492 |
clearTimeout(timeout);
|
| 493 |
timeout = setTimeout(later, wait);
|
| 494 |
};
|
| 495 |
-
}
|
| 496 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 497 |
});
|
| 498 |
}
|
| 499 |
// Parse ZAI response into file objects
|
|
@@ -514,7 +427,6 @@ function parseZAIFiles(response) {
|
|
| 514 |
|
| 515 |
return files;
|
| 516 |
}
|
| 517 |
-
|
| 518 |
// Apply changes to the original project
|
| 519 |
function applyChangesToProject() {
|
| 520 |
if (!state.correctedFiles || state.correctedFiles.length === 0) {
|
|
@@ -525,26 +437,9 @@ function applyChangesToProject() {
|
|
| 525 |
// Apply corrected content to the file contents map
|
| 526 |
state.correctedFiles.forEach(file => {
|
| 527 |
state.fileContents.set(file.path, file.content);
|
| 528 |
-
|
| 529 |
-
// If this file is currently in the editor, update it
|
| 530 |
-
if (state.currentFile === file.path) {
|
| 531 |
-
elements.codeEditor.value = file.content;
|
| 532 |
-
}
|
| 533 |
});
|
| 534 |
|
| 535 |
-
|
| 536 |
-
const selectedPath = elements.fileSelector.value;
|
| 537 |
-
setupFileSelector(Array.from(state.fileContents.keys()).map(path => ({
|
| 538 |
-
name: path,
|
| 539 |
-
selected: true
|
| 540 |
-
})));
|
| 541 |
-
|
| 542 |
-
if (selectedPath) {
|
| 543 |
-
elements.fileSelector.value = selectedPath;
|
| 544 |
-
loadFileContent();
|
| 545 |
-
}
|
| 546 |
-
|
| 547 |
-
showNotification('Changes applied to project successfully!', 'success');
|
| 548 |
}
|
| 549 |
// Render results
|
| 550 |
function renderResults(files) {
|
|
@@ -604,17 +499,13 @@ function downloadFile(path, content) {
|
|
| 604 |
// Download all files
|
| 605 |
async function downloadAllFiles() {
|
| 606 |
if (state.correctedFiles && state.correctedFiles.length > 0) {
|
| 607 |
-
// Download corrected files
|
| 608 |
state.correctedFiles.forEach(file => {
|
| 609 |
downloadFile(file.path, file.content);
|
| 610 |
});
|
| 611 |
-
showNotification(
|
| 612 |
} else {
|
| 613 |
-
|
| 614 |
-
state.fileContents.forEach((content, path) => {
|
| 615 |
-
downloadFile(path, content);
|
| 616 |
-
});
|
| 617 |
-
showNotification('Downloaded current project files', 'success');
|
| 618 |
}
|
| 619 |
}
|
| 620 |
// Show notification
|
|
|
|
| 7 |
qwenResponse: '',
|
| 8 |
zaiResponse: '',
|
| 9 |
correctedFiles: [],
|
|
|
|
| 10 |
isProcessing: false
|
| 11 |
};
|
| 12 |
// DOM Elements
|
|
|
|
| 14 |
dropZone: document.getElementById('drop-zone'),
|
| 15 |
fileInput: document.getElementById('file-input'),
|
| 16 |
browseBtn: document.getElementById('browse-btn'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
problemInput: document.getElementById('problem-input'),
|
| 18 |
voiceBtn: document.getElementById('voice-btn'),
|
| 19 |
startAnalysis: document.getElementById('start-analysis'),
|
|
|
|
| 25 |
fileList: document.getElementById('file-list'),
|
| 26 |
downloadAll: document.getElementById('download-all'),
|
| 27 |
applyChanges: document.getElementById('apply-changes'),
|
|
|
|
|
|
|
| 28 |
errorContainer: document.getElementById('error-container')
|
| 29 |
};
|
| 30 |
// Initialize the app
|
| 31 |
document.addEventListener('DOMContentLoaded', () => {
|
| 32 |
setupEventListeners();
|
| 33 |
});
|
|
|
|
| 34 |
// Set up event listeners
|
| 35 |
function setupEventListeners() {
|
| 36 |
// File upload
|
|
|
|
| 38 |
elements.dropZone.addEventListener('dragover', handleDragOver);
|
| 39 |
elements.dropZone.addEventListener('drop', handleDrop);
|
| 40 |
elements.fileInput.addEventListener('change', handleFileSelect);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
// Voice input
|
| 43 |
elements.voiceBtn.addEventListener('click', startVoiceInput);
|
|
|
|
| 49 |
elements.downloadAll.addEventListener('click', downloadAllFiles);
|
| 50 |
elements.applyChanges.addEventListener('click', applyChangesToProject);
|
| 51 |
}
|
|
|
|
| 52 |
// File handling functions
|
| 53 |
function handleDragOver(e) {
|
| 54 |
e.preventDefault();
|
|
|
|
| 73 |
processDirectoryFiles(files);
|
| 74 |
}
|
| 75 |
}
|
|
|
|
| 76 |
// Process directory items from drag and drop
|
| 77 |
function processDirectoryItems(items) {
|
| 78 |
state.files = [];
|
|
|
|
| 84 |
}
|
| 85 |
}
|
| 86 |
|
| 87 |
+
// Process files automatically after a short delay
|
| 88 |
setTimeout(() => {
|
| 89 |
+
processAllFiles();
|
|
|
|
| 90 |
}, 500);
|
| 91 |
}
|
|
|
|
| 92 |
// Process directory files from file input
|
| 93 |
function processDirectoryFiles(files) {
|
| 94 |
state.files = Array.from(files).map(file => ({
|
|
|
|
| 98 |
selected: true
|
| 99 |
}));
|
| 100 |
|
| 101 |
+
// Process files automatically
|
| 102 |
+
processAllFiles();
|
| 103 |
}
|
|
|
|
| 104 |
// Traverse file tree (for drag and drop)
|
| 105 |
function traverseFileTree(item, path = '') {
|
| 106 |
if (item.isFile) {
|
|
|
|
| 122 |
});
|
| 123 |
}
|
| 124 |
}
|
| 125 |
+
// Process all files automatically
|
| 126 |
+
async function processAllFiles() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
try {
|
| 128 |
+
// Filter to only include files (not directories)
|
| 129 |
+
const fileObjects = state.files.filter(f => !f.isDirectory);
|
| 130 |
|
| 131 |
// Sort files alphabetically
|
| 132 |
+
fileObjects.sort((a, b) => a.name.localeCompare(b.name));
|
| 133 |
|
| 134 |
// Process each file
|
| 135 |
const fileContents = [];
|
| 136 |
+
for (const fileObj of fileObjects) {
|
| 137 |
try {
|
| 138 |
const content = await readFileAsText(fileObj.file);
|
| 139 |
fileContents.push({
|
|
|
|
| 147 |
}
|
| 148 |
}
|
| 149 |
|
| 150 |
+
// Generate structured text output for AI analysis
|
| 151 |
let output = '';
|
| 152 |
for (const fileContent of fileContents) {
|
| 153 |
output += `${fileContent.path}\n"${fileContent.content}"\n\n`;
|
| 154 |
}
|
| 155 |
|
| 156 |
state.processedText = output;
|
| 157 |
+
showNotification('Files processed and ready for AI analysis!', 'success');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
} catch (error) {
|
| 159 |
showError('Error processing files: ' + error.message);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
}
|
| 161 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
// Read file as text
|
| 163 |
function readFileAsText(file) {
|
| 164 |
return new Promise((resolve, reject) => {
|
|
|
|
| 192 |
showError('Voice input error: ' + event.error);
|
| 193 |
};
|
| 194 |
}
|
|
|
|
| 195 |
// Start analysis workflow
|
| 196 |
async function startAnalysis() {
|
| 197 |
if (state.isProcessing) return;
|
| 198 |
|
| 199 |
if (!state.processedText) {
|
| 200 |
+
showError('Please upload your project first.');
|
| 201 |
return;
|
| 202 |
}
|
| 203 |
|
| 204 |
const problem = elements.problemInput.value.trim();
|
| 205 |
if (!problem) {
|
| 206 |
+
showError('Please describe the problem you want to fix.');
|
| 207 |
return;
|
| 208 |
}
|
| 209 |
|
| 210 |
state.isProcessing = true;
|
| 211 |
elements.startAnalysis.disabled = true;
|
| 212 |
+
elements.startAnalysis.textContent = 'AI Analyzing & Fixing...';
|
| 213 |
|
| 214 |
try {
|
| 215 |
// Reset progress
|
|
|
|
| 218 |
elements.resultsContainer.classList.add('hidden');
|
| 219 |
elements.errorContainer.classList.add('hidden');
|
| 220 |
|
| 221 |
+
// Phase 1: AI Analysis - Find problematic files
|
| 222 |
+
updateProgress('qwen', 30, 'Analyzing project structure...');
|
| 223 |
state.qwenResponse = await simulateQwenAnalysis(problem, state.processedText);
|
| 224 |
+
updateProgress('qwen', 100, 'Files identified');
|
| 225 |
|
| 226 |
+
// Phase 2: AI Correction - Fix the issues
|
| 227 |
+
updateProgress('zai', 30, 'Applying fixes...');
|
| 228 |
state.zaiResponse = await simulateZAICorrection(state.qwenResponse);
|
| 229 |
+
updateProgress('zai', 100, 'Corrections complete');
|
| 230 |
|
| 231 |
+
// Parse AI response into corrected files
|
| 232 |
const correctedFiles = parseZAIFiles(state.zaiResponse);
|
| 233 |
renderResults(correctedFiles);
|
| 234 |
|
| 235 |
+
showNotification(`AI successfully identified and fixed issues in ${correctedFiles.length} file(s)!`, 'success');
|
| 236 |
} catch (error) {
|
| 237 |
showError('Analysis failed: ' + error.message);
|
| 238 |
} finally {
|
| 239 |
state.isProcessing = false;
|
| 240 |
elements.startAnalysis.disabled = false;
|
| 241 |
+
elements.startAnalysis.textContent = 'AI Automatic Analysis & Fix';
|
| 242 |
}
|
| 243 |
}
|
| 244 |
+
// Simulate AI analysis (in a real app, this would interact with the AI)
|
|
|
|
| 245 |
function simulateQwenAnalysis(problem, projectText) {
|
| 246 |
return new Promise((resolve) => {
|
| 247 |
setTimeout(() => {
|
| 248 |
+
// AI analyzes the project and identifies which files need fixing
|
| 249 |
+
const analysisResult = `
|
| 250 |
+
AI Analysis Complete:
|
| 251 |
Problem: ${problem}
|
| 252 |
+
|
| 253 |
+
Files requiring attention:
|
| 254 |
+
- src/main.js: Contains potential undefined variable errors
|
| 255 |
+
- src/app.js: Missing error handling in async functions
|
| 256 |
+
- src/utils.js: Functions need better parameter validation
|
| 257 |
+
- package.json: Missing required dependencies
|
| 258 |
+
|
| 259 |
+
Recommended fixes:
|
| 260 |
+
1. Add proper error boundaries
|
| 261 |
+
2. Implement input validation
|
| 262 |
+
3. Fix async/await patterns
|
| 263 |
+
4. Update dependencies
|
| 264 |
+
`;
|
| 265 |
+
resolve(analysisResult);
|
| 266 |
+
}, 2500);
|
| 267 |
});
|
| 268 |
}
|
| 269 |
|
| 270 |
+
// Simulate AI correction (in a real app, this would interact with the AI)
|
| 271 |
+
function simulateZAICorrection(analysisResult) {
|
| 272 |
return new Promise((resolve) => {
|
| 273 |
setTimeout(() => {
|
| 274 |
+
// AI generates the corrected code for the identified files
|
| 275 |
+
const correctedCode = `
|
| 276 |
+
src/main.js
|
| 277 |
+
"// Fixed version with proper error handling
|
| 278 |
+
console.log('Application starting...');
|
| 279 |
+
|
| 280 |
+
let appConfig = {
|
| 281 |
+
apiUrl: process.env.API_URL || 'http://localhost:3000',
|
| 282 |
+
debug: process.env.NODE_ENV === 'development'
|
| 283 |
+
};
|
| 284 |
|
| 285 |
+
function initializeApp() {
|
| 286 |
+
try {
|
| 287 |
+
if (!appConfig.apiUrl) {
|
| 288 |
+
throw new Error('API URL is required');
|
| 289 |
+
}
|
| 290 |
+
|
| 291 |
+
console.log('App initialized successfully');
|
| 292 |
+
return true;
|
| 293 |
+
} catch (error) {
|
| 294 |
+
console.error('Failed to initialize app:', error.message);
|
| 295 |
+
return false;
|
| 296 |
+
}
|
| 297 |
}
|
| 298 |
|
| 299 |
+
// Auto-initialize
|
| 300 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 301 |
+
initializeApp();
|
| 302 |
+
});"
|
| 303 |
+
|
| 304 |
+
src/app.js
|
| 305 |
+
"// Fixed async functions with proper error handling
|
| 306 |
+
class App {
|
| 307 |
+
constructor() {
|
| 308 |
+
this.data = [];
|
| 309 |
+
this.isLoading = false;
|
| 310 |
}
|
| 311 |
+
|
| 312 |
+
async fetchData(url) {
|
| 313 |
+
if (!url) {
|
| 314 |
+
throw new Error('URL is required');
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
this.isLoading = true;
|
| 318 |
+
try {
|
| 319 |
+
const response = await fetch(url);
|
| 320 |
+
|
| 321 |
+
if (!response.ok) {
|
| 322 |
+
throw new Error(\`HTTP error! status: \${response.status}\`);
|
| 323 |
+
}
|
| 324 |
+
|
| 325 |
+
const data = await response.json();
|
| 326 |
+
this.data = data;
|
| 327 |
+
return data;
|
| 328 |
+
} catch (error) {
|
| 329 |
+
console.error('Failed to fetch data:', error);
|
| 330 |
+
throw error;
|
| 331 |
+
} finally {
|
| 332 |
+
this.isLoading = false;
|
| 333 |
+
}
|
| 334 |
+
}
|
| 335 |
+
|
| 336 |
+
async processData() {
|
| 337 |
+
try {
|
| 338 |
+
if (this.data.length === 0) {
|
| 339 |
+
console.warn('No data to process');
|
| 340 |
+
return [];
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
return this.data.map(item => ({
|
| 344 |
+
...item,
|
| 345 |
+
processed: true,
|
| 346 |
+
timestamp: new Date().toISOString()
|
| 347 |
+
}));
|
| 348 |
+
} catch (error) {
|
| 349 |
+
console.error('Processing failed:', error);
|
| 350 |
+
throw error;
|
| 351 |
+
}
|
| 352 |
+
}
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
export default App;"
|
| 356 |
|
| 357 |
src/utils.js
|
| 358 |
+
"// Fixed utility functions with parameter validation
|
| 359 |
+
function formatFileSize(bytes) {
|
| 360 |
+
if (typeof bytes !== 'number' || bytes < 0) {
|
| 361 |
+
throw new Error('Bytes must be a non-negative number');
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
if (bytes === 0) return '0 Bytes';
|
| 365 |
+
|
| 366 |
+
const k = 1024;
|
| 367 |
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
| 368 |
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
| 369 |
+
|
| 370 |
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
| 371 |
}
|
| 372 |
|
| 373 |
function debounce(func, wait) {
|
| 374 |
+
if (typeof func !== 'function') {
|
| 375 |
+
throw new Error('First argument must be a function');
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
if (typeof wait !== 'number' || wait < 0) {
|
| 379 |
+
throw new Error('Wait time must be a non-negative number');
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
let timeout;
|
| 383 |
return function executedFunction(...args) {
|
| 384 |
const later = () => {
|
| 385 |
clearTimeout(timeout);
|
| 386 |
+
func.apply(this, args);
|
| 387 |
};
|
| 388 |
clearTimeout(timeout);
|
| 389 |
timeout = setTimeout(later, wait);
|
| 390 |
};
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
function validateEmail(email) {
|
| 394 |
+
if (typeof email !== 'string') {
|
| 395 |
+
return false;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
|
| 399 |
+
return emailRegex.test(email);
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
module.exports = {
|
| 403 |
+
formatFileSize,
|
| 404 |
+
debounce,
|
| 405 |
+
validateEmail
|
| 406 |
+
};"
|
| 407 |
+
`;
|
| 408 |
+
resolve(correctedCode);
|
| 409 |
+
}, 3500);
|
| 410 |
});
|
| 411 |
}
|
| 412 |
// Parse ZAI response into file objects
|
|
|
|
| 427 |
|
| 428 |
return files;
|
| 429 |
}
|
|
|
|
| 430 |
// Apply changes to the original project
|
| 431 |
function applyChangesToProject() {
|
| 432 |
if (!state.correctedFiles || state.correctedFiles.length === 0) {
|
|
|
|
| 437 |
// Apply corrected content to the file contents map
|
| 438 |
state.correctedFiles.forEach(file => {
|
| 439 |
state.fileContents.set(file.path, file.content);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 440 |
});
|
| 441 |
|
| 442 |
+
showNotification(`AI corrections applied to ${state.correctedFiles.length} file(s)!`, 'success');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 443 |
}
|
| 444 |
// Render results
|
| 445 |
function renderResults(files) {
|
|
|
|
| 499 |
// Download all files
|
| 500 |
async function downloadAllFiles() {
|
| 501 |
if (state.correctedFiles && state.correctedFiles.length > 0) {
|
| 502 |
+
// Download only the corrected files
|
| 503 |
state.correctedFiles.forEach(file => {
|
| 504 |
downloadFile(file.path, file.content);
|
| 505 |
});
|
| 506 |
+
showNotification(`Downloaded ${state.correctedFiles.length} AI-corrected file(s)`, 'success');
|
| 507 |
} else {
|
| 508 |
+
showError('No corrected files available for download');
|
|
|
|
|
|
|
|
|
|
|
|
|
| 509 |
}
|
| 510 |
}
|
| 511 |
// Show notification
|