Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5e53757
Update app.js
priyankmodiPM Jun 25, 2026
fdd9572
Add discount image auto-reply for WhatsApp messages
Jun 26, 2026
4a26ed6
feat: replace static discount auto-reply with GPT tool-calling assist…
priyankmodiPM Jul 6, 2026
b1ed8d8
fix: regenerate lockfiles against the public npm registry (#2)
priyankmodiPM Jul 6, 2026
f5acca1
fix: regenerate yarn.lock against public npm registry (#3)
priyankmodiPM Jul 6, 2026
4fc8641
fix: declare OPENAI_API_KEY in render.yaml envVars
Jul 6, 2026
f7ee32e
fix: make OpenAI model/baseURL configurable and log request/error det…
Jul 6, 2026
272e14a
Feat/express edit flow (#4)
priyankmodiPM Jul 13, 2026
8bef9c0
Feat/real express api integration (#5)
priyankmodiPM Jul 16, 2026
4e7f47d
Cap discounts at 40%, add Hindi translation guidance, update graphic …
Jul 21, 2026
3909999
Turn allowed-edits reply into tappable quick-reply buttons (#6)
priyankmodiPM Jul 21, 2026
540a43e
Feat/edit options quick reply buttons (#7)
priyankmodiPM Jul 21, 2026
13d3bff
feat: add create_design flow for brand-new creatives (Onam) (#8)
varun6325 Jul 21, 2026
9cf20d7
fix: make Onam translate/edit routing robust for the 3-message demo flow
Jul 22, 2026
ea0f765
Feat/edit options quick reply buttons (#10)
priyankmodiPM Jul 22, 2026
61a7a1a
Merge pull request #9 from priyankmodiPM/fix/onam-malayalam-translate…
varun6325 Jul 22, 2026
2d3272e
refactor: split the two edit flows into self-contained modules
Jul 22, 2026
18391a2
Merge pull request #11 from priyankmodiPM/refactor/split-express-loca…
varun6325 Jul 22, 2026
1616d3d
feat(local): guided create flow with button follow-ups and image capt…
Jul 22, 2026
fd41439
feat(local): stream "work being done" and add a realistic generation …
Jul 22, 2026
2fd4cf3
fix(local): put the follow-up in the image caption so it can't preced…
Jul 22, 2026
346f202
Merge pull request #12 from priyankmodiPM/feat/local-guided-create-flow
varun6325 Jul 22, 2026
555526b
Add Edit Product/Discount/Price menu with Hinglish-mirrored replies (…
priyankmodiPM Jul 22, 2026
e0a820f
fix(local): give each TV model list row a unique id
Jul 22, 2026
6406aa5
fix(express): use S3 URL for TV placeholder image, not Scene7
Jul 22, 2026
595512e
fix(express): shrink TV model row ids below WhatsApp's 200-char limit
Jul 22, 2026
1c4fdce
fix(express): use fixed Diwali-offer caption, delay edit menu, add bu…
Jul 22, 2026
f578e63
fix(express): send numeric edit values as strings to generate-variation
Jul 22, 2026
8e4dce9
feat(local): switch Flow 2 to a personalised automobile-insurance offer
Jul 23, 2026
647b17b
fix(local): don't repeat the governance message after the salesman ac…
Jul 23, 2026
83e3236
feat(local): drop the price-governance step; merge two streaming lines
Jul 23, 2026
0df6bc6
fix(local): use https image URLs without cache-busting for reliable d…
Jul 23, 2026
d13afe9
fix(local): keep ?cache=off on the https offer image URLs
Jul 23, 2026
5ab4bf2
Merge pull request #14 from priyankmodiPM/feat/auto-insurance-flow
varun6325 Jul 23, 2026
38af5b3
Fix/tv image s3 presign and discount percentage (#15)
priyankmodiPM Jul 23, 2026
50301d7
Fix/tv image s3 presign and discount percentage (#16)
priyankmodiPM Jul 24, 2026
7a3f56d
fix(express): request the Sony TV source image as png-alpha from Scen…
priyankmodiPM Jul 24, 2026
abeaf39
feat(local): emoji-prefixed Yes/No + edit buttons, slower generation …
Jul 27, 2026
57e03a5
Merge pull request #18 from priyankmodiPM/feat/flow2-emoji-followups-…
varun6325 Jul 27, 2026
4fc9e47
fix(express): serve product-change requests from a hardcoded banner, …
priyankmodiPM Jul 27, 2026
4e0c2d2
fix(express): serve discount-change requests from a hardcoded banner …
priyankmodiPM Jul 27, 2026
0677190
feat(flow2): deterministic, phone-gated personalised-offer flow
Jul 27, 2026
dbfe13a
tune(flow2): speed up generation progress streaming (3500ms → 1500ms)
Jul 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
.DS_Store
.superpowers
.env
61 changes: 0 additions & 61 deletions app.js

This file was deleted.

3 changes: 3 additions & 0 deletions data/express-templates.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
{ "id": "img_1", "name": "Croma Diwali offer", "docId": "urn:aaid:sc:AP:4b4b25bb-0949-588e-bd7b-76d0e9a113bd" }
]
22 changes: 22 additions & 0 deletions data/offer-design.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"_comment": "Personalised customer offer used by create_design (source: 'local'). Two canned creatives — English and Hindi. Swap the image URLs for your hosted banners. Plans/featured drive the plan-picker buttons and the HQ price-floor governance in the system prompt.",
"images": {
"en": "https://s7ap1.scene7.com/is/image/varunAEM/banner-apoorva?cache=off",
"hi": "https://s7ap1.scene7.com/is/image/varunAEM/banner-apoorva-hindi?cache=off"
},
"plans": ["3-Yr Comprehensive", "Zero Dep + RSA", "Engine Protect combo"],
"featured": {
"plan": "3-Yr Comprehensive",
"price": "₹28,999/year",
"was": "₹52,499/year",
"savings": "₹23,500/year"
},
"defaults": { "customer": "Apoorva", "model": "Grand Vitara" },
"models": ["Grand Vitara", "Brezza", "Swift", "Baleno", "Ertiga", "Fronx", "Jimny", "Dzire", "Ciaz", "XL6"],
"slots": {
"editable": [
{ "name": "language", "type": "text", "aliases": ["lang", "translate", "translation", "headline", "text"] }
],
"locked": ["logo", "brand", "price", "plan", "product"]
}
}
64 changes: 64 additions & 0 deletions demo-auto-flow.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# Drives the personalised automobile-insurance offer flow (Flow 2) against a
# running webhook, one step at a time. Watch the server logs for `GPT chose
# action:` and `[edit:local] resolved image`.
#
# Usage: bash demo-auto-flow.sh
# BASE_URL=http://localhost:3000 PHONE=919899860983 bash demo-auto-flow.sh

set -euo pipefail

BASE_URL="${BASE_URL:-http://localhost:3000}"
PHONE="${PHONE:-919899860983}"
PAUSE="${PAUSE:-10}"
GEN_PAUSE="${GEN_PAUSE:-30}"

# Send a free-text WhatsApp message.
send() {
echo ">>> [text] $1"
curl -s -X POST "$BASE_URL/" -H 'Content-Type: application/json' -d "$(cat <<JSON
{"object":"whatsapp_business_account","entry":[{"changes":[{"value":{"messages":[
{"from":"$PHONE","type":"text","text":{"body":"$1"}}]}}]}]}
JSON
)" >/dev/null
echo " (200 ack — check server logs)"
echo
}

# Tap a reply button (WhatsApp interactive button_reply). Arg = button title.
tap() {
echo ">>> [tap button] $1"
curl -s -X POST "$BASE_URL/" -H 'Content-Type: application/json' -d "$(cat <<JSON
{"object":"whatsapp_business_account","entry":[{"changes":[{"value":{"messages":[
{"from":"$PHONE","type":"interactive","interactive":{"type":"button_reply","button_reply":{"id":"qr:$1","title":"$1"}}}]}}]}]}
JSON
)" >/dev/null
echo " (200 ack — check server logs)"
echo
}

echo "=== WhatsCraft personalised auto-insurance offer flow → $BASE_URL (phone: $PHONE) ==="
echo

# 1) Salesman asks for a personalised offer → WC asks which HQ-approved plan [buttons]
send "Apoorva test drove the Grand Vitara yesterday and asked for insurance options. Create a personalised offer for her."
sleep "$PAUSE"

# 2) Pick the plan → WC asks whether to add the salesman's contact [Yes/No]
tap "3-Yr Comprehensive"
sleep "$PAUSE"

# 3) Yes to contact → WC asks "anything else?" [Yes / No, go ahead]
tap "✅ Yes"
sleep "$PAUSE"

# 4) Nothing else → WC streams progress for a few seconds, then sends the English banner.
# Wait for that generation to finish before the next step so messages don't interleave.
tap "➡️ No, go ahead"
echo "... waiting ${GEN_PAUSE}s for generation to stream + finish ..."
sleep "$GEN_PAUSE"

# 5) Translate → WC streams briefly, then sends the Hindi banner
send "make it in Hindi"

echo "=== done — verify the two banners (English + Hindi) on WhatsApp and the tool choices in the logs ==="
26 changes: 26 additions & 0 deletions docs/diagrams/flow-express-catalog-edit.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
%% Flow A — Rajesh: edit an existing catalog design (image.source = "express")
%% Backed by the real Adobe Express API, with interactive quick-reply buttons.
%% Render: https://mermaid.live or any Mermaid-capable viewer.
flowchart TD
R1["User: 'what can I change?'"] --> CAE["tool: check_allowed_edits"]
CAE --> CAEa["actionCheckAllowedEdits<br/>image.source = express"]
CAEa --> EX1["expressApi.getTaggedDocument(docId)<br/>collectTaggedElements"]
EX1 --> BTN["buildEditOptions<br/>returns {edit_options, historyText}"]
BTN --> SEND1["sendEditOptions() → reply buttons<br/>id = 'edit:img_1:heading'"]

SEND1 -.->|"user taps a button"| TAP["webhook: messageTextForInteractiveReply()<br/>parse id → I'd like to change heading on image img_1"]
TAP --> ASK["tool: ask_for_more_information<br/>what would you like to change it to?"]
ASK -.->|"user replies with a value"| EG

R2["User: 'change the offer to 7500'"] --> EG["tool: edit_graphic"]
EG --> RT{"actionEditGraphic<br/>image.source?"}
RT -->|"express"| EXE["editExpressDesign"]
EXE --> V{"field is a tagged element?<br/>discount ≤ MAX_DISCOUNT?"}
V -->|"ok"| GEN["expressApi.generateVariation<br/>→ pollJobStatus → thumbnailUrl"]
GEN --> REC["recordEdits + sendImage(thumbnail)"]
V -->|"no"| REJ["reply: can't edit that field / discount capped"]

R3["User: 'change the product to a TV'"] --> STV["tool: select_tv_model"]
STV --> STVa["actionSelectTvModel → 3 model buttons<br/>id encodes full edits (buildValueEditId)"]
STVa -.->|"user taps e.g. LG UA82 AI"| TAP2["parse id → edits JSON → sentence → GPT"]
TAP2 --> EG
24 changes: 24 additions & 0 deletions docs/diagrams/flow-local-create-design.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
%% Flow B — Anjali: create + edit a brand-new design (image.source = "local")
%% No Express calls — resolves to canned image URLs in data/onam-design.json.
%% Render: https://mermaid.live or any Mermaid-capable viewer.
flowchart TD
A1["User: 'create a new design for Onam,<br/>LG washing machine + dishwasher, 20% off'"] --> CD["tool: create_design"]
CD --> CDa["actionCreateDesign<br/>loadOnamDesign + imageStore.createDesign<br/>(source = local, id = local_1)"]
CDa --> S1["sendImage(images.base)"]

A2["User: 'add my store address Princess Street Kochi'"] --> EG2["tool: edit_graphic"]
A3["User: 'translate the banner to Malayalam'"] --> EG3["tool: edit_graphic"]
EG2 --> RT{"actionEditGraphic<br/>image.source?"}
EG3 --> RT
RT -->|"local"| EL["editLocalDesign"]

EL --> M{"Malayalam request?<br/>(Malayalam script OR the word<br/>'Malayalam' in ANY key/value)"}
M -->|"yes"| MAL["short-circuit:<br/>appliedEdits = {language: 'Malayalam'}<br/>skip locked/palette guards"]
M -->|"no"| CANON["canonicalizeEdits (aliases)"]
CANON --> GUARD{"unknown key? → 'locked by HQ'<br/>background off-palette? → reject"}
GUARD -->|"ok"| RES["resolveLocalImage:<br/>address/background set → images.final<br/>else → images.base"]
MAL --> RESM["resolveLocalImage → images.malayalam"]
RES --> S2["recordEdits + sendImage(url)"]
RESM --> S2

RT -->|"express"| EXE["editExpressDesign<br/>(Adobe Express API — see other diagram)"]
Loading