Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2cca306
Merge branch 'main' of github.com:facebookresearch/OpenApps
aaronsmulktis Sep 8, 2026
378ddc4
[Tweak] Ignore nested git worktrees
aaronsmulktis Aug 31, 2026
b8814bd
[Feature] Rewrite the online shop without the JDK
aaronsmulktis Aug 31, 2026
6c7b2f8
[Fix] Cart line totals, shop navigation, and readable table names
aaronsmulktis Aug 31, 2026
e6c6cb5
[Docs] Document the rewritten online shop
aaronsmulktis Sep 1, 2026
6b857a0
[Improvement] Draw product category line art instead of initials
aaronsmulktis Sep 1, 2026
fe1c3ec
[Improvement] Build the shop catalog from the WebShop dataset
aaronsmulktis Sep 2, 2026
214ea78
[Improvement] Add an opt-in hotlinked product image carousel
aaronsmulktis Sep 2, 2026
9e96505
[Fix] Import apps as open_apps, not the legacy src.open_apps prefix
aaronsmulktis Sep 3, 2026
768985f
Add missing read-only navigate_to_onlineshop
aaronsmulktis Sep 14, 2026
d5b5db8
[Improvement] Commit the WebShop catalog and hotlink it by default
aaronsmulktis Sep 14, 2026
981eac7
[Improvement] Take the shop catalog to the full 1k WebShop dump
aaronsmulktis Sep 14, 2026
d28c1be
[Improvement] Align the shop bar and CTA rows, drop the Java narrative
aaronsmulktis Sep 14, 2026
fc44643
[Improvement] Make webshop the shop's default content pack
aaronsmulktis Sep 14, 2026
bf12217
Tweak styles, tweak run names
aaronsmulktis Sep 15, 2026
5b2d403
Merge branch 'main' into aaronsmulktis/shop-with-bank
aaronsmulktis Sep 17, 2026
1de636c
[Fix] Drop the include_onlineshop gate from the screenshot variation …
aaronsmulktis Sep 17, 2026
650ce94
[Feature] Give OpenBanking cards a CVV and an authorization path
aaronsmulktis Sep 17, 2026
020778d
[Feature] Pay for shop orders with an OpenBanking credit card
aaronsmulktis Sep 17, 2026
ef9ac60
[Feature] Score a shop purchase paid with an OpenBanking card
aaronsmulktis Sep 18, 2026
e5ab265
[Tweaks] changes:
aaronsmulktis Sep 25, 2026
c44c5d3
Merge branch 'main' of github.com:facebookresearch/OpenApps
aaronsmulktis Sep 28, 2026
be0a58b
Merge aaronsmulktis/webshop-rewrite into aaronsmulktis/shop-with-bank
aaronsmulktis Oct 5, 2026
f4686cd
[Fix] fail fast on a missing vLLM hostname; log run errors to W&B
aaronsmulktis Oct 8, 2026
3972499
[Feature] scripts/serve_vllm.sbatch for a persistent vLLM server
aaronsmulktis Oct 8, 2026
189808c
Merge branch 'main' of github.com:aaronsmulktis/OpenApps
aaronsmulktis Oct 12, 2026
fb337ea
Merge main into aaronsmulktis/shop-with-bank
aaronsmulktis Oct 13, 2026
57e405b
[Test] Give coherence tests a placeholder vLLM hostname
aaronsmulktis Oct 14, 2026
7c76894
[Fix] Record declined card authorizations; reject past or malformed e…
aaronsmulktis Oct 16, 2026
7f1abbd
[Fix] Restore the GPT-5.5 model alias in GPT-5.5-computer-use
aaronsmulktis Oct 19, 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
23 changes: 20 additions & 3 deletions config/apps/onlineshop/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ database_path: ${databases_dir}/onlineshop.db
# Override for just this app with `apps.onlineshop.theme=solarized`.
theme: null

# --- Behaviour -------------------------------------------------------------

# `enable=False` hides the shop outright.
#
# One subtlety: the shop is hidden rather than broken when it has nothing to
Expand All @@ -30,10 +32,25 @@ theme: null
# `apps/onlineshop/content=default`. See `content/default.yaml`.
enable: True

# --- Payment ---------------------------------------------------------------

