返回技能库

Zepto

在几秒钟内通过 Zepto 订购杂货。只需说出你需要的东西,就会在 WhatsApp 上收到一个付款链接,在手机上付款即可完成。会记住你常买的物品。在 Zepto 提供配送的印度各地均可使用。

作者:bewithgaurav · 最新版本:1.0.6

收藏:0 · 下载:1.2k

说明文档

# zepto

**Order groceries from Zepto in 30 seconds. From chat to checkout.**

Tell your AI what you need. It shops, generates a payment link, sends it to WhatsApp. You pay on your phone. Groceries arrive in 10 minutes.

## 💬 Examples

**Quick orders:**
```
"Order milk and bread from Zepto"
"Add vegetables - tomatoes, onions, potatoes"  
"Get me Amul butter and cheese"
```

**Your usuals:**
```
"Add my usual milk" → AI picks the brand you always order
"Order the usual groceries" → AI suggests your frequent items
```

**Full shopping list:**
```
"Add milk, bread, eggs, coriander, ginger, and tea bags"
→ AI adds everything, shows total: ₹X
→ Sends payment link to WhatsApp
→ You pay, groceries arrive
```

---

## 🔒 Security & Privacy

**What this skill does:**
- ✅ Browser automation on zepto.com (your local browser, your session)
- ✅ Stores order history locally in `~/.openclaw/skills/zepto/order-history.json` (local file, not shared)
- ✅ Sends payment links via WhatsApp (requires your consent for each order)
- ✅ All authentication happens through Zepto's official flow (Phone + OTP)

**What this skill does NOT do:**
- ❌ No automatic payments (you must click the link and pay manually)
- ❌ No data sent to external servers (except Zepto.com and WhatsApp via your channels)
- ❌ No persistent background jobs (optional one-time order status check only if you approve)
- ❌ No storage of payment info or OTPs
- ❌ No access to your banking/UPI apps

**Data Storage:**
- Order history: `~/.openclaw/skills/zepto/order-history.json` (local only, helps with "usuals" feature)
- Browser session: Managed by OpenClaw's browser (standard Chrome/Chromium profile)

**User Control:**
- You control when to order
- You approve each payment link
- You can delete order history file anytime
- All browser actions happen in your profile with your visibility

---

## 🚨 CRITICAL WORKFLOW RULES

**ALWAYS follow this order when building an order:**

### Rule 1: CHECK CART FIRST
```bash
# Before adding ANY items, ALWAYS check cart state
node zepto-agent.js get-cart
```

**Why:** Cart may have items from previous sessions. Adding duplicates is wasteful.

### Rule 2: Use smart-shop (RECOMMENDED)
```bash
# This handles everything: clears unwanted, checks duplicates, adds missing
node zepto-agent.js smart-shop "milk, bread, eggs"
```

**What it does:**
1. Checks current cart state
2. Clears existing items (if any)
3. For each item: checks if already in cart → skips if present → adds only if missing
4. Returns: `{ added: [], skipped: [], failed: [] }`

### Rule 3: NEVER take screenshots unless snapshot data is insufficient
- Snapshot shows all refs, buttons, text
- Screenshot is ONLY for visual debugging when snapshot is truncated or unclear
- **In 99% of cases, snapshot is enough**

### Rule 4: Detect "already in cart" signals
When you see in snapshot:
```
"Decrease quantity 1 Increase quantity"  → Item is IN CART
button "Remove" [ref=eXX]                 → Item is IN CART
```

**DO NOT** click "ADD" when you see these signals!

---

## Complete Flow
1. **Authentication** - Phone + OTP verification
2. **Address Confirmation** - Verify delivery location
3. **Shopping** - Search & add items (with YOUR usuals prioritized!)
4. **Payment Link** - Generate & send Juspay link via WhatsApp

---

## Step 0: Order History & Usuals

**Your order history is tracked in:** `{SKILL_DIR}/order-history.json`

(Where `{SKILL_DIR}` is your skill directory, typically `~/.openclaw/skills/zepto/`)

**Smart Selection Logic:**
1. When user requests an item (e.g., "add milk")
2. Check `order-history.json` for that category
3. **If ordered 2+ times** → Auto-add your most-ordered variant
4. **If ordered 0-1 times** → Show options and ask for selection

### Automated Order History Scraper

**When to run:** User says "update my zepto history" or "refresh order history"

