From affb55df4300d02ae299ce46d50bf634145b30bf Mon Sep 17 00:00:00 2001 From: Muyue Date: Sat, 18 Oct 2025 23:44:31 +0200 Subject: [PATCH] Add section deletion and simplify working agent display - Add deleteSection() method to collaborativeOrchestrator.js for removing sections by header - Enable IAs to delete sections with 'DELETE: ## Section Name' format - Modify mistralClient.js prompt to include deletion instructions - Simplify working agent card UI: show only raised hand animation + agent name - Remove thinking content display from working agent card for cleaner UX --- .../src/services/collaborativeOrchestrator.js | 65 +++++++++++++++--- backend/src/services/mistralClient.js | 15 +++-- .../src/components/CollaborativeSession.vue | 67 +++---------------- 3 files changed, 75 insertions(+), 72 deletions(-) diff --git a/backend/src/services/collaborativeOrchestrator.js b/backend/src/services/collaborativeOrchestrator.js index e7b3056..3b6caae 100644 --- a/backend/src/services/collaborativeOrchestrator.js +++ b/backend/src/services/collaborativeOrchestrator.js @@ -198,21 +198,33 @@ class CollaborativeOrchestrator { // Check if agent made changes if (section !== 'Section is good, no changes needed' && !section.includes('no changes needed')) { - // Merge section into document const docBefore = session.currentDocument - const updatedDocument = this.mergeSection(session.currentDocument, section) + let updatedDocument = docBefore + let action = '' + let headerText = '' - if (updatedDocument !== session.currentDocument) { + // Check if it's a DELETE command + if (section.startsWith('DELETE:')) { + const deleteMatch = section.match(/DELETE:\s*(.+)/m) + if (deleteMatch) { + headerText = deleteMatch[1].trim() + updatedDocument = this.deleteSection(docBefore, headerText) + action = 'DELETED SECTION' + } + } else { + // Modify or create section + updatedDocument = this.mergeSection(docBefore, section) + const sectionHeader = section.match(/^(#+)\s+(.+)/m) + headerText = sectionHeader ? sectionHeader[2] : 'Unknown' + const isNewSection = !docBefore.includes(headerText) + action = isNewSection ? 'CREATED NEW SECTION' : 'MODIFIED' + } + + if (updatedDocument !== docBefore) { session.currentDocument = updatedDocument session.versionNumber++ modifiedAgents.push(agentName) - // Check if it's a new section or modification - const sectionHeader = section.match(/^(#+)\s+(.+)/m) - const headerText = sectionHeader ? sectionHeader[2] : 'Unknown' - const isNewSection = !docBefore.includes(headerText) - const action = isNewSection ? 'CREATED NEW SECTION' : 'MODIFIED' - console.log(`[Session ${sessionId}] ✓ ${agentName} ${action}: "${headerText}"`) console.log(`[Session ${sessionId}] Document updated: v${session.versionNumber - 1} → v${session.versionNumber} (${docBefore.length} → ${updatedDocument.length} chars)`) console.log(`[Session ${sessionId}] ===== BEFORE (v${session.versionNumber - 1}) =====`) @@ -243,7 +255,7 @@ class CollaborativeOrchestrator { roundNumber }) } else { - console.log(`[Session ${sessionId}] Round ${roundNumber}: ${agentName} - section proposed but no actual changes merged`) + console.log(`[Session ${sessionId}] Round ${roundNumber}: ${agentName} - change proposed but no actual changes made`) } } else { console.log(`[Session ${sessionId}] Round ${roundNumber}: ${agentName} - no changes needed`) @@ -341,6 +353,39 @@ class CollaborativeOrchestrator { } } + /** + * Delete a section from the document by its header text + */ + deleteSection(document, headerText) { + if (!document || !headerText) return document + + // Find the header in the document to determine its level + const headerRegex = new RegExp(`^(#{1,4})\\s+${headerText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`, 'gm') + const match = document.match(headerRegex) + + if (!match) return document + + // Extract the header level + const headerMatch = match[0].match(/^#{1,4}/) + if (!headerMatch) return document + + const headerLevel = headerMatch[0].length + + // Create regex to match this section and everything until the next section of same or higher level + const sectionRegex = new RegExp( + `^${'#'.repeat(headerLevel)}\\s+${headerText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:\\n(?!^#{1,${headerLevel}}\\s+)[\\s\\S])*`, + 'gm' + ) + + // Remove the section + let updated = document.replace(sectionRegex, '').trim() + + // Clean up extra blank lines + updated = updated.replace(/\n\n\n+/g, '\n\n') + + return updated + } + /** * Complete a session */ diff --git a/backend/src/services/mistralClient.js b/backend/src/services/mistralClient.js index 9daf011..2913c37 100644 --- a/backend/src/services/mistralClient.js +++ b/backend/src/services/mistralClient.js @@ -16,24 +16,27 @@ Your responsibilities: 1. Review the current document structure 2. Either: a) Modify ONE existing section (identified by #, ##, ###, #### headers), OR - b) Create a NEW section if you think it's needed + b) Create a NEW section if you think it's needed, OR + c) Delete a section if you think it's redundant or not useful 3. Provide your thinking process and reasoning -4. Return ONLY the section (modified or new) with its header, or confirm it's good as-is +4. Return ONLY the section (modified or new) with its header, or command to delete, or confirm it's good as-is IMPORTANT RULES: - Work on exactly ONE section only - Never modify the entire document - Return only the section you're working on, not the whole document -- You CAN create a new section if you think the document is missing important content +- You CAN create a new section if document is missing important content +- You CAN delete a section if it's redundant, duplicate, or not useful +- To delete a section, respond: "DELETE: ## Section Name" (with exact header) - If section is good, respond: "Section is good, no changes needed" -- Think step-by-step about what could be improved +- Think step-by-step about what could be improved or removed - Share your reasoning process Format your response as: THINKING: [Your analysis and reasoning] -DECISION: [What you'll modify, create, or if keeping as-is] +DECISION: [What you'll modify, create, delete, or if keeping as-is] SECTION: -[The modified section, new section, or confirmation that all is good]` +[The modified section, new section, DELETE command, or confirmation that all is good]` } /** diff --git a/frontend/src/components/CollaborativeSession.vue b/frontend/src/components/CollaborativeSession.vue index 18a6d8f..67693d0 100644 --- a/frontend/src/components/CollaborativeSession.vue +++ b/frontend/src/components/CollaborativeSession.vue @@ -225,20 +225,10 @@ function formatAgentName(agent) {
-
-
- -
-
-

{{ formatAgentName(currentWorkingAgent) }}

-

is reviewing...

-
-
- -
-

Thinking:

-

{{ currentAgentThinking }}

+
+
+
{{ formatAgentName(currentWorkingAgent) }}
@@ -435,67 +425,32 @@ function formatAgentName(agent) { } .working-agent-card { - padding: 1.5rem; + display: flex; + align-items: center; + gap: 1rem; + padding: 1rem 1.5rem; background: rgba(102, 126, 234, 0.1); border: 2px solid rgba(102, 126, 234, 0.4); border-radius: 16px; backdrop-filter: blur(10px); } -.working-agent-header { - display: flex; - align-items: center; - gap: 1rem; - margin-bottom: 1rem; -} - .raised-hand-animation { display: flex; align-items: center; justify-content: center; - width: 60px; - height: 60px; - background: rgba(102, 126, 234, 0.2); - border-radius: 50%; + flex-shrink: 0; } .hand { - font-size: 2rem; + font-size: 2.5rem; animation: raise-hand 1s infinite; } -.agent-name-display h3 { - margin: 0; - font-size: 1.3rem; +.agent-name-working { + font-size: 1.2rem; color: rgba(102, 126, 234, 0.95); -} - -.agent-label { - margin: 0.25rem 0 0 0; - font-size: 0.85rem; - color: rgba(255, 255, 255, 0.6); -} - -.agent-thinking { - padding: 1rem; - background: rgba(0, 0, 0, 0.2); - border-radius: 10px; -} - -.thinking-label { - margin: 0 0 0.5rem 0; - font-size: 0.85rem; font-weight: 600; - color: rgba(102, 126, 234, 0.9); - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.thinking-content { - margin: 0; - font-size: 0.95rem; - color: rgba(255, 255, 255, 0.8); - line-height: 1.5; } .convergence-message {