# With the check on, checkout asks for a card number, expiry, CVV and
# cardholder name and matches them against a credit card seeded in the
# OpenBanking app, which also holds the available credit the purchase is
# authorized against. Turn it off for a shop that takes any order.
enable_credit_card_check: true

# Card networks this shop accepts, matched against the `card_brand` of the card
# on file -- not against anything the shopper types. An empty list accepts
# every brand the bank knows about.
allowed_credit_cards:
- 'Visa'
- 'MasterCard'
enable_credit_card_check: false
- 'Meridian'

# What the charge is called in the bank's ledger. `{order_id}` is substituted
# with the shop's order id, so a ledger row can be traced back to an order. A
# refused charge is recorded under the same string with the order id dropped
# ('OPENAPPS SHOP'), since a declined checkout never writes the order.
card_descriptor: 'OPENAPPS SHOP {order_id}'

# Products per page in listings and search results.
products_per_page: 10
Expand Down
4 changes: 3 additions & 1 deletion config/apps/onlineshop/layout/default.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# @package apps.onlineshop
# Structure only -- no colors/fonts (those come from the shared theme).
# Structure only -- colors and fonts come from the shared theme
# (`config/apps/theme/`). Select with `apps/onlineshop/layout=<name>`.
#
# One product per row: image left, details right.
layout: default
20 changes: 20 additions & 0 deletions config/apps/openbanking/content/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ hide_number_label: "Hide number"
# (what is owed, the least they can pay, and by when) rather than a balance.
card_number_label: "Card number"
card_expires_label: "Expires"
card_cvv_label: "CVV"
payment_heading: "Payment"
statement_balance_label: "Statement balance"
minimum_payment_label: "Minimum payment due"
Expand Down Expand Up @@ -94,6 +95,24 @@ column_labels:
# the account/routing disclosure) or `credit_card` (the card graphic and the
# payment panel). Omitted means `deposit`, so the noise variants can append a
# plain checking account without restating it.

# --- Payment rows ----------------------------------------------------------
# The online shop posts a card charge through `authorize_card_purchase`; these
# are the strings it writes into the ledger, and the messages it hands back to
# the shopper. Declines stay vague on purpose -- naming the wrong field would
# let an agent brute-force the CVV.
purchase_type: "Card"
overlimit_type: "Fee"
overlimit_description: "OVERLIMIT NOTICE - credit limit exceeded by {amount}"
# A refused charge posts one zero-amount row so the attempt is on record.
# `{amount}` is what was attempted, never the shortfall.
declined_type: "Declined"
declined_description: "DECLINED - {merchant} {amount} - insufficient available credit"
charge_approved_message: "Payment approved."
charge_declined_message: "Card declined. Check the card details and try again."
charge_insufficient_message: "Card declined for insufficient available credit."
charge_unavailable_message: "Card payments are unavailable right now."

accounts:
- name: "BUS COMPLETE CHK (...5555)"
kind: deposit
Expand Down Expand Up @@ -211,6 +230,7 @@ accounts:
routing_number: null
card_brand: "Meridian"
card_expiration: "09/29"
card_cvv: "418"
available_balance: 0.00
present_balance: -1284.19
available_credit: 8715.81
Expand Down
16 changes: 16 additions & 0 deletions config/apps/openbanking/content/german.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ hide_number_label: "Nummer ausblenden"

card_number_label: "Kartennummer"
card_expires_label: "Gültig bis"
card_cvv_label: "Prüfziffer"
payment_heading: "Zahlung"
statement_balance_label: "Abrechnungssaldo"
minimum_payment_label: "Mindestzahlung fällig"
Expand Down Expand Up @@ -55,6 +56,20 @@ column_labels:
amount: "Betrag"
balance: "Saldo"


# --- Zahlungszeilen --------------------------------------------------------
# Siehe `default.yaml`: die Zeilen, die der Online-Shop bei einer
# Kartenzahlung in das Kontoblatt schreibt.
purchase_type: "Karte"
overlimit_type: "Gebühr"
overlimit_description: "HINWEIS ÜBERZIEHUNG - Kreditlimit überschritten um {amount}"
declined_type: "Abgelehnt"
declined_description: "ABGELEHNT - {merchant} {amount} - nicht genügend verfügbarer Kredit"
charge_approved_message: "Zahlung genehmigt."
charge_declined_message: "Karte abgelehnt. Bitte Kartendaten prüfen und erneut versuchen."
charge_insufficient_message: "Karte abgelehnt: nicht genügend verfügbarer Kredit."
charge_unavailable_message: "Kartenzahlungen sind derzeit nicht möglich."

