This commit is contained in:
2026-04-05 00:43:23 +05:30
commit 8be37d3e92
425 changed files with 101853 additions and 0 deletions

View File

@@ -0,0 +1,125 @@
import asyncio
import json
from agents.negotiator_agent import NegotiatorAgent
import database as db
async def run_negotiation(negotiation_id: str, preferences_a: dict, preferences_b: dict,
user_a_id: int, user_b_id: int, feature_type: str,
personality_a: str = "balanced", personality_b: str = "balanced",
on_round_update=None, on_resolution=None,
feature_context: str = ""):
"""
Main negotiation loop with personality-aware agents and analytics tracking.
"""
await db.update_negotiation_status(negotiation_id, "active")
# Create personality-aware negotiators
negotiator_a = NegotiatorAgent(personality=personality_a)
negotiator_b = NegotiatorAgent(personality=personality_b)
current_proposal = None
max_rounds = 7
satisfaction_timeline = []
for round_num in range(1, max_rounds + 1):
await asyncio.sleep(1.5) # Rate limit protection for Gemini
if round_num == 1:
response = await negotiator_a.generate_initial_proposal(
my_preferences=preferences_a, feature_type=feature_type,
feature_context=feature_context
)
proposer_id = user_a_id
elif round_num % 2 == 0:
response = await negotiator_b.evaluate_and_respond(
received_proposal=current_proposal, my_preferences=preferences_b,
feature_type=feature_type, round_number=round_num,
feature_context=feature_context
)
proposer_id = user_b_id
else:
response = await negotiator_a.evaluate_and_respond(
received_proposal=current_proposal, my_preferences=preferences_a,
feature_type=feature_type, round_number=round_num,
feature_context=feature_context
)
proposer_id = user_a_id
# Handle errors
if "error" in response:
response = {
"action": "counter" if round_num < max_rounds else "escalate",
"proposal": current_proposal or {"summary": "Let's discuss further", "details": {}},
"satisfaction_score": 50, "reasoning": "Agent encountered an issue",
"concessions_made": [], "concessions_requested": []
}
action = response.get("action", "counter")
current_proposal = response.get("proposal", {})
satisfaction = response.get("satisfaction_score", 50)
concessions = response.get("concessions_made", [])
# Track satisfaction for analytics
# The proposer's score is the one returned; estimate the other party's
if proposer_id == user_a_id:
sat_a, sat_b = satisfaction, max(30, 100 - satisfaction * 0.4)
else:
sat_b, sat_a = satisfaction, max(30, 100 - satisfaction * 0.4)
satisfaction_timeline.append({
"round": round_num, "score_a": sat_a, "score_b": sat_b
})
# Save round with analytics data
await db.save_round(
negotiation_id=negotiation_id, round_number=round_num,
proposer_id=proposer_id, proposal=response,
response_type=action, reasoning=response.get("reasoning", ""),
satisfaction_a=sat_a, satisfaction_b=sat_b,
concessions_made=concessions
)
# Notify via callback
round_data = {
"negotiation_id": negotiation_id, "round_number": round_num,
"action": action, "proposal": current_proposal,
"satisfaction_score": satisfaction, "reasoning": response.get("reasoning", ""),
"proposer_id": proposer_id,
"satisfaction_a": sat_a, "satisfaction_b": sat_b
}
if on_round_update:
await on_round_update(round_data)
# Check outcome
if action == "accept":
resolution = {
"status": "resolved", "final_proposal": current_proposal,
"rounds_taken": round_num, "summary": current_proposal.get("summary", "Agreement reached"),
"satisfaction_timeline": satisfaction_timeline
}
await db.update_negotiation_status(negotiation_id, "resolved", resolution)
if on_resolution:
await on_resolution(resolution)
return resolution
if action == "escalate":
resolution = {
"status": "escalated", "final_proposal": current_proposal,
"rounds_taken": round_num, "summary": "Agents couldn't fully agree. Options for human decision.",
"satisfaction_timeline": satisfaction_timeline
}
await db.update_negotiation_status(negotiation_id, "escalated", resolution)
if on_resolution:
await on_resolution(resolution)
return resolution
# Exhausted rounds
resolution = {
"status": "escalated", "final_proposal": current_proposal,
"rounds_taken": max_rounds, "summary": "Max rounds reached. Best proposal for human decision.",
"satisfaction_timeline": satisfaction_timeline
}
await db.update_negotiation_status(negotiation_id, "escalated", resolution)
if on_resolution:
await on_resolution(resolution)
return resolution