← Tasks
[AI-05] ACP choreography (Swiss HF) (retry 1) (retry 2) (retry 3)
completedcode_genP0
Description
## AI-05: ACP agent-to-agent choreography
Section: AI Features | Milestone: M4
### Requirements
Implement an ACP (Agent Communication Protocol) module for buyer/seller marketplace agents.
### Acceptance Criteria
- File src/lib/acp-agents.ts must contain: agent choreography, acp, buyer_agent, seller_agent
### Codebase Conventions
- Trilingual comments: // EN: ... // VI: ... // ES: ...
- SPEC section refs in comments
- Zod at module level with .safeParse()
- NextResponse.json() responses
Write
Assignee
-
Claimed By
Cloud Lu → Claude Sonnet
Created
1d ago
Completed
1d ago
Quality
Overall
78%
Pass
PASS
Graded By
-
Graded At
-
Cost
Input Tokens
-
Output Tokens
-
Est. USD
-
Result
{
"cost": {
"input_tokens": 179,
"estimated_usd": 0.075522,
"output_tokens": 4999
},
"model": "claude-sonnet-4-20250514",
"status": "success",
"transport": "anthropic_api",
"latency_ms": 54399,
"response_text": "```typescript\n// src/lib/acp-agents.ts\n// EN: ACP (Agent Communication Protocol) module for buyer/seller marketplace agents\n// VI: Mô-đun ACP (Giao thức Giao tiếp Đại lý) cho các đại lý mua/bán marketplace\n// ES: Módulo ACP (Protocolo de Comunicación de Agentes) para agentes comprador/vendedor del marketplace\n// SPEC: AI-05 - ACP agent-to-agent choreography\n\nimport { z } from 'zod';\n\n// EN: ACP message schema validation\n// VI: Xác thực schema tin nhắn ACP\n// ES: Validación de esquema de mensaje ACP\nconst ACPMessageSchema = z.object({\n id: z.string(),\n type: z.enum(['propose', 'accept', 'reject', 'counter_offer', 'inquiry', 'confirm']),\n sender: z.string(),\n recipient: z.string(),\n content: z.object({\n item_id: z.string().optional(),\n price: z.number().optional(),\n quantity: z.number().optional(),\n terms: z.string().optional(),\n message: z.string().optional()\n }),\n timestamp: z.string()\n});\n\n// EN: Agent state schema\n// VI: Schema trạng thái đại lý\n// ES: Esquema de estado del agente\nconst AgentStateSchema = z.object({\n agent_id: z.string(),\n type: z.enum(['buyer', 'seller']),\n status: z.enum(['active', 'negotiating', 'busy', 'offline']),\n preferences: z.object({\n max_price: z.number().optional(),\n min_price: z.number().optional(),\n preferred_items: z.array(z.string()).optional(),\n negotiation_style: z.enum(['aggressive', 'moderate', 'conservative']).optional()\n })\n});\n\ntype ACPMessage = z.infer<typeof ACPMessageSchema>;\ntype AgentState = z.infer<typeof AgentStateSchema>;\n\n// EN: Core ACP communication protocol class\n// VI: Lớp giao thức giao tiếp ACP cốt lõi\n// ES: Clase principal del protocolo de comunicación ACP\nexport class acp {\n private static messageHistory: Map<string, ACPMessage[]> = new Map();\n private static agents: Map<string, AgentState> = new Map();\n\n // EN: Send message between agents\n // VI: Gửi tin nhắn giữa các đại lý\n // ES: Enviar mensaje entre agentes\n static async sendMessage(message: unknown): Promise<{ success: boolean; error?: string }> {\n const validation = ACPMessageSchema.safeParse(message);\n if (!validation.success) {\n return { success: false, error: 'Invalid message format' };\n }\n\n const validMessage = validation.data;\n const conversationId = this.getConversationId(validMessage.sender, validMessage.recipient);\n \n if (!this.messageHistory.has(conversationId)) {\n this.messageHistory.set(conversationId, []);\n }\n \n this.messageHistory.get(conversationId)!.push(validMessage);\n \n // EN: Notify recipient agent\n // VI: Thông báo cho đại lý nhận\n // ES: Notificar al agente receptor\n await this.notifyAgent(validMessage.recipient, validMessage);\n \n return { success: true };\n }\n\n // EN: Get conversation history between two agents\n // VI: Lấy lịch sử hội thoại giữa hai đại lý\n // ES: Obtener historial de conversación entre dos agentes\n static getConversationHistory(agent1: string, agent2: string): ACPMessage[] {\n const conversationId = this.getConversationId(agent1, agent2);\n return this.messageHistory.get(conversationId) || [];\n }\n\n // EN: Register agent in the system\n // VI: Đăng ký đại lý trong hệ thống\n // ES: Registrar agente en el sistema\n static registerAgent(agentData: unknown): { success: boolean; error?: string } {\n const validation = AgentStateSchema.safeParse(agentData);\n if (!validation.success) {\n return { success: false, error: 'Invalid agent data' };\n }\n\n const validAgent = validation.data;\n this.agents.set(validAgent.agent_id, validAgent);\n return { success: true };\n }\n\n private static getConversationId(agent1: string, agent2: string): string {\n return [agent1, agent2].sort().join('_');\n }\n\n private static async notifyAgent(agentId: string, message: ACPMessage): Promise<void> {\n // EN: Implementation would notify the specific agent of new message\n // VI: Triển khai sẽ thông báo cho đại lý cụ thể về tin nhắn mới\n // ES: La implementación notificaría al agente específico del nuevo mensaje\n console.log(`Notifying agent ${agentId} of new message:`, message);\n }\n}\n\n// EN: Buyer agent class implementing ACP choreography\n// VI: Lớp đại lý mua triển khai choreography ACP\n// ES: Clase de agente comprador implementando coreografía ACP\nexport class buyer_agent {\n private agentId: string;\n private preferences: AgentState['preferences'];\n\n constructor(agentId: string, preferences: AgentState['preferences'] = {}) {\n this.agentId = agentId;\n this.preferences = preferences;\n \n // EN: Register this buyer agent\n // VI: Đăng ký đại lý mua này\n // ES: Registrar este agente comprador\n acp.registerAgent({\n agent_id: agentId,\n type: 'buyer',\n status: 'active',\n preferences\n });\n }\n\n // EN: Send inquiry to seller about item\n // VI: Gửi yêu cầu tới người bán về sản phẩm\n // ES: Enviar consulta al vendedor sobre el artículo\n async inquireItem(sellerId: string, itemId: string, message?: string): Promise<{ success: boolean; error?: string }> {\n const inquiryMessage: ACPMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'inquiry',\n sender: this.agentId,\n recipient: sellerId,\n content: {\n item_id: itemId,\n message: message || 'Interested in this item. Can you provide more details?'\n },\n timestamp: new Date().toISOString()\n };\n\n return await acp.sendMessage(inquiryMessage);\n }\n\n // EN: Make offer to seller\n // VI: Đưa ra đề nghị cho người bán\n // ES: Hacer oferta al vendedor\n async makeOffer(sellerId: string, itemId: string, price: number, quantity: number = 1, terms?: string): Promise<{ success: boolean; error?: string }> {\n // EN: Check if price is within buyer's budget\n // VI: Kiểm tra xem giá có nằm trong ngân sách của người mua không\n // ES: Verificar si el precio está dentro del presupuesto del comprador\n if (this.preferences.max_price && price > this.preferences.max_price) {\n return { success: false, error: 'Offer exceeds maximum budget' };\n }\n\n const offerMessage: ACPMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'propose',\n sender: this.agentId,\n recipient: sellerId,\n content: {\n item_id: itemId,\n price,\n quantity,\n terms: terms || 'Standard purchase terms'\n },\n timestamp: new Date().toISOString()\n };\n\n return await acp.sendMessage(offerMessage);\n }\n\n // EN: Accept seller's counter offer\n // VI: Chấp nhận đề nghị phản hồi của người bán\n // ES: Aceptar contraoferta del vendedor\n async acceptOffer(sellerId: string, itemId: string): Promise<{ success: boolean; error?: string }> {\n const acceptMessage: ACPMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'accept',\n sender: this.agentId,\n recipient: sellerId,\n content: {\n item_id: itemId,\n message: 'Offer accepted. Ready to proceed with purchase.'\n },\n timestamp: new Date().toISOString()\n };\n\n return await acp.sendMessage(acceptMessage);\n }\n\n // EN: Reject seller's offer\n // VI: Từ chối đề nghị của người bán\n // ES: Rechazar oferta del vendedor\n async rejectOffer(sellerId: string, itemId: string, reason?: string): Promise<{ success: boolean; error?: string }> {\n const rejectMessage: ACPMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'reject',\n sender: this.agentId,\n recipient: sellerId,\n content: {\n item_id: itemId,\n message: reason || 'Unable to accept current offer'\n },\n timestamp: new Date().toISOString()\n };\n\n return await acp.sendMessage(rejectMessage);\n }\n\n // EN: Get conversation history with specific seller\n // VI: Lấy lịch sử hội thoại với người bán cụ thể\n // ES: Obtener historial de conversación con vendedor específico\n getConversationHistory(sellerId: string): ACPMessage[] {\n return acp.getConversationHistory(this.agentId, sellerId);\n }\n}\n\n// EN: Seller agent class implementing ACP choreography\n// VI: Lớp đại lý bán triển khai choreography ACP\n// ES: Clase de agente vendedor implementando coreografía ACP\nexport class seller_agent {\n private agentId: string;\n private preferences: AgentState['preferences'];\n\n constructor(agentId: string, preferences: AgentState['preferences'] = {}) {\n this.agentId = agentId;\n this.preferences = preferences;\n \n // EN: Register this seller agent\n // VI: Đăng ký đại lý bán này\n // ES: Registrar este agente vendedor\n acp.registerAgent({\n agent_id: agentId,\n type: 'seller',\n status: 'active',\n preferences\n });\n }\n\n // EN: Respond to buyer inquiry\n // VI: Phản hồi yêu cầu của người mua\n // ES: Responder a consulta del comprador\n async respondToInquiry(buyerId: string, itemId: string, itemDetails: string): Promise<{ success: boolean; error?: string }> {\n const responseMessage: ACPMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'confirm',\n sender: this.agentId,\n recipient: buyerId,\n content: {\n item_id: itemId,\n message: `Item details: ${itemDetails}`\n },\n timestamp: new Date().toISOString()\n };\n\n return await acp.sendMessage(responseMessage);\n }\n\n // EN: Make counter offer to buyer\n // VI: Đưa ra đề nghị phản hồi cho người mua\n // ES: Hacer contraoferta al comprador\n async makeCounterOffer(buyerId: string, itemId: string, price: number, quantity: number = 1, terms?: string): Promise<{ success: boolean; error?: string }> {\n // EN: Check if price meets seller's minimum\n // VI: Kiểm tra xem giá có đáp ứng mức tối thiểu của người bán không\n // ES: Verificar si el precio cumple el mínimo del vendedor\n if (this.preferences.min_price && price < this.preferences.min_price) {\n return { success: false, error: 'Counter offer below minimum acceptable price' };\n }\n\n const counterOfferMessage: ACPMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'counter_offer',\n sender: this.agentId,\n recipient: buyerId,\n content: {\n item_id: itemId,\n price,\n quantity,\n terms: terms || 'Counter offer with adjusted terms'\n },\n timestamp: new Date().toISOString()\n };\n\n return await acp.sendMessage(counterOfferMessage);\n }\n\n // EN: Accept buyer's offer\n // VI: Chấp nhận đề nghị của người mua\n // ES: Aceptar oferta del comprador\n async acceptOffer(buyerId: string, itemId: string): Promise<{ success: boolean; error?: string }> {\n const acceptMessage: ACPMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'accept',\n sender: this.agentId,\n recipient: buyerId,\n content: {\n item_id: itemId,\n message: 'Offer accepted. Ready to proceed with sale.'\n },\n timestamp: new Date().toISOString()\n };\n\n return await acp.sendMessage(acceptMessage);\n }\n\n // EN: Reject buyer's offer\n // VI: Từ chối đề nghị của người mua\n // ES: Rechazar oferta del comprador\n async rejectOffer(buyerId: string, itemId: string, reason?: string): Promise<{ success: boolean; error?: string }> {\n const rejectMessage: ACPMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: 'reject',\n sender: this.agentId,\n recipient: buyerId,\n content: {\n item_id: itemId,\n message: reason || 'Unable to accept current offer'\n },\n timestamp: new Date().toISOString()\n };\n\n return await acp.sendMessage(rejectMessage);\n }\n\n // EN: Get conversation history with specific buyer\n // VI: Lấy lịch sử hội thoại với người mua cụ thể\n // ES: Obtener historial de conversación con comprador específico\n getConversationHistory(buyerId: string): ACPMessage[] {\n return acp.getConversationHistory(this.agentId, buyerId);\n }\n}\n\n// EN: Agent choreography orchestrator for complex multi-agent interactions\n// VI: Bộ điều phối choreography đại lý cho tương tác đa đại lý phức tạp\n// ES: Orquestador de coreografía de agentes para interacciones multi-agente complejas\nexport class agent_choreography {\n private activeNegotiations: Map<string, {\n buyer: string;\n seller: string;\n item_id: string;\n status: 'active' | 'completed' | 'failed';\n start_time: string;\n last_activity: string;\n }> = new Map();\n\n // EN: Initiate negotiation between buyer and seller\n // VI: Khởi tạo đàm phán giữa người mua và người bán\n // ES: Iniciar negociación entre comprador y vendedor\n initiateNegotiation(buyerId: string, sellerId: string, itemId: string): string {\n const negotiationId = `neg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n \n this.activeNegotiations.set(negotiationId, {\n buyer: buyerId,\n seller: sellerId,\n item_id: itemId,\n status: 'active',\n start_time: new Date().toISOString(),\n last_activity: new Date().toISOString()\n });\n\n return negotiationId;\n }\n\n // EN: Monitor negotiation progress and intervene if needed\n // VI: Theo dõi tiến trình đàm phán và can thiệp nếu cần\n // ES: Monitorear progreso de negociación e intervenir si es necesario\n monitorNegotiation(negotiationId: string): {\n status: string;\n messages: ACPMessage[];\n recommendations?: string[];\n } | null {\n const negotiation = this.activeNegotiations.get(negotiationId);\n if (!negotiation) return null;\n\n const messages = acp.getConversationHistory(negotiation.buyer, negotiation.seller);\n const recommendations: string[] = [];\n\n // EN: Analyze conversation and provide recommendations\n // VI: Phân tích cuộc hội thoại và đưa ra khuyến nghị\n // ES: Analizar conversación y proporcionar recomendaciones\n if (messages.length > 10) {\n recommendations.push('Consider involving a mediator for complex negotiation');\n }\n \n const recentMessages = messages.filter(msg => \n Date.now() - new Date(msg.timestamp).getTime() < 3600000 // Last hour\n );\n \n if (recentMessages.length === 0) {\n recommendations.push('Negotiation appears stalled - consider follow-up');\n }\n\n return {\n status: negotiation.status,\n messages,\n recommendations: recommendations.length > 0 ? recommendations : undefined\n };\n }\n\n // EN: Complete negotiation when agreement is reached\n // VI: Hoàn thành đàm phán khi đạt được thỏa thuận\n // ES: Completar negociación cuando se alcanza acuerdo\n completeNegotiation(negotiationId: string, success: boolean): boolean {\n const negotiation = this.activeNegotiations.get(negotiationId);\n if (!negotiation) return false;\n\n negotiation.status = success ? 'completed' : 'failed';\n negotiation.last_activity = new Date().toISOString();\n \n return true;\n }\n\n // EN: Get all active negotiations\n // VI: Lấy tất cả đàm phán đang hoạt động\n // ES: Obtener todas las negociaciones activas\n getActiveNegotiations(): Array<{\n id: string;\n buyer: string;\n seller: string;\n item_id: string;\n status: string;\n start_time: string;\n last_activity: string;\n }> {\n return Array.from(this.activeNegotiations.entries()).map(([id, negotiation]) => ({\n id,\n ...negotiation\n }));\n }\n}\n\n// EN: Default export for choreography orchestrator\n// VI: Xuất mặc định cho bộ điều phối choreography\n// ES: Exportación por defecto para orquestador de coreografía\nexport default agent_choreography;\n```"
}Task ID: a226f72c-812a-4bc1-b4c4-763046c3b6c2