Compare commits

..

No commits in common. "10ccae24306c79d3d3d5ec61a20ded24a5e374fc" and "68cf310f0cbc4798a3f809f0328eef14456a3f20" have entirely different histories.

4 changed files with 99 additions and 81 deletions

View File

@ -82,7 +82,7 @@ class CollaborativeOrchestrator {
} }
/** /**
* Start a session - SYSTEM creates base structure, then Round 1 begins with Agent 1 * Start a session - create initial document with first agent
*/ */
async startSession(sessionId) { async startSession(sessionId) {
try { try {
@ -91,23 +91,27 @@ class CollaborativeOrchestrator {
console.log(`[Session ${sessionId}] Starting session with ${session.agents.length} agents: ${session.agents.join(', ')}`) console.log(`[Session ${sessionId}] Starting session with ${session.agents.length} agents: ${session.agents.join(', ')}`)
// STEP 1: SYSTEM creates base structure (not an AI agent) const firstAgent = session.agents[0]
console.log(`[Session ${sessionId}] [SYSTEM] Creating base document structure...`) console.log(`[Session ${sessionId}] ${firstAgent} creating initial document...`)
const baseStructure = `# ${session.initialPrompt.split('\n')[0] || 'Project Overview'}\n\nThis document will be collaboratively developed by ${session.agents.length} AI specialists.`
console.log(`[Session ${sessionId}] [SYSTEM] Base structure created (${baseStructure.length} chars)`) // Generate initial document
console.log(`[Session ${sessionId}] ===== BASE STRUCTURE (v0) =====`) const initialResponse = await generateAgentResponseSync(
console.log(baseStructure) firstAgent,
console.log(`[Session ${sessionId}] ===== END BASE STRUCTURE =====`) session.initialPrompt,
''
)
// Save base structure to DB const initialDocument = extractSection(initialResponse)
const thinking = extractThinking(initialResponse)
// Save to DB
const insertStmt = db.prepare( const insertStmt = db.prepare(
'INSERT INTO document_versions (session_id, version_number, content, modified_by, modification_reason, round_number) VALUES (?, ?, ?, ?, ?, ?)' 'INSERT INTO document_versions (session_id, version_number, content, modified_by, modification_reason, round_number) VALUES (?, ?, ?, ?, ?, ?)'
) )
insertStmt.run(sessionId, 0, baseStructure, 'SYSTEM', 'Base structure creation', 0) insertStmt.run(sessionId, 0, initialDocument, firstAgent, 'Initial document creation', 0)
// Update session // Update session
session.currentDocument = baseStructure session.currentDocument = initialDocument
session.versionNumber = 0 session.versionNumber = 0
session.started = true session.started = true
session.consecutiveNoChanges = 0 session.consecutiveNoChanges = 0
@ -116,17 +120,22 @@ class CollaborativeOrchestrator {
const updateStmt = db.prepare('UPDATE collaborative_sessions SET status = ? WHERE id = ?') const updateStmt = db.prepare('UPDATE collaborative_sessions SET status = ? WHERE id = ?')
updateStmt.run('ongoing', sessionId) updateStmt.run('ongoing', sessionId)
// Broadcast base structure console.log(`[Session ${sessionId}] Initial document created (${initialDocument.length} chars)`)
console.log(`[Session ${sessionId}] ===== INITIAL DOCUMENT =====`)
console.log(initialDocument)
console.log(`[Session ${sessionId}] ===== END INITIAL DOCUMENT =====`)
// Broadcast initial document
this.broadcast(sessionId, { this.broadcast(sessionId, {
type: 'initial_document_created', type: 'initial_document_created',
content: baseStructure, content: initialDocument,
agentName: 'SYSTEM', agentName: firstAgent,
thinking: 'Created base structure for collaboration', thinking,
roundNumber: 0 roundNumber: 0
}) })
console.log(`[Session ${sessionId}] Base structure ready. Scheduling Round 1 in 2s...`) console.log(`[Session ${sessionId}] Scheduling first round in 2s...`)
// Auto-start first round with all agents // Auto-start first round
setTimeout(() => this.runRound(sessionId), 2000) setTimeout(() => this.runRound(sessionId), 2000)
} catch (error) { } catch (error) {
console.error('Error starting session:', error) console.error('Error starting session:', error)
@ -151,17 +160,11 @@ class CollaborativeOrchestrator {
console.log(`[Session ${sessionId}] ===== ROUND ${roundNumber} START =====`) console.log(`[Session ${sessionId}] ===== ROUND ${roundNumber} START =====`)
// Each agent reviews the document SEQUENTIALLY, receiving the updated version from the previous agent // Each agent reviews the document
for (let i = 0; i < agentsInRound.length; i++) { for (let i = 0; i < agentsInRound.length; i++) {
const agentName = agentsInRound[i] const agentName = agentsInRound[i]
const documentVersion = session.versionNumber
// STEP: Agent receives current document state console.log(`[Session ${sessionId}] Round ${roundNumber}: ${agentName} reviewing...`)
console.log(`[Session ${sessionId}] Round ${roundNumber}: AGENT ${i + 1}/${agentsInRound.length} - ${agentName}`)
console.log(`[Session ${sessionId}] ${agentName} receives document v${documentVersion} (${session.currentDocument.length} chars)`)
console.log(`[Session ${sessionId}] ===== DOCUMENT SEEN BY ${agentName} (v${documentVersion}) =====`)
console.log(session.currentDocument)
console.log(`[Session ${sessionId}] ===== END DOCUMENT SEEN BY ${agentName} =====`)
// Broadcast that this agent is working // Broadcast that this agent is working
this.broadcast(sessionId, { this.broadcast(sessionId, {
@ -171,22 +174,21 @@ class CollaborativeOrchestrator {
}) })
try { try {
console.log(`[Session ${sessionId}] ${agentName} analyzing and generating response...`)
const response = await generateAgentResponseSync( const response = await generateAgentResponseSync(
agentName, agentName,
session.initialPrompt, session.initialPrompt,
session.currentDocument // <-- This is always the latest version session.currentDocument
) )
const thinking = extractThinking(response) const thinking = extractThinking(response)
const section = extractSection(response) const section = extractSection(response)
console.log(`[Session ${sessionId}] ${agentName} response received (${response.length} chars)`) console.log(`[Session ${sessionId}] Round ${roundNumber}: ${agentName} response received (${response.length} chars)`)
console.log(`[Session ${sessionId}] --- THINKING (${agentName}) ---`) console.log(`[Session ${sessionId}] --- THINKING ---`)
console.log(thinking) console.log(thinking)
console.log(`[Session ${sessionId}] --- SECTION (${agentName}) ---`) console.log(`[Session ${sessionId}] --- SECTION ---`)
console.log(section) console.log(section)
console.log(`[Session ${sessionId}] --- END RESPONSE (${agentName}) ---`) console.log(`[Session ${sessionId}] --- END RESPONSE ---`)
// Broadcast agent's thinking in real-time // Broadcast agent's thinking in real-time
this.broadcast(sessionId, { this.broadcast(sessionId, {
@ -213,13 +215,12 @@ class CollaborativeOrchestrator {
const isNewSection = !docBefore.includes(headerText) const isNewSection = !docBefore.includes(headerText)
const action = isNewSection ? 'CREATED NEW SECTION' : 'MODIFIED' const action = isNewSection ? 'CREATED NEW SECTION' : 'MODIFIED'
console.log(`[Session ${sessionId}] ✓ ${agentName} ${action}: "${headerText}"`) console.log(`[Session ${sessionId}] Round ${roundNumber}: ${agentName} ${action}: "${headerText}" (v${session.versionNumber})`)
console.log(`[Session ${sessionId}] Document updated: v${session.versionNumber - 1} → v${session.versionNumber} (${docBefore.length}${updatedDocument.length} chars)`) console.log(`[Session ${sessionId}] ===== DOCUMENT BEFORE (v${session.versionNumber - 1}) =====`)
console.log(`[Session ${sessionId}] ===== BEFORE (v${session.versionNumber - 1}) =====`)
console.log(docBefore) console.log(docBefore)
console.log(`[Session ${sessionId}] ===== AFTER (v${session.versionNumber}) [${agentName}] =====`) console.log(`[Session ${sessionId}] ===== DOCUMENT AFTER (v${session.versionNumber}) =====`)
console.log(updatedDocument) console.log(updatedDocument)
console.log(`[Session ${sessionId}] ===== END CHANGE =====`) console.log(`[Session ${sessionId}] ===== END DOCUMENT =====`)
// Save version to DB // Save version to DB
const insertStmt = db.prepare( const insertStmt = db.prepare(

View File

@ -48,7 +48,7 @@ function startNewCollaboration() {
<CollaborativeSession <CollaborativeSession
v-if="currentSessionId" v-if="currentSessionId"
:session-id="currentSessionId" :session-id="currentSessionId"
@go-home="startNewCollaboration" @session-completed="startNewCollaboration"
/> />
</div> </div>
</div> </div>

View File

@ -12,7 +12,7 @@ const props = defineProps({
} }
}) })
const emit = defineEmits(['go-home']) const emit = defineEmits(['session-completed'])
const collaborationStore = useCollaborationStore() const collaborationStore = useCollaborationStore()
const ws = useWebSocket(props.sessionId) const ws = useWebSocket(props.sessionId)
@ -149,7 +149,7 @@ const completeSession = async () => {
isAutoRunning.value = false isAutoRunning.value = false
if (autoRunTimeout.value) clearTimeout(autoRunTimeout.value) if (autoRunTimeout.value) clearTimeout(autoRunTimeout.value)
await collaborationStore.completeSession(props.sessionId) await collaborationStore.completeSession(props.sessionId)
// Stay on the session page - don't redirect emit('session-completed')
} catch (error) { } catch (error) {
console.error('Error completing session:', error) console.error('Error completing session:', error)
} }
@ -199,7 +199,7 @@ function formatAgentName(agent) {
</button> </button>
<button <button
v-if="!hasConverged && (isAutoRunning || isRunningRound)" v-if="isAutoRunning || isRunningRound"
@click="stopSession" @click="stopSession"
class="stop-btn" class="stop-btn"
title="Stop the session" title="Stop the session"
@ -207,15 +207,6 @@ function formatAgentName(agent) {
Stop Stop
</button> </button>
<button
v-if="hasConverged"
@click="$emit('go-home')"
class="home-btn"
title="Start new session"
>
Home
</button>
<div v-if="isAutoRunning || isRunningRound" class="auto-run-indicator"> <div v-if="isAutoRunning || isRunningRound" class="auto-run-indicator">
<span class="pulse"></span> <span class="pulse"></span>
Auto-running... Auto-running...
@ -394,24 +385,6 @@ function formatAgentName(agent) {
box-shadow: 0 8px 20px rgba(244, 67, 54, 0.3); box-shadow: 0 8px 20px rgba(244, 67, 54, 0.3);
} }
.home-btn {
padding: 0.75rem 1.5rem;
background: rgba(76, 175, 80, 0.8);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
border-radius: 10px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
}
.home-btn:hover {
background: rgba(76, 175, 80, 0.95);
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(76, 175, 80, 0.3);
}
.auto-run-indicator { .auto-run-indicator {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -17,14 +17,26 @@ const getAgentStatus = (round) => {
})) }))
} }
const totalRounds = computed(() => conversationHistory.value.length) const roundProgress = computed(() => {
if (agentCount.value === 0 || conversationHistory.value.length === 0) return 0
// Estimate progress: assume ~10 rounds max before convergence
const maxRounds = Math.ceil(agentCount.value * 1.5)
return Math.min(Math.round((conversationHistory.value.length / maxRounds) * 100), 100)
})
</script> </script>
<template> <template>
<div class="timeline-panel"> <div class="timeline-panel">
<!-- Round Counter --> <!-- Progress Bar -->
<div class="progress-section"> <div class="progress-section">
<div class="round-counter">Round {{ totalRounds }}</div> <div class="progress-header">
<span class="progress-label">Session Progress</span>
<span class="progress-percent">{{ roundProgress }}%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" :style="{ width: roundProgress + '%' }"></div>
</div>
<div class="round-counter">Round {{ currentRound }}</div>
</div> </div>
<!-- Timeline --> <!-- Timeline -->
@ -78,18 +90,50 @@ const totalRounds = computed(() => conversationHistory.value.length)
.progress-section { .progress-section {
padding: 1rem; padding: 1rem;
background: rgba(102, 126, 234, 0.12); background: rgba(102, 126, 234, 0.1);
border: 1px solid rgba(102, 126, 234, 0.3); border: 1px solid rgba(102, 126, 234, 0.3);
border-radius: 12px; border-radius: 12px;
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
text-align: center; }
.progress-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
font-size: 0.875rem;
}
.progress-label {
color: rgba(255, 255, 255, 0.7);
font-weight: 500;
}
.progress-percent {
color: var(--primary);
font-weight: 600;
}
.progress-bar {
height: 6px;
background: rgba(255, 255, 255, 0.05);
border-radius: 3px;
overflow: hidden;
margin-bottom: 0.5rem;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #667eea, #764ba2);
border-radius: 3px;
transition: width 0.3s ease;
} }
.round-counter { .round-counter {
font-size: 1.2rem; text-align: center;
color: rgba(102, 126, 234, 0.9); font-size: 0.875rem;
font-weight: 600; color: rgba(255, 255, 255, 0.6);
letter-spacing: 0.5px; font-weight: 500;
} }
.timeline-list { .timeline-list {
@ -152,18 +196,18 @@ const totalRounds = computed(() => conversationHistory.value.length)
align-items: center; align-items: center;
gap: 0.3rem; gap: 0.3rem;
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
background: rgba(150, 150, 150, 0.15); background: rgba(255, 255, 255, 0.05);
border-radius: 6px; border-radius: 6px;
font-size: 0.7rem; font-size: 0.7rem;
color: rgba(255, 255, 255, 0.35); color: rgba(255, 255, 255, 0.5);
cursor: help; cursor: help;
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.agent-item.active { .agent-item.active {
background: rgba(76, 175, 80, 0.25); background: rgba(76, 175, 80, 0.2);
color: rgba(76, 175, 80, 0.95); color: rgba(76, 175, 80, 0.9);
border: 1px solid rgba(76, 175, 80, 0.4); border: 1px solid rgba(76, 175, 80, 0.3);
} }
.agent-dot { .agent-dot {