accounts:
- name: "BUS COMPLETE CHK (...5555)"
kind: deposit
Expand Down Expand Up @@ -153,6 +168,7 @@ accounts:
routing_number: null
card_brand: "Meridian"
card_expiration: "09/29"
card_cvv: "418"
available_balance: 0.00
present_balance: -1284.19
available_credit: 8715.81
Expand Down
15 changes: 15 additions & 0 deletions config/apps/openbanking/content/mandarin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ hide_number_label: "隐藏号码"

card_number_label: "卡号"
card_expires_label: "有效期至"
card_cvv_label: "安全码"
payment_heading: "还款"
statement_balance_label: "账单余额"
minimum_payment_label: "最低还款额"
Expand Down Expand Up @@ -53,6 +54,19 @@ column_labels:
amount: "金额"
balance: "余额"


# --- 付款记录 --------------------------------------------------------------
# 参见 `default.yaml`:网上商店刷卡付款时写入账单的记录行。
purchase_type: "银行卡"
overlimit_type: "手续费"
overlimit_description: "超限通知 - 超出信用额度 {amount}"
declined_type: "已拒绝"
declined_description: "已拒绝 - {merchant} {amount} - 可用信用额度不足"
charge_approved_message: "付款已批准。"
charge_declined_message: "银行卡被拒绝。请检查卡片信息后重试。"
charge_insufficient_message: "银行卡被拒绝:可用信用额度不足。"
charge_unavailable_message: "目前无法使用银行卡付款。"

accounts:
- name: "BUS COMPLETE CHK (...5555)"
kind: deposit
Expand Down Expand Up @@ -150,6 +164,7 @@ accounts:
routing_number: null
card_brand: "Meridian"
card_expiration: "09/29"
card_cvv: "418"
available_balance: 0.00
present_balance: -1284.19
available_credit: 8715.81
Expand Down
18 changes: 18 additions & 0 deletions config/apps/openbanking/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,21 @@ database_path: ${databases_dir}/openbanking.db
# deliberately no bank-specific theme: the point of the shared theme group is
# that a sweep can restyle every app at once.
theme: null

# --- Payments --------------------------------------------------------------

# How far past a card's `available_credit` a purchase may still authorize, in
# dollars. The grace band is what makes "check the balance before you buy" a
# real decision rather than a hard wall: an agent that ignores the figure
# mostly gets away with it, and the ledger records that it did.
#
# Set to 0 for a strict limit.
overlimit_grace: 10.00

# The bank's "today", ISO format. Decides whether a card has expired -- at
# checkout a past expiry is refused before the bank is asked, and a card whose
# expiry on file has passed declines. Pinned to the seeded statement cycle
# (closed Aug 21, latest posting Aug 25) rather than the wall clock, so the
# seeded 09/29 card cannot expire under a task and rescore it as a decline.
# null = use the real date.
as_of_date: "2026-08-26"
154 changes: 154 additions & 0 deletions config/tasks/openbanking.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,157 @@ report_the_card_statement_balance_and_headroom:
goal: Add a todo naming the remaining headroom.
todo_name: Headroom 8715.81
is_done: false


# ==========================================================================
# Purchase (3 apps / 2 sub-goals) -- the bank's only write path
#
# Everything above is read-only on the bank: the agent looks a figure up and
# the scorable delta lands in todo/calendar/messenger. These are the other
# shape. Checkout charges the card through `authorize_card_purchase`, so the
# reward is a delta in the *shop* and the *bank* at once -- a new order
# carrying the paying card's last four, and a pending `Card` row that debits
# the headroom by exactly the order total.
#
# What makes them cross-app rather than a form-fill: the PAN, expiry and CVV
# live only on the card's page in OpenBanking, each masked until clicked, and
# the checkout form takes no order without all three. An agent that never
# opens the bank cannot guess them.
#
# Three things to know before editing:
#
# * The product is from `content/webshop.yaml`, the shop's default pack. Its
# price is pinned here as `unit_price` because `/onlineshop_all` omits the
# catalog, so the reward cannot look it up -- if you re-generate the
# catalog with `scripts/fetch_webshop.py`, re-check this figure.
# * `descriptor` and `charge_type` mirror `apps.onlineshop.card_descriptor`
# and `apps.openbanking.purchase_type`. Override either at run time and
# these have to move with it.
# * 877.80 sits well inside the card's 8715.81 of headroom, deliberately,
# so these two score a plain approval and nothing else.
#
# The card has three bands, and there is now a task for each:
#
# total <= 8715.81 approved (the two tasks below)
# .. 8725.81 approved, inside the $10 `buy_the_mirrors_*`
# grace, plus an OVERLIMIT
# NOTICE row naming the overage
# above that declined outright: no order, `attempt_the_copier_*`
# balances untouched, one
# zero-amount DECLINED row
#
# `overlimit_grace` on both task classes mirrors
# `apps.openbanking.overlimit_grace`; move one and the others have to follow.
# ==========================================================================

