Skip to content

Commit

Permalink
billions
Browse files Browse the repository at this point in the history
  • Loading branch information
lalalune committed Dec 11, 2024
1 parent 2df768d commit a4900a9
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 64 deletions.
73 changes: 31 additions & 42 deletions packages/plugin-dominos/src/PizzaOrderManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,9 @@ export class PizzaOrderManager implements OrderManager {
);
}

// Get next required action based on order state
getNextRequiredAction(order: Order, customer: Customer): string {
console.log("getNextRequiredAction: ", order, customer);
if (!order.items || order.items.length === 0) {
return "Collect initial pizza order details - show size, crust, and topping options to customer";
return "Collect initial pizza order details";
}

if (!customer.name) {
Expand All @@ -251,28 +249,20 @@ export class PizzaOrderManager implements OrderManager {
return "Request email for order confirmation";
}

if (order.paymentStatus === PaymentStatus.NOT_PROVIDED) {
return "Request credit card information";
if (!customer.paymentMethod) {
return "Request credit card information for payment";
}

if (order.paymentStatus === PaymentStatus.INVALID) {
return "Request alternative payment method";
}

if (
!order.progress.isConfirmed &&
order.paymentStatus === PaymentStatus.VALID
) {
if (!order.progress.isConfirmed) {
return "Review order details with customer and obtain final confirmation";
}

return "Provide order confirmation number and estimated delivery time";
}

getNextRequiredActionDialogue(order: Order, customer: Customer): string {
console.log("getNextRequiredActionDialogue: ", order, customer);
if (!order.items || order.items.length === 0) {
return "Let me help you build your perfect pizza! What size would you like? We have Small, Medium, Large and Extra Large. Then I can help you choose your crust type and toppings.";
return "Let me help you build your perfect pizza! What size would you like?";
}

if (!customer.name) {
Expand All @@ -284,29 +274,22 @@ export class PizzaOrderManager implements OrderManager {
}

if (!customer.address) {
return "Where would you like your pizza delivered? Please provide your complete delivery address.";
return "Where would you like your pizza delivered?";
}

if (!customer.email) {
return "What email address should we send your order confirmation to?";
}

if (order.paymentStatus === PaymentStatus.NOT_PROVIDED) {
return "Great! To process your order, I'll need your credit card information. Could you please provide your card number?";
if (!customer.paymentMethod) {
return "To complete your order, I'll need your credit card information. Could you please provide your card number, expiration date (MM/YY), CVV, and billing zip code?";
}

if (order.paymentStatus === PaymentStatus.INVALID) {
return "I apologize, but there seems to be an issue with that payment method. Could you please provide a different credit card?";
if (!order.progress.isConfirmed) {
return "Great! I have all your information. Would you like me to review everything before placing your order?";
}

if (
!order.progress.isConfirmed &&
order.paymentStatus === PaymentStatus.VALID
) {
return "Perfect! I have all your order details. Would you like me to review everything with you before finalizing your order?";
}

return "Great news! Your order is confirmed. Let me get your confirmation number and estimated delivery time for you.";
return "Your order is confirmed! Let me get your confirmation number and estimated delivery time.";
}

// Get topping category and price
Expand Down Expand Up @@ -628,13 +611,17 @@ export class PizzaOrderManager implements OrderManager {

// Calculate order progress
calculateOrderProgress(order: Order, customer: Customer): OrderProgress {
console.log("calculateOrderProgress: ", order, customer);
return {
hasCustomerInfo: !this.validateCustomerInfo(customer),
hasPaymentMethod: order.paymentMethod !== undefined,
hasValidPayment:
order.paymentStatus === PaymentStatus.VALID ||
order.paymentStatus === PaymentStatus.PROCESSED,
hasCustomerInfo: Boolean(
customer.name &&
customer.phone &&
customer.email &&
customer.address
),
hasPaymentMethod: Boolean(customer.paymentMethod),
hasValidPayment: Boolean(
customer.paymentMethod && order.payments?.[0]?.isValid
),
isConfirmed: order.status === OrderStatus.CONFIRMED,
};
}
Expand Down Expand Up @@ -714,14 +701,16 @@ export class PizzaOrderManager implements OrderManager {
order.progress = this.calculateOrderProgress(order, customer);

// Update order status based on current state
if (!order.progress.hasCustomerInfo) {
order.status = OrderStatus.AWAITING_CUSTOMER_INFO;
} else if (!order.progress.hasValidPayment) {
order.status = OrderStatus.AWAITING_PAYMENT;
} else if (!order.progress.isConfirmed) {
order.status = OrderStatus.PROCESSING;
} else {
order.status = OrderStatus.CONFIRMED;
if (order.progress) {
if (!order.progress.hasCustomerInfo) {
order.status = OrderStatus.AWAITING_CUSTOMER_INFO;
} else if (!order.progress.hasValidPayment) {
order.status = OrderStatus.AWAITING_PAYMENT;
} else if (!order.progress.isConfirmed) {
order.status = OrderStatus.PROCESSING;
} else {
order.status = OrderStatus.CONFIRMED;
}
}

return order;
Expand Down
58 changes: 58 additions & 0 deletions packages/plugin-dominos/src/actions/confirmOrder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Action, IAgentRuntime, Memory } from "@ai16z/eliza";
import { PizzaOrderManager } from "../PizzaOrderManager";
import { OrderStatus } from "../types";

export const confirmOrder: Action = {
name: "CONFIRM_ORDER",
similes: ["FINALIZE_ORDER", "FINISH_ORDER", "PLACE_ORDER"],
examples: [
// TODO
],
description: "Confirms and places the final order with Dominos",
validate: async (runtime: IAgentRuntime, message: Memory) => {
const orderManager = new PizzaOrderManager(runtime);
const userId = message.userId;
const order = await orderManager.getOrder(userId);
const customer = await orderManager.getCustomer(userId);

if (!order || !customer) return false;

// Only valid if we have complete customer info and valid payment
return (
order.progress &&
order.progress.hasCustomerInfo &&
order.progress.hasValidPayment &&
!order.progress.isConfirmed
);
},
handler: async (runtime: IAgentRuntime, message: Memory) => {
const orderManager = new PizzaOrderManager(runtime);
const userId = message.userId;
const order = await orderManager.getOrder(userId);
const customer = await orderManager.getCustomer(userId);

try {
// Final validation with Dominos
await order.validate();

// Get final pricing
await order.price();

// Place the order
await order.place();

// Update order status
order.status = OrderStatus.CONFIRMED;
await orderManager.saveOrder(userId, order);

return (
`Great news! Your order has been confirmed and is being prepared.\n\n` +
`Order Number: ${order.orderID}\n` +
`Estimated Delivery Time: ${order.estimatedWaitMinutes} minutes\n\n` +
orderManager.getOrderSummary(order, customer)
);
} catch (error) {
return "There was an issue placing your order: " + error.message;
}
},
};
69 changes: 51 additions & 18 deletions packages/plugin-dominos/src/actions/updateCustomer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
ModelClass,
State,
} from "@ai16z/eliza";
import { Customer } from "dominos";
import { Customer, Payment } from "dominos";
import { z } from "zod";
import { PizzaOrderManager } from "../PizzaOrderManager";

Expand All @@ -22,6 +22,14 @@ const CustomerSchema = z.object({
.optional(),
email: z.string().email().optional(),
address: z.string().min(10).optional(),
paymentMethod: z
.object({
cardNumber: z.string().regex(/^\d{16}$/),
expiryDate: z.string().regex(/^(0[1-9]|1[0-2])\/([0-9]{2})$/),
cvv: z.string().regex(/^\d{3,4}$/),
postalCode: z.string().regex(/^\d{5}$/),
})
.optional(),
});

export const handler: Handler = async (
Expand All @@ -45,24 +53,31 @@ export const handler: Handler = async (

// Extract customer details using LLM and schema
const extractionTemplate = `
Extract customer information from the following conversation. Keep existing information if not mentioned in the update.
Current customer information:
Name: ${customer.name || "Not provided"}
Phone: ${customer.phone || "Not provided"}
Email: ${customer.email || "Not provided"}
Address: ${customer.address || "Not provided"}
{{recentConversation}}
Provide updated customer information as a JSON object, including only fields that should be changed:
{
"name": string (optional),
"phone": string (optional, format: XXX-XXX-XXXX),
"email": string (optional, valid email),
"address": string (optional, full delivery address)
Extract customer information from the following conversation. Keep existing information if not mentioned in the update.
Current customer information:
Name: ${customer.name || "Not provided"}
Phone: ${customer.phone || "Not provided"}
Email: ${customer.email || "Not provided"}
Address: ${customer.address || "Not provided"}
Payment: ${customer.paymentMethod ? "Provided" : "Not provided"}
{{recentConversation}}
Provide updated customer information as a JSON object, including only fields that should be changed:
{
"name": string (optional),
"phone": string (optional, format: XXX-XXX-XXXX),
"email": string (optional, valid email),
"address": string (optional, full delivery address),
"paymentMethod": {
"cardNumber": string (16 digits),
"expiryDate": string (MM/YY),
"cvv": string (3-4 digits),
"postalCode": string (5 digits)
}
`;
}
`;

const context = composeContext({
state,
Expand All @@ -83,6 +98,24 @@ export const handler: Handler = async (
if (customerUpdates.email) customer.email = customerUpdates.email;
if (customerUpdates.address) customer.address = customerUpdates.address;

// Update the handler logic
if (customerUpdates.paymentMethod) {
// Create Dominos Payment object
const payment = new Payment({
number: customerUpdates.paymentMethod.cardNumber,
expiration: customerUpdates.paymentMethod.expiryDate,
securityCode: customerUpdates.paymentMethod.cvv,
postalCode: customerUpdates.paymentMethod.postalCode,
amount: order.amountsBreakdown.customer,
});

// Clear existing payments and add new one
order.payments = [payment];

// Update customer payment method
customer.paymentMethod = customerUpdates.paymentMethod;
}

await orderManager.saveCustomer(userId, customer);

// Process updated order
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-dominos/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { pizzaOrderProvider } from "./providers/pizzaOrder.ts";
import { endOrder } from "./actions/endOrder.ts";
import { updateCustomer } from "./actions/updateCustomer.ts";
import { updateOrder } from "./actions/updateOrder.ts";
import { confirmOrder } from "./actions/confirmOrder.ts";

export * as actions from "./actions/index.ts";
export * as providers from "./providers/index.ts";

export const dominosPlugin: Plugin = {
name: "dominos",
description: "Order a dominos pizza",
actions: [startOrder, endOrder, updateCustomer, updateOrder],
actions: [startOrder, endOrder, updateCustomer, updateOrder, confirmOrder],
providers: [pizzaOrderProvider],
};
23 changes: 21 additions & 2 deletions packages/plugin-dominos/src/providers/pizzaOrder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IAgentRuntime, Memory, Provider } from "@ai16z/eliza";
import { OrderStatus } from "../types";
import { PizzaOrderManager } from "../PizzaOrderManager";
import { OrderStatus, PaymentStatus } from "../types";

export const pizzaOrderProvider: Provider = {
get: async (runtime: IAgentRuntime, message: Memory) => {
Expand All @@ -13,7 +13,26 @@ export const pizzaOrderProvider: Provider = {
return "No active pizza order. The customer needs to start a new order.";
}

let context = "=== PIZZA ORDER STATUS ===\n\n";
// Add payment-specific status to context
let context = "\nPAYMENT STATUS:\n";
context += `Current Status: ${order.paymentStatus}\n`;
if (order.paymentStatus === PaymentStatus.NOT_PROVIDED) {
context += "Payment information needed to complete order.\n";
} else if (order.paymentStatus === PaymentStatus.INVALID) {
context +=
"Previous payment method was invalid. Please provide new payment information.\n";
}

// Add clearer next action guidance
if (order.status === OrderStatus.AWAITING_PAYMENT) {
context +=
"\nREQUIRED: Please provide credit card information to complete your order.\n";
} else if (order.status === OrderStatus.PROCESSING) {
context +=
"\nREQUIRED: Please review your order and confirm to place it.\n";
}

context += "=== PIZZA ORDER STATUS ===\n\n";

// Add order summary
context += orderManager.getOrderSummary(order, customer);
Expand Down
16 changes: 15 additions & 1 deletion packages/plugin-dominos/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@ enum OrderStatus {
NEW = "NEW",
AWAITING_CUSTOMER_INFO = "AWAITING_CUSTOMER_INFO",
AWAITING_PAYMENT = "AWAITING_PAYMENT",
AWAITING_CONFIRMATION = "AWAITING_CONFIRMATION",
PROCESSING = "PROCESSING",
CONFIRMED = "CONFIRMED",
FAILED = "FAILED",
}

interface Order {
status: OrderStatus;
paymentStatus: PaymentStatus;
paymentMethod?: PaymentMethod;
customer?: Customer;
items?: OrderItem[];
}

// Order progress tracking
interface OrderProgress {
hasCustomerInfo: boolean;
Expand Down Expand Up @@ -42,7 +51,12 @@ interface Customer {
phone: string;
email: string;
address: string;
paymentMethods?: PaymentMethod[];
paymentMethod?: {
cardNumber?: string;
expiryDate?: string;
cvv?: string;
postalCode?: string;
};
isReturning: boolean;
}

Expand Down

0 comments on commit a4900a9

Please sign in to comment.