FOUNDRY
C8 Platform
← Tasks

[AI-05] ACP choreography (Vertex Flash)

completedcode_genP3

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
Vertex Flash
Created
25d ago
Completed
25d ago

Quality

Overall
77%
Pass
PASS
Graded By
-
Graded At
-

Cost

Input Tokens
168
Output Tokens
2,380
Est. USD
-

Result

{
  "code": "```typescript\n// EN: ACP agent-to-agent choreography module. // VI: Mô-đun biên đạo múa giữa các tác nhân ACP. // ES: Módulo de coreografía agente a agente ACP.\n// SPEC: AI-05\n\nimport { z } from \"zod\";\nimport { NextResponse } from \"next/server\";\n\n// EN: Define Zod schemas for agent types. // VI: Xác định lược đồ Zod cho các loại tác nhân. // ES: Define esquemas Zod para los tipos de agentes.\nconst BuyerAgentSchema = z.object({\n  id: z.string(),\n  type: z.literal(\"buyer\"),\n  preferences: z.object({\n    category: z.string(),\n    maxPrice: z.number(),\n  }),\n});\ntype BuyerAgent = z.infer<typeof BuyerAgentSchema>;\n\nconst SellerAgentSchema = z.object({\n  id: z.string(),\n  type: z.literal(\"seller\"),\n  inventory: z.array(\n    z.object({\n      name: z.string(),\n      category: z.string(),\n      price: z.number(),\n      quantity: z.number(),\n    })\n  ),\n});\ntype SellerAgent = z.infer<typeof SellerAgentSchema>;\n\nconst MarketplaceAgentSchema = z.object({\n  id: z.string(),\n  type: z.literal(\"marketplace\"),\n});\ntype MarketplaceAgent = z.infer<typeof MarketplaceAgentSchema>;\n\n// EN: Define ACP message types. // VI: Định nghĩa các loại tin nhắn ACP. // ES: Define tipos de mensajes ACP.\nconst OfferSchema = z.object({\n  type: z.literal(\"offer\"),\n  itemId: z.string(), // EN: ID of the item being offered. // VI: ID của mặt hàng đang được cung cấp. // ES: ID del artículo que se ofrece.\n  price: z.number(),\n});\ntype Offer = z.infer<typeof OfferSchema>;\n\nconst RequestForOfferSchema = z.object({\n  type: z.literal(\"request_for_offer\"),\n  category: z.string(),\n  maxPrice: z.number(),\n});\ntype RequestForOffer = z.infer<typeof RequestForOfferSchema>;\n\nconst AcceptOfferSchema = z.object({\n  type: z.literal(\"accept_offer\"),\n  itemId: z.string(),\n});\ntype AcceptOffer = z.infer<typeof AcceptOfferSchema>;\n\nconst RejectOfferSchema = z.object({\n  type: z.literal(\"reject_offer\"),\n  itemId: z.string(),\n});\ntype RejectOffer = z.infer<typeof RejectOfferSchema>;\n\nconst ACPMessageSchema = z.discriminatedUnion(\"type\", [\n  OfferSchema,\n  RequestForOfferSchema,\n  AcceptOfferSchema,\n  RejectOfferSchema,\n]);\ntype ACPMessage = z.infer<typeof ACPMessageSchema>;\n\n// EN: Agent choreography functions. // VI: Các hàm biên đạo múa tác nhân. // ES: Funciones de coreografía del agente.\nasync function buyerAgent(\n  buyer: BuyerAgent,\n  seller: SellerAgent\n): Promise<NextResponse> {\n  // EN: Buyer sends a request for an offer. // VI: Người mua gửi yêu cầu chào hàng. // ES: El comprador envía una solicitud de oferta.\n  const requestForOffer: RequestForOffer = {\n    type: \"request_for_offer\",\n    category: buyer.preferences.category,\n    maxPrice: buyer.preferences.maxPrice,\n  };\n\n  // EN: Seller receives the request and checks inventory. // VI: Người bán nhận được yêu cầu và kiểm tra hàng tồn kho. // ES: El vendedor recibe la solicitud y verifica el inventario.\n  const relevantItems = seller.inventory.filter(\n    (item) =>\n      item.category === requestForOffer.category &&\n      item.price <= requestForOffer.maxPrice &&\n      item.quantity > 0\n  );\n\n  if (relevantItems.length === 0) {\n    // EN: No matching items, send a reject message (simulated). // VI: Không có mặt hàng phù hợp, gửi tin nhắn từ chối (mô phỏng). // ES: No hay artículos coincidentes, envía un mensaje de rechazo (simulado).\n    return NextResponse.json({ status: \"no_offer\" });\n  }\n\n  // EN: Seller sends an offer for the first relevant item. // VI: Người bán gửi một lời đề nghị cho mặt hàng phù hợp đầu tiên. // ES: El vendedor envía una oferta para el primer artículo relevante.\n  const offeredItem = relevantItems[0];\n  const offer: Offer = {\n    type: \"offer\",\n    itemId: offeredItem.name,\n    price: offeredItem.price,\n  };\n\n  // EN: Buyer receives the offer and decides to accept or reject. // VI: Người mua nhận được lời đề nghị và quyết định chấp nhận hoặc từ chối. // ES: El comprador recibe la oferta y decide aceptarla o rechazarla.\n  if (offer.price <= buyer.preferences.maxPrice) {\n    const acceptOffer: AcceptOffer = {\n      type: \"accept_offer\",\n      itemId: offer.itemId,\n    };\n    return NextResponse.json({ status: \"accepted\", offer });\n  } else {\n    const rejectOffer: RejectOffer = {\n      type: \"reject_offer\",\n      itemId: offer.itemId,\n    };\n    return NextResponse.json({ status: \"rejected\", offer });\n  }\n}\n\nasync function sellerAgent(\n  seller: SellerAgent,\n  message: any\n): Promise<NextResponse> {\n\n  const parsedMessage = ACPMessageSchema.safeParse(message);\n\n  if (!parsedMessage.success) {\n    console.error(\"Invalid ACP message:\", parsedMessage.error);\n    return NextResponse.json({ status: \"error\", message: \"Invalid message format\" });\n  }\n\n  const acpMessage = parsedMessage.data;\n\n\n  if (acpMessage.type === \"request_for_offer\") {\n    const relevantItems = seller.inventory.filter(\n      (item) =>\n        item.category === acpMessage.category &&\n        item.price <= acpMessage.maxPrice &&\n        item.quantity > 0\n    );\n\n    if (relevantItems.length === 0) {\n      return NextResponse.json({ status: \"no_offer\" });\n    }\n\n    const offeredItem = relevantItems[0];\n    const offer: Offer = {\n      type: \"offer\",\n      itemId: offeredItem.name,\n      price: offeredItem.price,\n    };\n\n    return NextResponse.json({ status: \"offer_sent\", offer });\n  } else if (acpMessage.type === \"accept_offer\") {\n    // EN: Simulate processing the accepted offer. // VI: Mô phỏng xử lý lời đề nghị đã được chấp nhận. // ES: Simular el procesamiento de la oferta aceptada.\n    const itemIndex = seller.inventory.findIndex(item => item.name === acpMessage.itemId);\n    if (itemIndex !== -1) {\n        seller.inventory[itemIndex].quantity -= 1;\n        return NextResponse.json({ status: \"offer_processed\", itemId: acpMessage.itemId });\n    } else {\n        return NextResponse.json({status: \"error\", message: \"Item not found in inventory.\"})\n    }\n\n  } else if (acpMessage.type === \"reject_offer\") {\n    // EN: Simulate processing the rejected offer. // VI: Mô phỏng xử lý lời đề nghị bị từ chối. // ES: Simular el procesamiento de la oferta rechazada.\n    return NextResponse.json({ status: \"offer_rejected\", itemId: acpMessage.itemId });\n  } else {\n    return NextResponse.json({ status: \"unknown_message_type\" });\n  }\n}\n\nasync function marketplaceAgent(\n    marketplace: MarketplaceAgent,\n    buyer: BuyerAgent,\n    seller: SellerAgent,\n    message: any\n): Promise<NextResponse> {\n    const parsedMessage = ACPMessageSchema.safeParse(message);\n\n    if (!parsedMessage.success) {\n        console.error(\"Invalid ACP message:\", parsedMessage.error);\n        return NextResponse.json({ status: \"error\", message: \"Invalid message format\" });\n    }\n\n    const acpMessage = parsedMessage.data;\n\n    if (acpMessage.type === \"request_for_offer\") {\n        //EN: Forward the request to the seller\n        const sellerResponse = await sellerAgent(seller, message)\n        return sellerResponse\n    } else if (acpMessage.type === \"offer\") {\n        // EN: Forward the offer to the buyer. // VI: Chuyển tiếp lời đề nghị cho người mua. // ES: Reenviar la oferta al comprador.\n        if (acpMessage.price <= buyer.preferences.maxPrice) {\n            const acceptOffer: AcceptOffer = {\n              type: \"accept_offer\",\n              itemId: acpMessage.itemId,\n            };\n            return NextResponse.json({ status: \"accepted\", offer: acpMessage });\n          } else {\n            const rejectOffer: RejectOffer = {\n              type: \"reject_offer\",\n              itemId: acpMessage.itemId,\n            };\n            return NextResponse.json({ status: \"rejected\", offer: acpMessage });\n          }\n\n    } else if (acpMessage.type === \"accept_offer\") {\n        // EN: Forward the acceptance to the seller. // VI: Chuyển tiếp sự chấp nhận cho người bán. // ES: Reenviar la aceptación al vendedor.\n        const sellerResponse = await sellerAgent(seller, acpMessage)\n        return sellerResponse\n    } else if (acpMessage.type === \"reject_offer\") {\n        // EN: Forward the rejection to the seller. // VI: Chuyển tiếp sự từ chối cho người bán. // ES: Reenviar el rechazo al vendedor.\n        const sellerResponse = await sellerAgent(seller, acpMessage)\n        return sellerResponse\n    } else {\n        return NextResponse.json({ status: \"unknown_message_type\" });\n    }\n}\n\n// EN: Export the agent choreography functions and schemas. // VI: Xuất các hàm và lược đồ biên đạo múa tác nhân. // ES: Exportar las funciones y esquemas de coreografía del agente.\nexport { buyerAgent, sellerAgent, marketplaceAgent, BuyerAgentSchema, SellerAgentSchema, MarketplaceAgentSchema, ACPMessageSchema };\nexport type { BuyerAgent, SellerAgent, MarketplaceAgent, ACPMessage };\n```",
  "spec_id": "AI-05"
}

Audit Trail (2)

25d agotask_completedVertex Flash
25d agotask_createdfoundry_swiss_race
Task ID: c14b97e0-5000-4f5f-8b5d-d6fcb8a6b35a