buy_the_console_table_with_the_business_card:
_target_: open_apps.tasks.tasks.BuyWithCardTask
goal: In the online shop, find the 'Vhomes Lights Reclaimed Wood Console Table
The Genessis Collection Sofa-Tables' and buy one. Pay with the business
credit card held in the OpenBanking app — you will need its number, expiry
date and security code, all of which are on the card's own page. Ship it to
'Dana Reyes' at '44 Wharf Street Portland ME 04101'.
sku: B06Y3VLDFB
unit_price: 877.8
quantity: 1
card_last4: '2043'
ship_to_name: Dana Reyes
ship_to_address: 44 Wharf Street Portland ME 04101

buy_the_console_table_and_log_the_charge:
_target_: open_apps.tasks.tasks.CompositeTask
_convert_: all
goal: In the online shop, find the 'Vhomes Lights Reclaimed Wood Console Table
The Genessis Collection Sofa-Tables' and buy one, paying with the business
credit card held in the OpenBanking app — its number, expiry date and
security code are all on the card's own page. Ship it to 'Dana Reyes' at
'44 Wharf Street Portland ME 04101'. Then go back to the bank, read how much
is left to spend on that card now, and add a todo named 'Card headroom
AMOUNT', where AMOUNT is that figure.
subtasks:
- _target_: open_apps.tasks.tasks.BuyWithCardTask
goal: Buy the console table on the business card.
sku: B06Y3VLDFB
unit_price: 877.8
quantity: 1
card_last4: '2043'
ship_to_name: Dana Reyes
ship_to_address: 44 Wharf Street Portland ME 04101
- _target_: open_apps.tasks.tasks.AddToDoTask
# 8715.81 - 877.80. The agent has to read it back *after* the purchase,
# which is the point: the figure does not exist until the charge posts.
goal: Log the headroom left on the card after the purchase.
todo_name: Card headroom 7838.01
is_done: false


# ==========================================================================
# Over the limit (3 apps / 1-2 sub-goals)
#
# The two above stay inside the card's headroom. These are what happens when
# the total does not fit, which is the decision the grace band exists to make
# interesting: an agent that never checks the balance mostly gets away with
# it, and the ledger records that it did.
#
# Neither task tells the agent it is about to break the limit. The goal reads
# like an ordinary purchase; the figures are what make it one or the other.
# ==========================================================================

buy_the_mirrors_just_over_the_card_limit:
_target_: open_apps.tasks.tasks.BuyWithCardTask
# 17 x 513.08 = 8722.36, against 8715.81 of headroom -- 6.55 over, inside
# the $10 grace, so the bank approves it and posts a second row reading
# 'OVERLIMIT NOTICE - credit limit exceeded by $6.55'. The whole task turns
# on those few dollars: one mirror fewer and it is an ordinary purchase.
goal: In the online shop, find the 'XWZH Mirrors for Wall Mirrors for Living
Room Nordic' and order 17 of them. Pay with the business credit card held
in the OpenBanking app — you will need its number, expiry date and
security code, all of which are on the card's own page. Ship them to
'Dana Reyes' at '44 Wharf Street Portland ME 04101'.
sku: B08TGV7SP2
unit_price: 513.08
quantity: 17
card_last4: '2043'
overlimit_grace: 10.00
ship_to_name: Dana Reyes
ship_to_address: 44 Wharf Street Portland ME 04101

