Compare commits
2 Commits
68cf310f0c
...
10ccae2430
| Author | SHA1 | Date | |
|---|---|---|---|
| 10ccae2430 | |||
| 59465c79c1 |
@ -82,7 +82,7 @@ class CollaborativeOrchestrator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a session - create initial document with first agent
|
* Start a session - SYSTEM creates base structure, then Round 1 begins with Agent 1
|
||||||
*/
|
*/
|
||||||
async startSession(sessionId) {
|
async startSession(sessionId) {
|
||||||
try {
|
try {
|
||||||
@ -91,27 +91,23 @@ 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(', ')}`)
|
||||||
|
|
||||||
const firstAgent = session.agents[0]
|
// STEP 1: SYSTEM creates base structure (not an AI agent)
|
||||||
console.log(`[Session ${sessionId}] ${firstAgent} creating initial document...`)
|
console.log(`[Session ${sessionId}] [SYSTEM] Creating base document structure...`)
|
||||||
|
const baseStructure = `# ${session.initialPrompt.split('\n')[0] || 'Project Overview'}\n\nThis document will be collaboratively developed by ${session.agents.length} AI specialists.`
|
||||||
|
|
||||||
// Generate initial document
|
console.log(`[Session ${sessionId}] [SYSTEM] Base structure created (${baseStructure.length} chars)`)
|
||||||
const initialResponse = await generateAgentResponseSync(
|
console.log(`[Session ${sessionId}] ===== BASE STRUCTURE (v0) =====`)
|
||||||
firstAgent,
|
console.log(baseStructure)
|
||||||
session.initialPrompt,
|
console.log(`[Session ${sessionId}] ===== END BASE STRUCTURE =====`)
|
||||||
''
|
|
||||||
)
|
|
||||||
|
|
||||||
const initialDocument = extractSection(initialResponse)
|
// Save base structure to DB
|
||||||
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, initialDocument, firstAgent, 'Initial document creation', 0)
|
insertStmt.run(sessionId, 0, baseStructure, 'SYSTEM', 'Base structure creation', 0)
|
||||||
|
|
||||||
// Update session
|
// Update session
|
||||||
session.currentDocument = initialDocument
|
session.currentDocument = baseStructure
|
||||||
session.versionNumber = 0
|
session.versionNumber = 0
|
||||||
session.started = true
|
session.started = true
|
||||||
session.consecutiveNoChanges = 0
|
session.consecutiveNoChanges = 0
|
||||||
@ -120,22 +116,17 @@ 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)
|
||||||
|
|
||||||
console.log(`[Session ${sessionId}] Initial document created (${initialDocument.length} chars)`)
|
// Broadcast base structure
|
||||||
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: initialDocument,
|
content: baseStructure,
|
||||||
agentName: firstAgent,
|
agentName: 'SYSTEM',
|
||||||
thinking,
|
thinking: 'Created base structure for collaboration',
|
||||||
roundNumber: 0
|
roundNumber: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(`[Session ${sessionId}] Scheduling first round in 2s...`)
|
console.log(`[Session ${sessionId}] Base structure ready. Scheduling Round 1 in 2s...`)
|
||||||
// Auto-start first round
|
// Auto-start first round with all agents
|
||||||
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)
|
||||||
@ -160,11 +151,17 @@ class CollaborativeOrchestrator {
|
|||||||
|
|
||||||
console.log(`[Session ${sessionId}] ===== ROUND ${roundNumber} START =====`)
|
console.log(`[Session ${sessionId}] ===== ROUND ${roundNumber} START =====`)
|
||||||
|
|
||||||
// Each agent reviews the document
|
// Each agent reviews the document SEQUENTIALLY, receiving the updated version from the previous agent
|
||||||
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
|
||||||
|
|
||||||
console.log(`[Session ${sessionId}] Round ${roundNumber}: ${agentName} reviewing...`)
|
// STEP: Agent receives current document state
|
||||||
|
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, {
|
||||||
@ -174,21 +171,22 @@ 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
|
session.currentDocument // <-- This is always the latest version
|
||||||
)
|
)
|
||||||
|
|
||||||
const thinking = extractThinking(response)
|
const thinking = extractThinking(response)
|
||||||
const section = extractSection(response)
|
const section = extractSection(response)
|
||||||
|
|
||||||
console.log(`[Session ${sessionId}] Round ${roundNumber}: ${agentName} response received (${response.length} chars)`)
|
console.log(`[Session ${sessionId}] ${agentName} response received (${response.length} chars)`)
|
||||||
console.log(`[Session ${sessionId}] --- THINKING ---`)
|
console.log(`[Session ${sessionId}] --- THINKING (${agentName}) ---`)
|
||||||
console.log(thinking)
|
console.log(thinking)
|
||||||
console.log(`[Session ${sessionId}] --- SECTION ---`)
|
console.log(`[Session ${sessionId}] --- SECTION (${agentName}) ---`)
|
||||||
console.log(section)
|
console.log(section)
|
||||||
console.log(`[Session ${sessionId}] --- END RESPONSE ---`)
|
console.log(`[Session ${sessionId}] --- END RESPONSE (${agentName}) ---`)
|
||||||
|
|
||||||
// Broadcast agent's thinking in real-time
|
// Broadcast agent's thinking in real-time
|
||||||
this.broadcast(sessionId, {
|
this.broadcast(sessionId, {
|
||||||
@ -215,12 +213,13 @@ 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}] Round ${roundNumber}: ${agentName} ${action}: "${headerText}" (v${session.versionNumber})`)
|
console.log(`[Session ${sessionId}] ✓ ${agentName} ${action}: "${headerText}"`)
|
||||||
console.log(`[Session ${sessionId}] ===== DOCUMENT BEFORE (v${session.versionNumber - 1}) =====`)
|
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}) =====`)
|
||||||
console.log(docBefore)
|
console.log(docBefore)
|
||||||
console.log(`[Session ${sessionId}] ===== DOCUMENT AFTER (v${session.versionNumber}) =====`)
|
console.log(`[Session ${sessionId}] ===== AFTER (v${session.versionNumber}) [${agentName}] =====`)
|
||||||
console.log(updatedDocument)
|
console.log(updatedDocument)
|
||||||
console.log(`[Session ${sessionId}] ===== END DOCUMENT =====`)
|
console.log(`[Session ${sessionId}] ===== END CHANGE =====`)
|
||||||
|
|
||||||
// Save version to DB
|
// Save version to DB
|
||||||
const insertStmt = db.prepare(
|
const insertStmt = db.prepare(
|
||||||
|
|||||||
@ -48,7 +48,7 @@ function startNewCollaboration() {
|
|||||||
<CollaborativeSession
|
<CollaborativeSession
|
||||||
v-if="currentSessionId"
|
v-if="currentSessionId"
|
||||||
:session-id="currentSessionId"
|
:session-id="currentSessionId"
|
||||||
@session-completed="startNewCollaboration"
|
@go-home="startNewCollaboration"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -12,7 +12,7 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['session-completed'])
|
const emit = defineEmits(['go-home'])
|
||||||
|
|
||||||
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)
|
||||||
emit('session-completed')
|
// Stay on the session page - don't redirect
|
||||||
} 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="isAutoRunning || isRunningRound"
|
v-if="!hasConverged && (isAutoRunning || isRunningRound)"
|
||||||
@click="stopSession"
|
@click="stopSession"
|
||||||
class="stop-btn"
|
class="stop-btn"
|
||||||
title="Stop the session"
|
title="Stop the session"
|
||||||
@ -207,6 +207,15 @@ 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...
|
||||||
@ -385,6 +394,24 @@ 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;
|
||||||
|
|||||||
@ -17,26 +17,14 @@ const getAgentStatus = (round) => {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
const roundProgress = computed(() => {
|
const totalRounds = computed(() => conversationHistory.value.length)
|
||||||
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">
|
||||||
<!-- Progress Bar -->
|
<!-- Round Counter -->
|
||||||
<div class="progress-section">
|
<div class="progress-section">
|
||||||
<div class="progress-header">
|
<div class="round-counter">Round {{ totalRounds }}</div>
|
||||||
<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 -->
|
||||||
@ -90,50 +78,18 @@ const roundProgress = computed(() => {
|
|||||||
|
|
||||||
.progress-section {
|
.progress-section {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background: rgba(102, 126, 234, 0.1);
|
background: rgba(102, 126, 234, 0.12);
|
||||||
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 {
|
||||||
text-align: center;
|
font-size: 1.2rem;
|
||||||
font-size: 0.875rem;
|
color: rgba(102, 126, 234, 0.9);
|
||||||
color: rgba(255, 255, 255, 0.6);
|
font-weight: 600;
|
||||||
font-weight: 500;
|
letter-spacing: 0.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-list {
|
.timeline-list {
|
||||||
@ -196,18 +152,18 @@ const roundProgress = computed(() => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.3rem;
|
gap: 0.3rem;
|
||||||
padding: 0.25rem 0.5rem;
|
padding: 0.25rem 0.5rem;
|
||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(150, 150, 150, 0.15);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
color: rgba(255, 255, 255, 0.5);
|
color: rgba(255, 255, 255, 0.35);
|
||||||
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.2);
|
background: rgba(76, 175, 80, 0.25);
|
||||||
color: rgba(76, 175, 80, 0.9);
|
color: rgba(76, 175, 80, 0.95);
|
||||||
border: 1px solid rgba(76, 175, 80, 0.3);
|
border: 1px solid rgba(76, 175, 80, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-dot {
|
.agent-dot {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user