**Process:**
1. Navigate to account page
2. Get all delivered order URLs
3. Visit each order sequentially
4. Extract items using DOM scraping
5. Build frequency map
6. Save to `order-history.json`

**Implementation:**
```bash
# Step 1: Navigate to account page
browser navigate url=https://www.zepto.com/account profile=openclaw

# Step 2: Extract order URLs
browser act profile=openclaw request='{"fn":"() => { const orders = []; document.querySelectorAll(\"a[href*=\\\"/order/\\\"]\").forEach(link => { if (link.href.includes(\"isArchived=false\") && link.textContent.includes(\"delivered\")) { orders.push(link.href); } }); return [...new Set(orders)]; }", "kind":"evaluate"}'
# Returns array of order URLs

# Step 3: For each order URL:
browser navigate url={order_url} profile=openclaw

# Step 4: Extract items from order page
browser act profile=openclaw request='{"fn":"() => { const items = []; document.querySelectorAll(\"*\").forEach(el => { const text = el.textContent; if (text.match(/\\d+\\s*unit/i)) { const parent = el.closest(\"div\"); if (parent) { const lines = parent.textContent.split(\"\\n\").map(l => l.trim()).filter(l => l && l.length > 5 && l.length < 100); if (lines[0]) { const qtyMatch = text.match(/(\\d+)\\s*unit/i); items.push({ name: lines[0], quantity: qtyMatch ? parseInt(qtyMatch[1]) : 1 }); } } } }); const uniqueItems = {}; items.forEach(item => { if (!uniqueItems[item.name]) uniqueItems[item.name] = item; }); return Object.values(uniqueItems); }", "kind":"evaluate"}'
# Returns array of {name, quantity}

# Step 5: Aggregate all items into frequency map
# Build JSON structure with counts

# Step 6: Write to file
write path={SKILL_DIR}/order-history.json content={json_data}
```

**Automated scraper advantages:**
- ✅ No manual screenshot review
- ✅ Faster (visits all orders programmatically)
- ✅ Always up-to-date
- ✅ Can re-run anytime

**Example:**
```
User: "Update my Zepto order history"

Response:
"🔍 Scanning your Zepto orders...
📦 Found 6 delivered orders
🔄 Extracting items...
✅ Updated! Found:
   - Coriander: 4 orders
   - Milk: 3 orders
   - Bread: 2 orders
   - Potato: 2 orders
   + 15 other items

Your usuals are ready!"
```

---

**Smart Selection Logic (Using History):**

**Example:**
```
User: "Add milk"

[Check order-history.json]
→ "Amul Taaza Toned Fresh Milk | Pouch (500ml)" ordered 3x

Response:
"🥛 Adding your usual milk!
Amul Taaza Toned Fresh Milk (500ml) - ₹29
📊 You've ordered this 3 times
✅ Added to cart"
```

**If only ordered once or never:**
```
User: "Add milk"

[Check order-history.json]
→ "Amul Taaza" ordered 1x only

Response:
"🥛 Found some milk options:
1. Amul Taaza Toned (500ml) - ₹29 ⭐ 4.8 (100k) - You've ordered this once
2. Amul Gold (1L) - ₹68 ⭐ 4.9 (80k) - Most popular
3. Mother Dairy (500ml) - ₹30 ⭐ 4.7 (60k)

Which one? (or tell me a number)"
```

**Update order history:** After each successful order, update the JSON file with new items.

---

## Step 1: Authentication (First Time Only)

**Check if already logged in:**
```bash
browser open url=https://www.zepto.com profile=openclaw
browser snapshot --interactive profile=openclaw
# Look for "login" button vs "profile" link
```

**If NOT logged in, start auth flow:**

### 1.1: Get Phone Number
Ask user: "What's your phone number for Zepto? (10 digits)"

### 1.2: Enter Phone & Request OTP
```bash
# Click login button
browser act profile=openclaw request='{"kind":"click","ref":"{login_button_ref}"}'

# Type phone number
browser act profile=openclaw request='{"kind":"type","ref":"{phone_input_ref}","text":"{phone}"}'

# Click Continue
browser act profile=openclaw request='{"kind":"click","ref":"{continue_button_ref}"}'
```

### 1.3: Get OTP from User
Ask user: "I've sent the OTP to {phone}. What's the OTP you received?"

### 1.4: Enter OTP
```bash
browser snapshot --interactive profile=openclaw  # Get OTP input refs
browser act profile=openclaw request='{"kind":"type","ref":"{otp_input_ref}","text":"{otp}"}'
# OTP auto-submits after 6 digits
```

