Add multi-provider AI support (Claude and Mistral)

- Update runRound() to dynamically select correct AI client based on session.aiProvider
- Modify POST /api/collaborate to accept and validate aiProvider parameter
- Add aiProvider field to session creation response
- Add AI provider selector dropdown to frontend (Mistral Large 2411 vs Claude 3.5 Sonnet)
- Update collaboration store to pass aiProvider parameter through API

Users can now choose between Mistral and Claude AI for their collaborative sessions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Augustin ROUX 2025-10-19 16:35:21 +02:00
parent 60fdc9a66f
commit 130e21c867
4 changed files with 33 additions and 12 deletions

View File

@ -10,7 +10,7 @@ const router = express.Router()
*/ */
router.post('/', async (req, res) => { router.post('/', async (req, res) => {
try { try {
const { prompt, documentFormat = 'md', agentCount = 7 } = req.body const { prompt, documentFormat = 'md', agentCount = 7, aiProvider = 'mistral' } = req.body
if (!prompt || prompt.trim().length === 0) { if (!prompt || prompt.trim().length === 0) {
return res.status(400).json({ error: 'Prompt is required' }) return res.status(400).json({ error: 'Prompt is required' })
@ -20,13 +20,18 @@ router.post('/', async (req, res) => {
return res.status(400).json({ error: 'Document format must be "md" or "txt"' }) return res.status(400).json({ error: 'Document format must be "md" or "txt"' })
} }
if (!['mistral', 'claude'].includes(aiProvider)) {
return res.status(400).json({ error: 'AI provider must be "mistral" or "claude"' })
}
// Validate agent count // Validate agent count
const validAgentCount = Math.min(Math.max(agentCount, 3), 50) const validAgentCount = Math.min(Math.max(agentCount, 3), 50)
const sessionId = collaborativeOrchestrator.createSession( const sessionId = collaborativeOrchestrator.createSession(
prompt, prompt,
documentFormat, documentFormat,
validAgentCount validAgentCount,
aiProvider
) )
const sessionInfo = collaborativeOrchestrator.getSessionInfo(sessionId) const sessionInfo = collaborativeOrchestrator.getSessionInfo(sessionId)
@ -36,6 +41,7 @@ router.post('/', async (req, res) => {
prompt, prompt,
documentFormat, documentFormat,
agentCount: validAgentCount, agentCount: validAgentCount,
aiProvider,
status: 'created', status: 'created',
agents: sessionInfo.agents, agents: sessionInfo.agents,
message: 'Collaborative session created. Start the session to begin collaboration.' message: 'Collaborative session created. Start the session to begin collaboration.'

View File

@ -1,5 +1,6 @@
import db from '../db/schema.js' import db from '../db/schema.js'
import { generateAgentResponseSync, extractSection, extractThinking } from './mistralClient.js' import * as mistralClient from './mistralClient.js'
import * as claudeClient from './claudeClient.js'
import { getRandomNames } from './nameGenerator.js' import { getRandomNames } from './nameGenerator.js'
class CollaborativeOrchestrator { class CollaborativeOrchestrator {
@ -44,13 +45,13 @@ class CollaborativeOrchestrator {
/** /**
* Create a new collaborative session with N random-named agents * Create a new collaborative session with N random-named agents
*/ */
createSession(initialPrompt, documentFormat = 'md', agentCount = 7) { createSession(initialPrompt, documentFormat = 'md', agentCount = 7, aiProvider = 'mistral') {
const stmt = db.prepare( const stmt = db.prepare(
'INSERT INTO collaborative_sessions (initial_prompt, document_format, status) VALUES (?, ?, ?)' 'INSERT INTO collaborative_sessions (initial_prompt, document_format, status) VALUES (?, ?, ?)'
) )
const result = stmt.run(initialPrompt, documentFormat, 'created') const result = stmt.run(initialPrompt, documentFormat, 'created')
const sessionId = result.lastInsertRowid const sessionId = result.lastInsertRowid
console.log(`[Session ${sessionId}] Created with ${agentCount} agents, format: ${documentFormat}`) console.log(`[Session ${sessionId}] Created with ${agentCount} agents, format: ${documentFormat}, provider: ${aiProvider}`)
// Generate random names for agents // Generate random names for agents
const agentNames = getRandomNames(Math.min(agentCount, 50)) const agentNames = getRandomNames(Math.min(agentCount, 50))
@ -59,6 +60,7 @@ class CollaborativeOrchestrator {
id: sessionId, id: sessionId,
initialPrompt, initialPrompt,
documentFormat, documentFormat,
aiProvider, // Claude or Mistral
agents: agentNames, // Array of agent names agents: agentNames, // Array of agent names
agentCount, agentCount,
currentAgentIndex: 0, currentAgentIndex: 0,
@ -179,14 +181,15 @@ class CollaborativeOrchestrator {
try { try {
console.log(`[Session ${sessionId}] ${agentName} analyzing and generating response...`) console.log(`[Session ${sessionId}] ${agentName} analyzing and generating response...`)
const response = await generateAgentResponseSync( const client = session.aiProvider === 'claude' ? claudeClient : mistralClient
const response = await client.generateAgentResponseSync(
agentName, agentName,
session.initialPrompt, session.initialPrompt,
session.currentDocument // <-- This is always the latest version session.currentDocument // <-- This is always the latest version
) )
const thinking = extractThinking(response) const thinking = client.extractThinking(response)
const section = extractSection(response) const section = client.extractSection(response)
console.log(`[Session ${sessionId}] ${agentName} response received (${response.length} chars)`) console.log(`[Session ${sessionId}] ${agentName} response received (${response.length} chars)`)
console.log(`[Session ${sessionId}] --- THINKING (${agentName}) ---`) console.log(`[Session ${sessionId}] --- THINKING (${agentName}) ---`)

View File

@ -9,6 +9,7 @@ const collaborationStore = useCollaborationStore()
const prompt = ref('') const prompt = ref('')
const contextFile = ref(null) const contextFile = ref(null)
const agentCount = ref(7) const agentCount = ref(7)
const aiProvider = ref('mistral')
const isCreating = ref(false) const isCreating = ref(false)
const previousSessions = ref([]) const previousSessions = ref([])
const loadingPreviousSessions = ref(false) const loadingPreviousSessions = ref(false)
@ -108,7 +109,8 @@ const handleCreateSession = async () => {
const session = await collaborationStore.createSession( const session = await collaborationStore.createSession(
finalPrompt, finalPrompt,
'md', 'md',
agentCount.value agentCount.value,
aiProvider.value
) )
emit('session-created', session) emit('session-created', session)
@ -117,6 +119,7 @@ const handleCreateSession = async () => {
prompt.value = '' prompt.value = ''
contextFile.value = null contextFile.value = null
agentCount.value = 7 agentCount.value = 7
aiProvider.value = 'mistral'
} catch (error) { } catch (error) {
alert(`Error creating session: ${collaborationStore.error}`) alert(`Error creating session: ${collaborationStore.error}`)
} finally { } finally {
@ -290,7 +293,7 @@ const removeFile = () => {
<p class="hint">Optional: Provide existing documentation or requirements to guide the design.</p> <p class="hint">Optional: Provide existing documentation or requirements to guide the design.</p>
</div> </div>
<!-- Agent Count Selection --> <!-- Agent Count and AI Provider Selection -->
<div class="form-grid"> <div class="form-grid">
<div class="form-group"> <div class="form-group">
<label for="agents" class="label">Number of AI Specialists</label> <label for="agents" class="label">Number of AI Specialists</label>
@ -301,6 +304,14 @@ const removeFile = () => {
</select> </select>
<p class="hint">More agents = more diverse perspectives.</p> <p class="hint">More agents = more diverse perspectives.</p>
</div> </div>
<div class="form-group">
<label for="provider" class="label">AI Provider</label>
<select v-model="aiProvider" id="provider" class="select">
<option value="mistral">Mistral (Large 2411)</option>
<option value="claude">Claude (3.5 Sonnet)</option>
</select>
<p class="hint">Choose the AI model for specialists.</p>
</div>
</div> </div>
<!-- Info Box --> <!-- Info Box -->

View File

@ -15,7 +15,7 @@ export const useCollaborationStore = defineStore('collaboration', () => {
/** /**
* Create a new collaborative session * Create a new collaborative session
*/ */
async function createSession(prompt, documentFormat = 'md', agentCount = 7) { async function createSession(prompt, documentFormat = 'md', agentCount = 7, aiProvider = 'mistral') {
loading.value = true loading.value = true
error.value = null error.value = null
@ -28,7 +28,8 @@ export const useCollaborationStore = defineStore('collaboration', () => {
body: JSON.stringify({ body: JSON.stringify({
prompt, prompt,
documentFormat, documentFormat,
agentCount agentCount,
aiProvider
}) })
}) })