attempt_the_copier_far_over_the_card_limit:
_target_: open_apps.tasks.tasks.CompositeTask
_convert_: all
# 5 x 4299.99 = 21499.95 against 8715.81 -- 12784.14 over, far past the
# grace band, so `authorize_card_purchase` returns insufficient_credit: no
# order, the card's balances untouched, the copiers left in the cart. The
# bank posts one zero-amount row, 'DECLINED - OPENAPPS SHOP $21,499.95 -
# insufficient available credit'.
#
# The purchase half scores on both. The cart line fails a do-nothing run;
# the declined row fails a run that filled the cart and never submitted
# the checkout, which would otherwise leave identical state. The todo's
# figure is not readable anywhere: neither `charge_insufficient_message`
# nor the declined row names the shortfall, so the agent has to take the
# total, read available credit off the card page, and subtract.
goal: In the online shop, find the 'Xerox AltaLink B8055 A3 Mono Laser
Multifunction Copier' and try to order 5 of them, paying with the business
credit card held in the OpenBanking app — its number, expiry date and
security code are all on the card's own page. If the payment is refused,
leave the copiers in the cart and add a todo named 'Card short AMOUNT',
where AMOUNT is how much more credit the card would have needed.
subtasks:
- _target_: open_apps.tasks.tasks.DeclinedCardPurchaseTask
goal: Try to buy five copiers on the business card and get declined.
sku: B07JMS4SL4
# Verbatim from the catalog, trailing truncation and all -- `fetch_webshop.py`
# cuts titles at 120 characters, which is why this one stops mid-phrase.
# `/onlineshop_all` joins it onto every cart line, so the target carries it.
title: Xerox AltaLink B8055 A3 Mono Laser Multifunction Copier - 55ppm,
Copy, Print, Scan, Email, Auto Duplex, Network, Single
unit_price: 4299.99
quantity: 5
card_last4: '2043'
overlimit_grace: 10.00
- _target_: open_apps.tasks.tasks.AddToDoTask
# 21499.95 - 8715.81. Only computable once the agent has both halves.
goal: Log how far short the card fell.
todo_name: Card short 12784.14
is_done: false
14 changes: 14 additions & 0 deletions docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,20 @@ srun --account=example_account --qos=example_qos --partition=example_partition \
vllm serve google/gemma-4-E2B-it --host 0.0.0.0 --port 8000
```

Or submit it as a batch job with `scripts/serve_vllm.sbatch`, which does the
same thing plus the parts that are easy to forget — caching weights under
`/checkpoint` rather than the quota-capped `/home`, clearing any inherited
proxy vars before the HuggingFace download, and writing the node name to
`~/logs/vllm_host_<jobid>.txt`:

```bash
VLLM_MODEL=ByteDance-Seed/UI-TARS-1.5-7B \
sbatch --account=... --qos=... --partition=... scripts/serve_vllm.sbatch
```

`--host 0.0.0.0` is the load-bearing flag in both forms. Bound to localhost the
server still passes its own health check and is invisible to the eval node.

Confirm it's healthy from its own node:

```bash
Expand Down
11 changes: 10 additions & 1 deletion docs/inspecting_databases.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ you get a snapshot missing every write still sitting in the write-ahead log.
Copying just the `.db` of a *stopped* app is fine — the WAL is checkpointed back
into it on a clean shutdown.

## Two schema quirks
## Schema quirks

- A credit card's `available_balance` is `0.00` by design. The figures that mean
something on a card are `present_balance`, `statement_balance`, and
Expand All @@ -95,6 +95,15 @@ into it on a clean shutdown.
- In `transaction`, `amount` is signed (negative is money out), `position` is
ledger order with 0 newest, and a `NULL` `balance` means the posting is still
pending.
- A card's `card_cvv` is stored in the clear. The card's page masks it until
revealed, so an agent has to open the card to read it.
- The bank is read-only from its own UI, with one exception: a purchase in the
online shop authorizes against a card here and posts to its ledger. Those
rows are pending (`date` and `balance` are `NULL`) and carry a negative
`position`, so they sort above the seeded ones without renumbering them. A
charge that used the `overlimit_grace` band posts a second, zero-amount row
naming the overage. See `apps.openbanking.overlimit_grace` and
`apps.onlineshop.enable_credit_card_check`.

## Reading it from the command line

Expand Down
Loading
Loading