**Result:** User is now logged in! Session persists across browser restarts.

---

## Step 2: Address Confirmation

**🚨 CRITICAL: ALWAYS CHECK ADDRESS BEFORE PROCEEDING WITH ANY SHOPPING!**

### Address Selection Rules

**Default behavior:**
1. Most users have multiple saved addresses (Home, Office, etc.)
2. **ALWAYS show current address and ASK for confirmation** - never assume
3. Check what was used in the last order (if order history exists)
4. Wait for explicit user confirmation before proceeding

**On homepage, address is visible in the header:**
```bash
browser snapshot --interactive profile=openclaw
# Look for button with heading level=3 containing the address
# Example ref: e16 with text like "Home - [Address Details]..."
# Delivery time shown nearby (e.g., "10 minutes")
```

**ALWAYS ask user to confirm before shopping:**
```
📍 I see your delivery address is set to:
{Address Name} - {Full Address}
⏱️ Delivery in ~{X} minutes

Is this correct? Should I proceed with this address?
```

### Programmatic Address Selection (NEW!)

**Use the `zepto-agent.js select-address` command:**

```bash
node zepto-agent.js select-address "Home"
node zepto-agent.js select-address "sanskar"     # Fuzzy matching works!
node zepto-agent.js select-address "kundu blr"
```

**How it works:**
1. **Fuzzy matching** - Case-insensitive, partial match supported
   - "sanskar" → "Sanskar Blr" ✅
   - "home" → "New Home" ✅
   - "kundu" → "Kundu Blr" ✅
2. **Already-selected detection** - Skips if you're already at that address
3. **Verification** - Confirms address change in header after click

**Example:**
```bash
# Current address: "Kundu Blr"
node zepto-agent.js select-address "sanskar"

# Output:
# ℹ️ Opening Zepto...
# ✅ Zepto opened
# ℹ️ 📍 Selecting address: "sanskar"
# ℹ️ Current: Kundu Blr
# ✅ Clicked: Sanskar BlrA-301, A, BLOCK-B...
# 🎉 Address changed to: Sanskar blr
```

**When user says "change address to X" or "deliver to X":**
```bash
# Just call the command with their address name/query
node zepto-agent.js select-address "{user_query}"
```

**No manual modal navigation needed!** The script handles:
- Opening the address modal
- Finding the address (fuzzy match)
- Clicking it
- Verifying the change
- Closing the modal

**Manual Selection (Fallback):**
If the programmatic method fails or address isn't found:

```bash
# Click the address button (ref e16 or similar)
browser act profile=openclaw request='{"kind":"click","ref":"e16"}'
# This opens address selection modal with all saved addresses
```

**Select address using JavaScript:**
```bash
# Replace {USER_ADDRESS_NAME} with the actual address name user selected
browser act profile=openclaw request='{"fn":"() => { const input = document.querySelector('input[placeholder*=\"address\"]'); if (!input) return { error: 'Modal not found' }; let modal = input; for (let i = 0; i < 15; i++) { if (!modal.parentElement) break; modal = modal.parentElement; if (window.getComputedStyle(modal).position === 'fixed') break; } const divs = Array.from(modal.querySelectorAll('div')); const match = divs.find(d => d.textContent && d.textContent.trim().startsWith('{USER_ADDRESS_NAME}')); if (!match) return { error: 'Address not found' }; let p = match; for (let i = 0; i < 10; i++) { if (!p) break; const s = window.getComputedStyle(p); if (p.onclick || p.getAttribute('onClick') || s.cursor === 'pointer') { p.scrollIntoView({ block: 'center' }); setTimeout(() => {}, 300); p.click(); return { clicked: true, text: match.textContent.substring(0, 100) }; } p = p.parentElement; } return { error: 'No clickable parent' }; }()","kind":"evaluate"}'
```

**After address confirmed by user:**
```
✅ Delivery address confirmed: {address_name}
📍 {full_address}
⏱️ ETA: {eta} mins

Ready to shop! What would you like to add to cart?
```

**⚠️ Address is CRITICAL - never skip this step!**

---

## Step 3: Shopping

### 3A: Discovery Mode (Browse & Explore)

When user asks to "explore", "show me", "what's good", "find something", or "discover":

**Common Discovery Patterns:**
- "Show me healthy snacks under ₹50"
- "What's good in da...