@agenzo/merchant-cli 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,68 +1,77 @@
1
1
  # @agenzo/merchant-cli
2
2
 
3
- > **Merchant-fulfillment product-line CLI** — binary `agenzo-merchant-cli`, lives in the monorepo `agenzo-cli/apps/merchant-cli`.
4
- > Covers two noun groups: capability discovery (`services`) and the ride-hailing business loop (`ride-elife`), 7 commands in total.
3
+ [![npm](https://img.shields.io/npm/v/@agenzo/merchant-cli.svg)](https://www.npmjs.com/package/@agenzo/merchant-cli) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENSE) ![node](https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg)
4
+
5
+ > **Merchant-fulfillment CLI** for the Agenzo platform — binary `agenzo-merchant-cli`.
6
+ > Agents fulfill commerce services here. Each capability is a noun and the set grows over time — use `services` to discover what's available; today's capabilities are ride-hailing (`ride-elife`) and hotel booking (`hotel-redaug`).
7
+
8
+ **[Overview](#overview)** · **[Features](#features)** · **[Quick Start](#quick-start)** · **[Global flags](#global-flags)** · **[Errors](#output-and-error-contract)** · **[Idempotency-Key](#idempotency-key)**
5
9
 
6
10
  ---
7
11
 
8
12
  ## Overview
9
13
 
10
- `agenzo-merchant-cli` is the command-line entry point for Agents to access Agenzo's merchant-fulfillment capabilities. This iteration ships two noun groups:
14
+ `agenzo-merchant-cli` is the command-line entry point for Agents to fulfill commerce services on the Agenzo platform. Each fulfillment capability is exposed as a **noun**, and the set grows over time:
11
15
 
12
- - **`services`** (capability discovery): lets an Agent discover available merchant-fulfillment capabilities (which noun/verb to call, and the call flow). The data source this iteration is the **CLI-bundled registry** (the backend `/services` discovery endpoint is pending impl).
13
- - **`ride-elife`** (ride hailing, the only online provider): the full loop of quote → book → query/poll → cancel → list-orders.
16
+ - **`services`** (capability discovery): list what's currently available and how to call it — run this first to learn the current capability set.
17
+ - **`ride-elife`** (ride-hailing): the full loop of quote → book → query/poll → cancel → list-orders.
18
+ - **`hotel-redaug`** (hotel booking): search, find-destination, hotel-filters, list-cities, hotel-detail, quote, create-order, pay-order, get (status/poll), cancel, checkout, get-checkout, list-orders. Supports both **monthly_settlement** (on-account deduction) and **pay_per_call** (user pays via EVO using the order_id as the merchantTransID).
14
19
 
15
- All shared infrastructure (HTTP client, output rendering, error system, exit codes, version negotiation, config) is reused from `@agenzo/cli-core`; the app only keeps command handling and merchant-domain-specific logic (ride body assembly, NDJSON watch, verb-schema help, services registry, idempotency-key policy).
16
-
17
- > This CLI keeps its structure, naming, and build configuration consistent with `agenzo-admin-cli` / `agenzo-token-cli` (4-CLI consistency).
20
+ More fulfillment capabilities are added as new nouns over time; `services list` always reflects the current set.
18
21
 
19
22
  ## Features
20
23
 
21
24
  | Noun | Verb | Type | HTTP | Description |
22
25
  |---|---|---|---|---|
23
- | `services` | `list` | Read | — (bundled registry) | List available merchant-fulfillment capabilities |
24
- | `services` | `get <service-id>` | Read | — (bundled registry) | View the full metadata of a single capability (miss → `SERVICE_NOT_FOUND`) |
26
+ | `services` | `list` | Read | — (local) | List available merchant-fulfillment capabilities |
27
+ | `services` | `get <service-id>` | Read | — (local) | View the full metadata of a single capability (miss → `SERVICE_NOT_FOUND`) |
25
28
  | `ride-elife` | `quote` | Read | `POST /ride/quote` | Point-to-point quote (`vehicle_classes[]` + meet-and-greet) |
26
29
  | `ride-elife` | `book` | Write/Y | `POST /ride/book` | Book against a quote (monthly_settlement-aware, see below) |
27
30
  | `ride-elife` | `get` | Read | `GET /ride/<id>/status` | Query order status; `--watch` emits an NDJSON polling stream |
28
31
  | `ride-elife` | `cancel` | Write/Y | `POST /ride/<id>/cancel` | Cancel an order (no body, may incur a fee) |
29
32
  | `ride-elife` | `list-orders` | Read | `GET /ride/orders` | List booked trips (pagination + filtering) |
30
-
31
- > Write commands (`book` / `cancel`) are subject to the idempotency-key rules (see [Idempotency-Key](#idempotency-key)).
32
- > Not implemented: `ride-elife track` (pending impl, the backend has no location-stream interface) — `get --watch` already covers order-status polling.
33
-
34
- ## Tech Stack
35
-
36
- - TypeScript (ESM) + [commander@14](https://github.com/tj/commander.js) + [@inquirer/prompts](https://github.com/SBoudrias/Inquirer.js)
37
- - Build: [tsup](https://tsup.egoist.dev/) (esm / node18 / dts, banner `#!/usr/bin/env node`)
38
- - Testing: [vitest](https://vitest.dev/) + [fast-check](https://fast-check.dev/) (PBT)
39
- - Shared base package: `@agenzo/cli-core` (the only horizontal dependency; importing other apps is **forbidden**)
33
+ | `hotel-redaug` | `search` | Read | `POST /hotel/search` | Search hotels by coordinates or destination-id + stay dates + filters |
34
+ | `hotel-redaug` | `find-destination` | Read | `POST /hotel/find-destination` | Resolve free-text to destinations (destination_id + coordinates) |
35
+ | `hotel-redaug` | `hotel-filters` | Read | `POST /hotel/filters` | Get available filter options for a location (codes → search flags) |
36
+ | `hotel-redaug` | `list-cities` | Read | `POST /hotel/cities` | List cities for a country (destination_id + coordinates) |
37
+ | `hotel-redaug` | `hotel-detail` | Read | `POST /hotel/detail` | Hotel detail with facilities/images AND `rooms[]` (area/floor/beds/photos) — call before quote |
38
+ | `hotel-redaug` | `quote` | Read | `POST /hotel/quote` | Real-time rooms/rates for one hotel (`product_token` + `price_items`) |
39
+ | `hotel-redaug` | `create-order` | Write/Y | `POST /hotel/create-order` | Create a hotel order without charging (locks rate + returns `order_id` + payable amount) |
40
+ | `hotel-redaug` | `pay-order` | Write/Y | `POST /hotel/{order_id}/pay` | Pay for a created order (takes only `--order-id`); billing path (`monthly_settlement` or `pay_per_call`) is chosen server-side |
41
+ | `hotel-redaug` | `get` | Read | `GET /hotel/<id>/status` | Query order status; `--watch` emits an NDJSON polling stream |
42
+ | `hotel-redaug` | `cancel` | Write/Y | `POST /hotel/<id>/cancel` | Cancel a whole order (acceptance ≠ proof; poll `get`) |
43
+ | `hotel-redaug` | `checkout` | Write/Y | `POST /hotel/<id>/checkout` | Partial check-out / out-of-policy cancellation (async) |
44
+ | `hotel-redaug` | `get-checkout` | Read | `GET /hotel/checkout/<task_order_code>` | Poll a check-out application; `--watch` emits an NDJSON stream |
45
+ | `hotel-redaug` | `list-orders` | Read | `GET /hotel/orders` | List hotel orders (pagination + status filter) |
46
+
47
+ > Write commands (`ride-elife book` / `cancel`; `hotel-redaug create-order` / `pay-order` / `cancel` / `checkout`) are subject to the idempotency-key rules (see [Idempotency-Key](#idempotency-key)).
48
+ > Read status verbs `get` / `get-checkout` support `--watch` for NDJSON status polling.
49
+ > `ride-elife track` is not available — use `get --watch` for order-status polling.
40
50
 
41
51
  ## Quick Start
42
52
 
43
53
  ### Requirements
44
54
 
45
- - Node.js 18+
46
- - `npm install` has been run in the monorepo
55
+ - Node.js 22+
47
56
 
48
- ### Build
57
+ ### Installation
49
58
 
50
59
  ```bash
51
- # in the monorepo root
52
- npm run build -w @agenzo/cli-core # must build the shared base package first
53
- npm run build -w @agenzo/merchant-cli # tsup produces dist/index.js (= bin agenzo-merchant-cli)
60
+ npm install -g @agenzo/merchant-cli
54
61
  agenzo-merchant-cli --version
55
62
  ```
56
63
 
64
+ Upgrade later with `npm install -g @agenzo/merchant-cli@latest`.
65
+
57
66
  ### Authentication
58
67
 
59
68
  A runtime-plane CLI that uses an **API Key** (`--api-key`, carried per command as the `X-Api-Key` header):
60
69
 
61
70
  - The API Key is issued by `agenzo-admin-cli keys create --scope merchant` and must include the `merchant` scope.
62
71
  - When `--api-key` is omitted, it is requested interactively (password input).
63
- - No Bearer Token / AuthService / keystore — consistent with `agenzo-token-cli`.
72
+ - No Bearer Token or local keystore — every command carries the API Key.
64
73
 
65
- ### End-to-end example
74
+ ### Ride-hailing end-to-end example
66
75
 
67
76
  ```bash
68
77
  # 1. Discover capabilities
@@ -92,13 +101,94 @@ agenzo-merchant-cli ride-elife cancel --api-key "$API_KEY" --yes \
92
101
  --order-id "$RIDE_ID" --idempotency-key "cancel-$(date +%s)"
93
102
  ```
94
103
 
104
+ ### Hotel booking end-to-end example
105
+
106
+ The core Agent loop is `search → quote → create-order → pay-order → get`. Amounts are decimal currency
107
+ units (e.g. `320.00` = 320.00 yuan). `pay-order` takes only `--order-id`; the billing path is chosen
108
+ server-side by the developer's `billing_mode`:
109
+ - **monthly_settlement**: deducted from the monthly-settlement account.
110
+ - **pay_per_call**: the user pays via shared EVO parameters using the `order_id` as the EVO merchantTransID; the platform verifies that payment for the same `order_id` before confirming.
111
+
112
+ ```bash
113
+ # 1. Search hotels by coordinates + stay dates (or use --destination-id from find-destination).
114
+ # Pick a hotels[].hotel_id from the result for the quote step.
115
+ agenzo-merchant-cli hotel-redaug search --api-key "$API_KEY" \
116
+ --lat 31.2304 --lng 121.4737 --distance 20 \
117
+ --check-in 2026-02-10 --check-out 2026-02-12 \
118
+ --adults 2 --children 0 --room-num 1
119
+
120
+ # 2. Quote one hotel (produces rates[].product_token, total_price, price_items)
121
+ agenzo-merchant-cli hotel-redaug quote --api-key "$API_KEY" \
122
+ --hotel-id "$HOTEL_ID" \
123
+ --check-in 2026-02-10 --check-out 2026-02-12 \
124
+ --adults 2 --room-num 1 --nationality CN
125
+
126
+ # 3. Create Order (write op: locks rate, no charge; returns order_id + payable amount).
127
+ agenzo-merchant-cli hotel-redaug create-order --api-key "$API_KEY" --yes \
128
+ --product-token "$PRODUCT_TOKEN" \
129
+ --total-amount 640.00 --currency CNY \
130
+ --price-items '[{"sale_date":"2026-02-10","sale_price":320.00,"breakfast_num":2},{"sale_date":"2026-02-11","sale_price":320.00,"breakfast_num":2}]' \
131
+ --check-in 2026-02-10 --check-out 2026-02-12 \
132
+ --guest-name "Zhang San" --contact-name "Zhang San" \
133
+ --contact-phone "13800138000" --contact-country-code 86 \
134
+ --idempotency-key "hotel-create-$(date +%s)"
135
+
136
+ # 4a. Pay Order — monthly_settlement path (on-account)
137
+ agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
138
+ --order-id "$ORDER_ID" \
139
+ --idempotency-key "hotel-pay-$(date +%s)"
140
+
141
+ # 4b. Pay Order — pay_per_call path (user already paid via EVO using order_id
142
+ # as the EVO merchantTransID). Same command, no other flag.
143
+ agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
144
+ --order-id "$ORDER_ID" \
145
+ --idempotency-key "hotel-pay-$(date +%s)"
146
+
147
+ # 4c. Pay Order — pay_per_call with --watch (polls until PAID or timeout)
148
+ agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
149
+ --order-id "$ORDER_ID" \
150
+ --idempotency-key "hotel-pay-$(date +%s)" \
151
+ --watch --watch-interval 5 --watch-timeout 120
152
+
153
+ # 5. Query / poll status. create-order returns order_status=AWAITING_PAYMENT;
154
+ # after pay-order succeeds, status becomes PAID; poll get until CONFIRMED.
155
+ agenzo-merchant-cli hotel-redaug get --api-key "$API_KEY" --order-id "$ORDER_ID"
156
+ agenzo-merchant-cli hotel-redaug get --api-key "$API_KEY" --order-id "$ORDER_ID" \
157
+ --watch --watch-interval 5 --watch-timeout 600
158
+
159
+ # 6. List orders (pagination + optional status filter)
160
+ agenzo-merchant-cli hotel-redaug list-orders --api-key "$API_KEY" \
161
+ --status CONFIRMED --page 1 --page-size 20
162
+
163
+ # 7. Cancel a whole order (write op). Acceptance is NOT proof — poll get until CANCELLED.
164
+ agenzo-merchant-cli hotel-redaug cancel --api-key "$API_KEY" --yes \
165
+ --order-id "$ORDER_ID" --fc-order-code "$FC_ORDER_CODE" \
166
+ --reason "Change of plans" \
167
+ --idempotency-key "hotel-cancel-$(date +%s)"
168
+
169
+ # 8. Partial check-out / out-of-policy cancellation (write op, async).
170
+ # Returns task_order_code; poll get-checkout for the refund outcome.
171
+ agenzo-merchant-cli hotel-redaug checkout --api-key "$API_KEY" --yes \
172
+ --order-id "$ORDER_ID" --fc-order-code "$FC_ORDER_CODE" \
173
+ --reason "Guest departing early" \
174
+ --checkout-rooms '[{"room_index":"1","guest_name":"Zhang San","cancel_check_in_date":"2026-02-11"}]' \
175
+ --refund-type 1 \
176
+ --idempotency-key "hotel-checkout-$(date +%s)"
177
+
178
+ # 9. Poll the check-out application until a terminal refund status
179
+ agenzo-merchant-cli hotel-redaug get-checkout --api-key "$API_KEY" \
180
+ --task-order-code "$TASK_ORDER_CODE"
181
+ agenzo-merchant-cli hotel-redaug get-checkout --api-key "$API_KEY" \
182
+ --task-order-code "$TASK_ORDER_CODE" --watch --watch-interval 10 --watch-timeout 600
183
+ ```
184
+
95
185
  ## Global flags
96
186
 
97
187
  | Flag | Default | Description |
98
188
  |---|---|---|
99
- | `--format <json\|table>` | **`json`** | Output format. merchant-cli is an agent-first entry point, so it **defaults to `json`** (a deliberate deviation from cli-core's `table` default, D2); also reads the `AGENZO_FORMAT` environment variable |
189
+ | `--format <json\|table>` | **`json`** | Output format. Defaults to `json`; pass `table` for tabular output. Also reads the `AGENZO_FORMAT` environment variable |
100
190
  | `--api-key <key>` | — (requested interactively) | API Key, carried per command as the `X-Api-Key` header |
101
- | `--yes` | `false` | Skip interactive confirmation (for CI / Agent); for write commands, `--yes` with a missing idempotency key is a hard error |
191
+ | `--yes` | `false` | Skip interactive confirmation (non-interactive automation); for write commands, `--yes` with a missing idempotency key is a hard error |
102
192
  | `--verbose` | `false` | Verbose logging (written to stderr) |
103
193
 
104
194
  ## Output and error contract
@@ -106,24 +196,25 @@ agenzo-merchant-cli ride-elife cancel --api-key "$API_KEY" --yes \
106
196
  - **`--format json` (non-watch commands)**: stdout contains only a **single valid JSON** (business payload + `profile`/`endpoint` envelope, where endpoint is host-only without a path); all status/progress/spinner lines go to stderr and are silenced in json mode.
107
197
  - **`--format table`**: business output goes to stdout, status lines/spinner go to stderr.
108
198
  - **`get --watch`**: stdout is a line-by-line NDJSON stream, **not wrapped** in the profile/endpoint envelope; polling stops when it hits the terminal-status set (`At destination` / `Cancelled` / `Rejected` / `Customer no show` / `Driver no show`, case-sensitive) or times out; on timeout the final line is `{ "watch_status": "timeout", ... }`.
109
- - **Error envelope** (cli-core §8): `json` → `{ "error": { "code", "code_num", "message", "request_id"? } }`; `table` → `✗ [<code_num>] <message>`.
199
+ - **`hotel-redaug get --watch` / `hotel-redaug get-checkout --watch`**: same NDJSON line-stream contract (no envelope). `get` stops when `order_status_code ∈ {3, 4, 5}` (equivalently `order_status ∈ {CONFIRMED, CANCELLED, COMPLETED}`); `get-checkout` stops when `refund_status ∈ {approved, rejected, refunded}`; on timeout the final line is `{ "watch_status": "timeout", ... }`.
200
+ - **Error envelope**: `json` → `{ "error": { "code", "code_num", "message", "request_id"? } }`; `table` → `✗ [<code_num>] <message>`. When a request fails, retry with the same `--idempotency-key`; if it persists, contact support with the `request_id` from the error output.
110
201
 
111
- Exit codes (mapped by cli-core's `exitCodeFor`):
202
+ Exit codes:
112
203
 
113
204
  | Exit code | Meaning | Representative error codes |
114
205
  |---|---|---|
115
206
  | `0` | Success | — |
116
- | `1` | Business / param | `PARAM_INVALID`(2101) · `PARAM_IDEMPOTENCY_KEY_REQUIRED`(2102) · `SERVICE_NOT_FOUND`(4101) · `VEHICLE_UNAVAILABLE`(4201) · `QUOTE_EXPIRED`(4202) · `BOOKING_FAILED`(4203) · `CANCELLATION_NOT_ALLOWED`(4204) · `BILLING_MODE_MISMATCH`(3001) · `ACCOUNT_*`(31xx) · `PAYMENT_ORDER_*`(32xx) |
207
+ | `1` | Business / param | `PARAM_INVALID`(2101) · `PARAM_IDEMPOTENCY_KEY_REQUIRED`(2102) · `SERVICE_NOT_FOUND`(4101) · `VEHICLE_UNAVAILABLE`(4201) · `QUOTE_EXPIRED`(4202) · `BOOKING_FAILED`(4203) · `CANCELLATION_NOT_ALLOWED`(4204) · `NO_AVAILABILITY`(4301) · `PRICE_CHANGED`(4302) · `NAME_FORMAT_INVALID`(4303) · `HOTEL_ORDER_NOT_FOUND`(4304) · `ALREADY_CANCELLED`(4305) · `CHECKOUT_NOT_ALLOWED`(4306) · `CHECKOUT_TASK_NOT_FOUND`(4307) · `PAY_PER_CALL_NOT_AVAILABLE`(4308) · `BILLING_MODE_MISMATCH`(3001) · `ACCOUNT_*`(31xx) · `PAYMENT_ORDER_*`(32xx) |
117
208
  | `2` | Upgrade required | `UPGRADE_REQUIRED`(9008) |
118
209
  | `3` | Auth / invalid key | `KEY_INVALID`(1101) · `KEY_SCOPE_DENIED`(1102) |
119
210
  | `4` | Network / 5xx | `RATE_LIMITED`(5001) · `UPSTREAM_ERROR`(5101) · `INTERNAL_ERROR`(5201) |
120
211
  | `5` | User cancel | `CLIENT_ABORTED`(9007) · SIGINT |
121
212
 
122
- > api-key auth mapping: HTTP 401 → `KEY_INVALID`, 403 → `KEY_SCOPE_DENIED`. A known §8 string code returned by the backend (e.g. `QUOTE_EXPIRED`) takes priority and is preserved; otherwise it falls back to the HTTP-status mapping.
213
+ > api-key auth mapping: HTTP 401 → `KEY_INVALID`, 403 → `KEY_SCOPE_DENIED`. A known string error code (e.g. `QUOTE_EXPIRED`) takes priority and is preserved; otherwise it falls back to the HTTP-status mapping.
123
214
 
124
215
  ## Idempotency-Key
125
216
 
126
- The write commands `ride-elife book` / `cancel` accept `--idempotency-key`:
217
+ The write commands `ride-elife book` / `cancel` and `hotel-redaug create-order` / `pay-order` / `cancel` / `checkout` accept `--idempotency-key`:
127
218
 
128
219
  - Format: `[A-Za-z0-9_-]{1,128}`.
129
220
  - **The CLI never auto-generates one**: `--yes` with a missing key → hard error `PARAM_IDEMPOTENCY_KEY_REQUIRED` (exit 1), and no request is sent; a missing key without `--yes` → requested interactively.
@@ -132,66 +223,49 @@ The write commands `ride-elife book` / `cancel` accept `--idempotency-key`:
132
223
 
133
224
  ## Billing model for book (monthly_settlement-aware)
134
225
 
135
- `ride-elife book` **does not accept** `--payment-method-id` or any card information — the merchant domain holds no payment handle. Funding is decided by the backend according to the Developer's `billing_mode`:
226
+ `ride-elife book` **does not accept** `--payment-method-id` or any card information — the merchant domain holds no payment handle. Funding is decided according to the Developer's `billing_mode`:
136
227
 
137
228
  - **monthly_settlement**: deducted from the monthly-settlement account, no payment handle; the response has `payment_status=ON_ACCOUNT` and includes `billing_entry_id`.
138
229
  - **pay_per_call**: optionally pass through `--payment-order-id` (a PAID order number charged separately, out-of-band); the response echoes `payment_order_id`.
139
230
 
140
231
  The request body contains at most an optional `payment_order_id`.
141
232
 
142
- ## profile / host model
233
+ ### hotel-redaug billing (create-order + pay-order, two billing modes)
143
234
 
144
- merchant-cli **has no host / config commands** and does not govern environments. It reuses `@agenzo/cli-core`'s `ConfigManager` default configuration (i.e. the environment governed centrally by `agenzo-admin-cli`, persisted by default to `~/.agenzo-admin-cli/`):
235
+ `hotel-redaug` uses a **two-step flow**: `create-order` (locks rate, no charge) then `pay-order` (settles).
145
236
 
146
- - Provides the `baseUrl` for `ApiClient` (host + `/api/merchant/v1`).
147
- - Provides the environment name + host for the `profile` / `endpoint` envelope in json output.
237
+ `pay-order` takes only `--order-id`; there is no merchant-transaction-id flag. The billing path is
238
+ chosen server-side by the developer's `billing_mode`:
148
239
 
149
- **Environment governance (setting the host / switching environments) belongs to `agenzo-admin-cli`** (`agenzo-admin-cli config set` / `set-host`) — consistent with `agenzo-token-cli`.
240
+ - **monthly_settlement**: deducted from the monthly-settlement account. The response carries `payment_status=ON_ACCOUNT`.
241
+ - **pay_per_call**: the user pays via shared EVO parameters out-of-band using the create-order `order_id` as the EVO merchantTransID; the platform queries EVO for that same `order_id` to confirm payment before calling upstream `payOrder` (response `settlement_path` is `pay_per_call`). If EVO reports "not yet paid", the CLI receives `PAYMENT_NOT_COMPLETED` (exit 1) — use `--watch` to poll until confirmed.
150
242
 
151
- ## Machine-readable verb schema
243
+ If the order's `billing_mode` is neither of the two values above, `pay-order` returns `BILLING_MODE_MISMATCH` (exit 1).
152
244
 
153
- Every `ride-elife` verb supports `--help --format json`, emitting that verb's machine-readable schema (`cli` / `noun` / `verb` / `description` / `flags` / `response` / `example`, some with `error_recovery` / `polling`):
245
+ ## Amount units (decimal currency)
154
246
 
155
- ```bash
156
- agenzo-merchant-cli ride-elife quote --help --format json
157
- agenzo-merchant-cli ride-elife book --help --format json
158
- ```
247
+ Both `ride-elife` and `hotel-redaug` express **every monetary amount in DECIMAL currency units** paired with an ISO 4217 `currency` code — `320.00` means 320.00 yuan, never `32000` minor units (cents/fen). This applies to inputs (`hotel-redaug create-order --total-amount`, each `--price-items[].sale_price`) and to every rendered amount (`quote` totals and `price_items`, `get` / `list-orders` prices, cancellation fees, and refunds). Amounts are forwarded and rendered **verbatim**, with no minor-unit conversion in either direction. This differs from `agenzo-token-cli` and `agenzo-payment-cli`, which use minor units.
159
248
 
160
- ## Development
249
+ ## profile / host model
161
250
 
162
- ```bash
163
- npm run build -w @agenzo/merchant-cli # tsup build
164
- npm run test -w @agenzo/merchant-cli # vitest (incl. fast-check PBT)
165
- ```
251
+ merchant-cli **has no host / config commands** and does not govern environments. It reuses the environment configured by `agenzo-admin-cli` (persisted under `~/.agenzo-admin-cli/`):
166
252
 
167
- Source structure:
168
-
169
- ```text
170
- apps/merchant-cli/
171
- src/
172
- index.ts # commander assembly + top-level reportError + SIGINT
173
- services/{list,get}.ts # capability discovery (this iteration: CLI-bundled registry)
174
- services/registry.ts # bundled static registry (merchant domain)
175
- ride-elife/{quote,book,get,cancel,list-orders}.ts
176
- ride-elife/watch.ts # NDJSON polling engine (merchant domain)
177
- verb-schema.ts # verb schema for --help --format json (merchant domain)
178
- idempotency.ts # idempotency key resolve / normalize (merchant domain)
179
- types/api.ts # ride/service response types (consumed by merchant only, not promoted to cli-core)
180
- docs/ # test design docs (see below)
181
- tests/ # vitest unit tests + PBT
182
- ```
253
+ - Determines the API host that requests are sent to.
254
+ - Provides the environment name + host for the `profile` / `endpoint` envelope in json output.
183
255
 
184
- ## Documentation index
256
+ **Setting the host / switching environments belongs to `agenzo-admin-cli`** (`agenzo-admin-cli config set-host`).
185
257
 
186
- - [Test design doc (command matrix v1)](docs/test-design-command-matrix-v1.md) — a 7-command × requirement/Property coverage matrix, the L1–L4 layered testing strategy, L1 unit / L3 command-level case tables, and L4 manually executable smoke cases.
187
- - Architecture and standards: `architecture-upgrade/v1/` (cli-standard / cli-design §4+§8 / cli-guide).
188
- - monorepo overview: [`agenzo-cli/README.md`](../../README.md).
258
+ ## Machine-readable verb schema
189
259
 
190
- ## Changelog
260
+ Every `ride-elife` and `hotel-redaug` verb supports `--help --format json`, emitting that verb's machine-readable schema (`cli` / `noun` / `verb` / `description` / `flags` / `response` / `example`, some with `error_recovery` / `polling`):
191
261
 
192
- ### 2026-06
262
+ ```bash
263
+ agenzo-merchant-cli ride-elife quote --help --format json
264
+ agenzo-merchant-cli ride-elife book --help --format json
265
+ agenzo-merchant-cli hotel-redaug quote --help --format json
266
+ agenzo-merchant-cli hotel-redaug create-order --help --format json # write verb: error_recovery
267
+ agenzo-merchant-cli hotel-redaug pay-order --help --format json # write verb: error_recovery
268
+ agenzo-merchant-cli hotel-redaug get --help --format json # long-running: polling block
269
+ ```
193
270
 
194
- - Landed merchant-cli in the monorepo `agenzo-cli/apps/merchant-cli` (rewritten per cli-design §4, reusing `@agenzo/cli-core`).
195
- - Shipped `services` (list / get) + `ride-elife` (quote / book / get [+`--watch`] / cancel / list-orders), 7 commands in total.
196
- - Output defaults to `json` (agent-first); API Key auth (`X-Api-Key`); write commands require `--idempotency-key`.
197
- - Added the test design doc `docs/test-design-command-matrix-v1.md`.
271
+ For `hotel-redaug`, `create-order` / `pay-order` / `cancel` / `checkout` are the write verbs that require `--idempotency-key`, and `get` / `get-checkout` are the long-running reads that support `--watch` NDJSON streaming (their schemas carry a `polling` block).