@agenzo/merchant-cli 0.9.6 → 0.10.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../../packages/cli-core/errors/error-catalog.ts","../../../packages/cli-core/errors/errors.ts","../../../packages/cli-core/version/version.ts","../../../packages/cli-core/api-client/client.ts","../../../packages/cli-core/credential-store/credential-store.ts","../../../packages/cli-core/key-store/key-store.ts","../../../packages/cli-core/config/config-manager.ts","../../../packages/cli-core/exit/exit.ts","../../../packages/cli-core/formatter/formatter.ts","../../../packages/cli-core/formatter/output.ts","../../../packages/cli-core/formatter/render-context.ts","../../../packages/cli-core/prompt-engine/prompt-engine.ts","../src/member.ts","../src/price-annotation.ts","../src/ride-elife/watch.ts","../src/verb-schema.ts","../src/ride-elife/quote.ts","../src/ride-elife/book.ts","../src/idempotency.ts","../src/ride-elife/create-order.ts","../src/ride-elife/pay-order.ts","../src/ride-elife/get.ts","../src/ride-elife/cancel.ts","../src/ride-elife/update.ts","../src/ride-elife/trip-status.ts","../src/ride-elife/list-orders.ts","../src/ride-elife/callback.ts","../src/services/registry.ts","../src/services/local-caps.ts","../src/services/list.ts","../src/services/get.ts","../src/orders/list.ts","../src/orders/get.ts","../src/orders/pay-batch.ts","../src/orders/get-payment-group.ts","../src/hotel-redaug/search.ts","../src/hotel-redaug/quote.ts","../src/hotel-redaug/create-order.ts","../src/hotel-redaug/pay-order.ts","../src/hotel-redaug/watch.ts","../src/hotel-redaug/get.ts","../src/hotel-redaug/cancel.ts","../src/hotel-redaug/checkout.ts","../src/hotel-redaug/get-checkout.ts","../src/hotel-redaug/list-orders.ts","../src/hotel-redaug/find-destination.ts","../src/hotel-redaug/hotel-filters.ts","../src/hotel-redaug/list-cities.ts","../src/hotel-redaug/hotel-detail.ts","../src/hotel-redaug/skill.ts","../src/flight-flink/_helpers.ts","../src/flight-flink/find-airport.ts","../src/flight-flink/list-airports.ts","../src/flight-flink/list-airlines.ts","../src/flight-flink/list-nationalities.ts","../src/flight-flink/search.ts","../src/flight-flink/more-offers.ts","../src/flight-flink/verify.ts","../src/flight-flink/create-order.ts","../src/flight-flink/pay-order.ts","../src/flight-flink/get-order.ts","../src/flight-flink/cancel-order.ts","../src/flight-flink/list-orders.ts","../src/flight-flink/change-search.ts","../src/flight-flink/change-apply.ts","../src/flight-flink/change-detail.ts","../src/flight-flink/change-cancel.ts","../src/flight-flink/change-pay.ts","../src/flight-flink/refund-apply.ts","../src/flight-flink/refund-detail.ts","../src/flight-flink/refund-confirm.ts","../src/flight-flink/skill.ts"],"sourcesContent":["import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n Formatter,\r\n CliError,\r\n UserCancelError,\r\n toErrorEnvelope,\r\n errorDetailLines,\r\n resolveFormat,\r\n type OutputFormat,\r\n exitCodeFor,\r\n getCurrentVersion,\r\n} from '@agenzo/cli-core';\r\n\r\n// ride-elife commands (injection-style register, D6)\r\nimport { registerQuoteCommand } from './ride-elife/quote.js';\r\nimport { registerBookCommand } from './ride-elife/book.js';\r\nimport { registerRideCreateOrderCommand } from './ride-elife/create-order.js';\r\nimport { registerRidePayOrderCommand } from './ride-elife/pay-order.js';\r\nimport { registerRideGetCommand } from './ride-elife/get.js';\r\nimport { registerCancelCommand } from './ride-elife/cancel.js';\r\nimport { registerRideUpdateCommand } from './ride-elife/update.js';\r\nimport { registerRideTripStatusCommand } from './ride-elife/trip-status.js';\r\nimport { registerListOrdersCommand } from './ride-elife/list-orders.js';\r\nimport { registerRideCallbackCommands } from './ride-elife/callback.js';\r\n\r\n// services commands (CLI-bundled registry, D4)\r\nimport { registerServicesListCommand } from './services/list.js';\r\nimport { registerServiceGetCommand } from './services/get.js';\r\n\r\n// orders commands (unified cross-provider order index — GET /orders)\r\nimport { registerOrdersListCommand } from './orders/list.js';\r\nimport { registerOrdersGetCommand } from './orders/get.js';\r\nimport { registerOrdersPayBatchCommand } from './orders/pay-batch.js';\r\nimport { registerOrdersGetPaymentGroupCommand } from './orders/get-payment-group.js';\r\n\r\n// hotel-redaug commands (injection-style register, D6)\r\nimport { registerHotelSearchCommand } from './hotel-redaug/search.js';\r\nimport { registerHotelQuoteCommand } from './hotel-redaug/quote.js';\r\nimport { registerHotelCreateOrderCommand } from './hotel-redaug/create-order.js';\r\nimport { registerHotelPayOrderCommand } from './hotel-redaug/pay-order.js';\r\nimport { registerHotelGetCommand } from './hotel-redaug/get.js';\r\nimport { registerHotelCancelCommand } from './hotel-redaug/cancel.js';\r\nimport { registerHotelCheckoutCommand } from './hotel-redaug/checkout.js';\r\nimport { registerHotelGetCheckoutCommand } from './hotel-redaug/get-checkout.js';\r\nimport { registerHotelListOrdersCommand } from './hotel-redaug/list-orders.js';\r\nimport { registerHotelFindDestinationCommand } from './hotel-redaug/find-destination.js';\r\nimport { registerHotelFiltersCommand } from './hotel-redaug/hotel-filters.js';\r\nimport { registerHotelListCitiesCommand } from './hotel-redaug/list-cities.js';\r\nimport { registerHotelDetailCommand } from './hotel-redaug/hotel-detail.js';\r\nimport { registerHotelSkillCommand } from './hotel-redaug/skill.js';\r\n\r\n// flight-flink commands (injection-style register, D6)\r\nimport { registerFindAirportCommand } from './flight-flink/find-airport.js';\r\nimport { registerListAirportsCommand } from './flight-flink/list-airports.js';\r\nimport { registerListAirlinesCommand } from './flight-flink/list-airlines.js';\r\nimport { registerListNationalitiesCommand } from './flight-flink/list-nationalities.js';\r\nimport { registerSearchCommand as registerFlightSearchCommand } from './flight-flink/search.js';\r\nimport { registerMoreOffersCommand } from './flight-flink/more-offers.js';\r\nimport { registerVerifyCommand } from './flight-flink/verify.js';\r\nimport { registerCreateOrderCommand as registerFlightCreateOrderCommand } from './flight-flink/create-order.js';\r\nimport { registerPayOrderCommand as registerFlightPayOrderCommand } from './flight-flink/pay-order.js';\r\nimport { registerGetOrderCommand as registerFlightGetOrderCommand } from './flight-flink/get-order.js';\r\nimport { registerCancelOrderCommand as registerFlightCancelOrderCommand } from './flight-flink/cancel-order.js';\r\nimport { registerListOrdersCommand as registerFlightListOrdersCommand } from './flight-flink/list-orders.js';\r\nimport { registerChangeSearchCommand } from './flight-flink/change-search.js';\r\nimport { registerChangeApplyCommand } from './flight-flink/change-apply.js';\r\nimport { registerChangeDetailCommand } from './flight-flink/change-detail.js';\r\nimport { registerChangeCancelCommand } from './flight-flink/change-cancel.js';\r\nimport { registerChangePayCommand } from './flight-flink/change-pay.js';\r\nimport { registerRefundApplyCommand } from './flight-flink/refund-apply.js';\r\nimport { registerRefundDetailCommand } from './flight-flink/refund-detail.js';\r\nimport { registerRefundConfirmCommand } from './flight-flink/refund-confirm.js';\r\nimport { registerFlightSkillCommand } from './flight-flink/skill.js';\r\n\r\n// Holds the parsed program so the top-level error handler can read the\r\n// resolved `--format` global flag. Assigned inside `main()` once the program\r\n// is constructed; may be undefined if an error is thrown before then.\r\nlet programRef: Command | undefined;\r\n\r\nasync function main() {\r\n // Instantiate shared infrastructure. merchant-cli authenticates per-command\r\n // via `--api-key` (X-Api-Key); there is no Bearer session / AuthService /\r\n // keystore. The no-arg ConfigManager reuses cli-core's default config (the\r\n // environment admin-cli governs) purely to supply the ApiClient baseUrl and\r\n // the json envelope's profile/endpoint — merchant-cli exposes no host\r\n // commands of its own.\r\n const configManager = new ConfigManager(undefined, '/api/merchant/v1');\r\n await configManager.ensureDirectories();\r\n\r\n const apiBaseUrl = await configManager.getApiBaseUrl();\r\n const apiClient = new ApiClient({ baseUrl: apiBaseUrl });\r\n\r\n // Discovery lives at the host root (/api/discovery/v1/catalog), NOT under the\r\n // per-binary merchant prefix, so it needs its own client built from the raw\r\n // host. Built here (not inside the action) so it can be injected/mocked.\r\n const apiHost = await configManager.getApiHost();\r\n const discoveryClient = new ApiClient({ baseUrl: apiHost });\r\n\r\n // Shared deps object for networked commands — API Key is supplied per-command\r\n // (or interactively), so commands only need the HTTP client.\r\n const deps = { apiClient };\r\n\r\n // Create program\r\n const program = new Command();\r\n programRef = program;\r\n program\r\n .name('agenzo-merchant-cli')\r\n .version(getCurrentVersion())\r\n .description(\r\n 'Agenzo merchant fulfillment plane: service discovery (services), ride ordering (ride-elife), hotel booking (hotel-redaug), and flight booking (flight-flink)',\r\n )\r\n .option('--verbose', 'Show verbose logs')\r\n .option('--yes', 'Skip confirmation prompts (for automation/AI Agents)')\r\n // merchant-cli is an agent-first entrypoint, so it defaults to json (D2),\r\n // unlike the cli-core default (table). resolveFormat only acts as a\r\n // fallback when the flag is absent.\r\n .option(\r\n '--format <format>',\r\n 'Output format: json | table (default: json; or set AGENZO_FORMAT)',\r\n 'json',\r\n )\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n\r\n // Mirror the resolved global --format into AGENZO_FORMAT before any action\r\n // runs, so code paths without direct format access can resolve the active\r\n // format and stay silent in json mode.\r\n program.hook('preAction', (thisCommand) => {\r\n const flag = thisCommand.opts().format as string | undefined;\r\n process.env.AGENZO_FORMAT = resolveFormat(flag);\r\n });\r\n\r\n // ride-elife command group (eLife ride ordering)\r\n const rideCmd = program.command('ride-elife').description(\r\n `Ride ordering (eLife) — quote a fare, book it, poll status, modify it, and cancel.\r\n\r\nWorkflow (typical order):\r\n 1. quote Get fare quotes between two points → vehicle_classes[] each with a quote_id\r\n 2. book Book one vehicle_class using its quote_id → ride_id (write; needs --idempotency-key)\r\n 3. get Poll ride status by --order-id=<ride_id> until terminal (or use --watch for NDJSON)\r\n 4. cancel (optional) Cancel a ride by --order-id (write; may incur a fee)\r\n update (optional) Modify trip details and/or passenger of a booked ride\r\n (write; needs --idempotency-key; the fare may change)\r\n trip-status (optional) Status + driver location points of ONE leg of a multi-leg ride\r\n list-orders (standalone) List the developer's previous ride orders\r\n callback-* (standalone) Status-event forwarding to your own https endpoint:\r\n callback-set/-get (one ride), callback-default-set/-get (fallback for all\r\n rides), callback-deliveries / callback-replay (inspect and re-send)\r\n\r\nKey notes:\r\n • Coordinates are NOT geocoded by the backend — supply --pickup-lat/lng and --dropoff-lat/lng.\r\n book must repeat the SAME pickup/dropoff coordinates+names and pickup-time used in quote;\r\n the quote_id does NOT carry them forward.\r\n • quote_id from quote is opaque and provider-specific — pass it unchanged to book, never reuse\r\n it across services.\r\n • vehicle_class values are case-sensitive literals (Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury /\r\n Train) — pass back to book verbatim.\r\n • --pickup-time is UTC epoch seconds or the literal \"now\"; convert the user's local time to UTC.\r\n • All amounts are DECIMAL currency units (e.g. 42.50 = $42.50), never minor units (cents).\r\n • Billing mode is decided server-side: pay_per_call needs a PAID --payment-order-id (from\r\n payment-cli); monthly_settlement forbids it (settled against the developer's account).\r\n • Write verbs (book / cancel / update) require --idempotency-key; reuse the SAME key when\r\n retrying the same intent.\r\n • update changes ONLY the fields you pass. Trip-side and passenger-side changes are two separate\r\n upstream calls with no transaction: the response reports ride_updated / passenger_updated, and a\r\n partial application returns UPSTREAM_ERROR with data.partial_update — re-issue update for the\r\n failed side only.`,\r\n );\r\n registerQuoteCommand(rideCmd, deps);\r\n registerBookCommand(rideCmd, deps);\r\n registerRideCreateOrderCommand(rideCmd, deps);\r\n registerRidePayOrderCommand(rideCmd, deps);\r\n registerRideGetCommand(rideCmd, deps);\r\n registerCancelCommand(rideCmd, deps);\r\n registerRideUpdateCommand(rideCmd, deps);\r\n registerRideTripStatusCommand(rideCmd, deps);\r\n registerListOrdersCommand(rideCmd, deps);\r\n registerRideCallbackCommands(rideCmd, deps);\r\n\r\n // services command group (capability discovery via platform backend + local fallback).\r\n // These commands gate backend capabilities against the CLI's own command tree,\r\n // so they need the root `program` to introspect registered nouns/verbs, plus\r\n // the host-root discovery client.\r\n const servicesCmd = program.command('services').description('Merchant service discovery');\r\n registerServicesListCommand(servicesCmd, { discoveryClient, program });\r\n registerServiceGetCommand(servicesCmd, { discoveryClient, program });\r\n\r\n // orders command group (unified cross-provider order index, GET /orders).\r\n // Spans ride + hotel + flight (+ future providers) in one call. Prefer a\r\n // domain-specific command only when provider-specific columns are needed.\r\n const ordersCmd = program.command('orders').description(\r\n 'Unified cross-provider order index (spans ride + hotel + flight). Use list/get for generic \"my orders\" requests (use ride-elife/hotel-redaug/flight-flink commands once the business is known); pay-batch settles a batch of AWAITING_PAYMENT orders in one aggregate payment (trip checkout).',\r\n );\r\n registerOrdersListCommand(ordersCmd, deps);\r\n registerOrdersGetCommand(ordersCmd, deps);\r\n // 行程聚合支付:orders pay-batch —— `orders__aggregate__pay-batch` 逻辑工具名的物理落点\r\n // (供 trip-aggregate 的 pay-orders write verb 经 UniversalGateway 调用)。\r\n registerOrdersPayBatchCommand(ordersCmd, deps);\r\n // 查 pay-batch 结算进度(只读,不重发付款)。\r\n registerOrdersGetPaymentGroupCommand(ordersCmd, deps);\r\n\r\n // hotel-redaug command group (Redaug hotel booking) — 13 verbs\r\n const hotelCmd = program.command('hotel-redaug').description(\r\n `Hotel booking (Redaug) — international hotel search, quote, create-order, pay-order, cancel, and check-out.\r\n\r\nWorkflow (typical order):\r\n 1. find-destination Resolve a place name → coordinates (or destination_id via list-cities)\r\n 2. hotel-filters (optional) Get filter options for a location (star/brand/facility codes)\r\n 3. search Search hotels by coordinates OR destination_id, with date/guest/filter params\r\n 4. hotel-detail View hotel + rooms[] (area/floor/beds/photos). Call it for the chosen/\r\n shortlisted hotel BEFORE quote — quote's room_name alone has no detail,\r\n and the user should see real room info before picking a rate at step 5.\r\n 5. quote Get real-time room rates for a hotel + dates → product_token + price_items.\r\n Pair each rate with hotel-detail's rooms[] (match by room_name) before\r\n presenting options to the user.\r\n 6. create-order Create order using product_token from quote (lock inventory, no charge)\r\n 7. pay-order Settle the order by --order-id (path chosen server-side by billing_mode)\r\n 8. get Poll order status until CONFIRMED (or use --watch for NDJSON stream)\r\n 9. cancel Cancel an order (whole-order, within policy)\r\n 10. checkout Apply for partial check-out / out-of-policy cancellation (async)\r\n 11. get-checkout Poll checkout application status\r\n 12. list-orders List developer's hotel orders\r\n\r\nKey notes:\r\n • search has two location branches: --destination-id OR --lat/--lng (exactly one required)\r\n • hotel-detail's rooms[] is the actual room info (area/beds/photos) — quote's room_name is\r\n just a bare label; show both together before asking the user to pick a rate\r\n • create-order locks inventory without charging; order enters AWAITING_PAYMENT\r\n • pay-order settles the order by --order-id; the path is chosen server-side by\r\n billing_mode. For pay_per_call the user pays via EVO using the order_id\r\n as the merchantTransID first; use --watch to poll until PAID\r\n • All amounts are DECIMAL (e.g. 10.00 = ten yuan), never minor units (cents)\r\n • product_token from quote is opaque — pass it unchanged to create-order\r\n • price_items from quote must be copied verbatim as --price-items JSON array to create-order`,\r\n );\r\n registerHotelSearchCommand(hotelCmd, deps);\r\n registerHotelQuoteCommand(hotelCmd, deps);\r\n registerHotelCreateOrderCommand(hotelCmd, deps);\r\n registerHotelPayOrderCommand(hotelCmd, deps);\r\n registerHotelGetCommand(hotelCmd, deps);\r\n registerHotelCancelCommand(hotelCmd, deps);\r\n registerHotelCheckoutCommand(hotelCmd, deps);\r\n registerHotelGetCheckoutCommand(hotelCmd, deps);\r\n registerHotelListOrdersCommand(hotelCmd, deps);\r\n registerHotelFindDestinationCommand(hotelCmd, deps);\r\n registerHotelFiltersCommand(hotelCmd, deps);\r\n registerHotelListCitiesCommand(hotelCmd, deps);\r\n registerHotelDetailCommand(hotelCmd, deps);\r\n registerHotelSkillCommand(hotelCmd);\r\n\r\n // flight-flink command group (Flink flight booking) — 18 verbs\r\n const flightCmd = program.command('flight-flink').description(\r\n `Flight booking (Flink) — international flight search, price verification, two-step create-then-pay ticketing, plus change (rebooking) and refund.\r\n\r\nWorkflow (typical order):\r\n 1. find-airport Resolve a place name → IATA city/airport codes\r\n 2. search Search flights (one-way/round-trip/multi-city). journeys carries ALL legs;\r\n round-trip/multi-city: relay the chosen offer's next_journey_ids into\r\n --journey-id until is_final_leg is true\r\n 3. verify Verify the fare → authoritative product_token + price_changed flag\r\n 4. create-order Create the order using verify's product_token (locks the fare, no charge)\r\n 5. pay-order Settle by --order-no (triggers ticketing); order → PAID\r\n 6. get-order Poll by --order-no until TICKETED (or use --watch for NDJSON)\r\n cancel-order (optional) Cancel an un-ticketed order (+ refund)\r\n change-* (optional) change-search → change-apply → change-detail; confirm via pay-order, cancel via change-cancel\r\n refund-* (optional) refund-apply → refund-detail → refund-confirm (1=confirm, 2=cancel)\r\n list-orders List the developer's flight orders\r\n\r\nKey notes:\r\n • product_token from search/verify is opaque — pass it unchanged; verify's token supersedes search's\r\n • passengers is a JSON array; gender/id_type are STRINGS (\"1\"/\"2\"); child/infant need adult_passenger_name\r\n • Ticketing is asynchronous — never claim \"booked\" until get-order returns TICKETED\r\n • create-order and pay-order are separate steps; create-order does NOT charge\r\n • Write verbs require --idempotency-key; reuse the SAME key when retrying the same intent`,\r\n );\r\n registerFindAirportCommand(flightCmd, deps);\r\n registerListAirportsCommand(flightCmd, deps);\r\n registerListAirlinesCommand(flightCmd, deps);\r\n registerListNationalitiesCommand(flightCmd, deps);\r\n registerFlightSearchCommand(flightCmd, deps);\r\n registerMoreOffersCommand(flightCmd, deps);\r\n registerVerifyCommand(flightCmd, deps);\r\n registerFlightCreateOrderCommand(flightCmd, deps);\r\n registerFlightPayOrderCommand(flightCmd, deps);\r\n registerFlightGetOrderCommand(flightCmd, deps);\r\n registerFlightCancelOrderCommand(flightCmd, deps);\r\n registerFlightListOrdersCommand(flightCmd, deps);\r\n registerChangeSearchCommand(flightCmd, deps);\r\n registerChangeApplyCommand(flightCmd, deps);\r\n registerChangeDetailCommand(flightCmd, deps);\r\n registerChangeCancelCommand(flightCmd, deps);\r\n registerChangePayCommand(flightCmd, deps);\r\n registerRefundApplyCommand(flightCmd, deps);\r\n registerRefundDetailCommand(flightCmd, deps);\r\n registerRefundConfirmCommand(flightCmd, deps);\r\n registerFlightSkillCommand(flightCmd);\r\n\r\n // Parse and execute\r\n await program.parseAsync(process.argv);\r\n}\r\n\r\n/**\r\n * Resolve the active output format for error reporting. Prefers the parsed\r\n * global `--format` flag (available on `programRef` once the program is\r\n * constructed; defaults to `json` for merchant-cli); if an error was thrown\r\n * before parsing, falls back to `resolveFormat(undefined)` (which consults\r\n * `AGENZO_FORMAT`, else `table`).\r\n */\r\nfunction resolveActiveFormat(): OutputFormat {\r\n const flag = programRef?.opts().format as string | undefined;\r\n return resolveFormat(flag);\r\n}\r\n\r\n/**\r\n * Top-level failure path. Writes the error envelope to stderr in the resolved\r\n * format and exits with the mapped code (1–5). stdout is left untouched so a\r\n * partial machine payload is never emitted on failure.\r\n *\r\n * - `json`: a single `{ error: { code, code_num, message, request_id?, upstream? } }` envelope (§8.2).\r\n * - `table`: `✗ [<code_num>] <message>`, plus a ` Order: <order_id>` line when the\r\n * error carries a recoverable order id (e.g. `PAYORDER_FAILED`, where the order\r\n * exists and only payment must be retried), plus a ` ↳ [<upstream.code>]\r\n * <upstream.message>` line when this failure originated from a third-party\r\n * upstream (e.g. Redaug/eLife) the platform calls out to.\r\n */\r\nfunction reportError(error: unknown): never {\r\n const envelope = toErrorEnvelope(error);\r\n const format = resolveActiveFormat();\r\n\r\n if (format === 'json') {\r\n console.error(JSON.stringify(envelope));\r\n } else {\r\n console.error(\r\n Formatter.status('error', `[${envelope.error.code_num}] ${envelope.error.message}`),\r\n );\r\n for (const line of errorDetailLines(envelope)) {\r\n console.error(line);\r\n }\r\n if (envelope.error.upstream) {\r\n console.error(` ↳ [${envelope.error.upstream.code}] ${envelope.error.upstream.message}`);\r\n }\r\n // Unknown (non-CliError) failures keep the --verbose raw-dump affordance.\r\n if (!(error instanceof CliError) && process.argv.includes('--verbose')) {\r\n console.error(error);\r\n }\r\n }\r\n\r\n // exitCodeFor owns the error-class → exit-code matrix, including\r\n // UpgradeRequiredError → 2 and UserCancelError → 5.\r\n process.exit(exitCodeFor(error));\r\n}\r\n\r\n// Ctrl+C / SIGINT maps to a user-cancel (exit 5) via the same envelope path.\r\nprocess.on('SIGINT', () => {\r\n reportError(new UserCancelError());\r\n});\r\n\r\n// Global error handler. Normal completion exits 0 naturally (the mapper is\r\n// never consulted on success).\r\nmain().catch(reportError);\r\n","/**\r\n * Unified outward-facing CLI error-code catalog (cli-design §8, single source of truth).\r\n *\r\n * Every outward code has both a string code (the preferred routing key) and a\r\n * numeric code (compact, convenient for log aggregation). The two map 1:1, bound\r\n * by {@link CODE_NUM}. String codes are grouped by domain prefix; numeric codes\r\n * are segmented by the same domains (§8.3).\r\n *\r\n * Note: `UPGRADE_REQUIRED` (CLI too old) and `CLIENT_ABORTED` (user-initiated\r\n * cancel) are non-business codes detected locally by the CLI. They are not part\r\n * of the §8.4 business dictionary and are allocated at the tail of the CLIENT range.\r\n */\r\nexport type ErrorCode =\r\n // AUTH_* (1000-1099)\r\n | 'AUTH_SESSION_EXPIRED'\r\n | 'AUTH_MAGIC_LINK_EXPIRED'\r\n | 'AUTH_INVITE_CODE_REQUIRED'\r\n | 'AUTH_INVITE_CODE_INVALID'\r\n // KEY_* (1100-1199)\r\n | 'KEY_INVALID'\r\n | 'KEY_SCOPE_DENIED'\r\n // PAYMENT_METHOD_* (1400-1499)\r\n | 'PAYMENT_METHOD_NOT_FOUND'\r\n | 'PAYMENT_METHOD_DISABLED'\r\n | 'INVALID_PAYMENT_METHOD'\r\n // RESOURCE_* (2000-2099)\r\n | 'RESOURCE_NOT_FOUND'\r\n | 'RESOURCE_CONFLICT'\r\n | 'RESOURCE_STATE_INVALID'\r\n // PARAM_* (2100-2199)\r\n | 'PARAM_INVALID'\r\n | 'PARAM_IDEMPOTENCY_KEY_REQUIRED'\r\n | 'PARAM_IDEMPOTENCY_KEY_CONFLICT'\r\n // BILLING_* (3000-3099)\r\n | 'BILLING_MODE_MISMATCH'\r\n // ACCOUNT_* (3100-3199)\r\n | 'ACCOUNT_NOT_FOUND'\r\n | 'ACCOUNT_SUSPENDED'\r\n | 'ACCOUNT_INSUFFICIENT_BALANCE'\r\n // PAYMENT_ORDER_* (3200-3299)\r\n | 'PAYMENT_ORDER_NOT_FOUND'\r\n | 'PAYMENT_ORDER_NOT_PAID'\r\n | 'PAYMENT_ORDER_MISMATCH'\r\n | 'PAYMENT_ORDER_ALREADY_CONSUMED'\r\n // TOKEN_* (4000-4099)\r\n | 'TOKEN_FEATURE_DISABLED'\r\n // SERVICE_* (4100-4199)\r\n | 'SERVICE_NOT_FOUND'\r\n // ride business codes (4200-4299)\r\n | 'VEHICLE_UNAVAILABLE'\r\n | 'QUOTE_EXPIRED'\r\n | 'BOOKING_FAILED'\r\n | 'CANCELLATION_NOT_ALLOWED'\r\n | 'PRICE_MISMATCH'\r\n | 'VEHICLE_CLASS_MISMATCH'\r\n | 'PAYMENT_METHOD_REQUIRED'\r\n | 'QUOTE_CACHE_UNAVAILABLE'\r\n | 'ARREARS_OUTSTANDING'\r\n | 'CONTACT_REQUIRED'\r\n | 'INVALID_PHONE'\r\n | 'SEAT_LIMIT_EXCEEDED'\r\n | 'RIDE_NOT_FOUND'\r\n // hotel business codes (4300-4399)\r\n | 'NO_AVAILABILITY'\r\n | 'PRICE_CHANGED'\r\n | 'NAME_FORMAT_INVALID'\r\n | 'HOTEL_ORDER_NOT_FOUND'\r\n | 'ALREADY_CANCELLED'\r\n | 'CHECKOUT_NOT_ALLOWED'\r\n | 'CHECKOUT_TASK_NOT_FOUND'\r\n | 'PAY_PER_CALL_NOT_AVAILABLE'\r\n | 'HOTEL_NOT_FOUND'\r\n | 'BOOKING_RESTRICTED'\r\n | 'PAYORDER_FAILED'\r\n | 'PAYORDER_FAILED_AFTER_PAYMENT'\r\n // flight business codes (4400-4499)\r\n | 'OFFER_UNAVAILABLE'\r\n // RATE_* (5000-5099)\r\n | 'RATE_LIMITED'\r\n // UPSTREAM_* (5100-5199)\r\n | 'UPSTREAM_ERROR'\r\n // INTERNAL_* (5200-5299)\r\n | 'INTERNAL_ERROR'\r\n // NOT_IMPLEMENTED (5300)\r\n | 'NOT_IMPLEMENTED'\r\n // CLIENT_* (9000-9099) — produced locally by the CLI\r\n | 'CLIENT_NOT_SIGNED_IN'\r\n | 'CLIENT_LOGIN_TIMEOUT'\r\n | 'CLIENT_ORG_NOT_LOCAL'\r\n | 'CLIENT_ORG_WRONG_ENV'\r\n | 'CLIENT_NO_PAYMENT_METHOD'\r\n | 'CLIENT_CARD_NOT_MATCHED'\r\n | 'CLIENT_ABORTED'\r\n // Non-business code (detected locally by the CLI)\r\n | 'UPGRADE_REQUIRED';\r\n\r\n/**\r\n * String code → numeric code (§8.4). Each outward code's numeric value is\r\n * uniquely bound by this table; once published it is append-only (never changed).\r\n */\r\nexport const CODE_NUM: Record<ErrorCode, number> = {\r\n AUTH_SESSION_EXPIRED: 1001,\r\n AUTH_MAGIC_LINK_EXPIRED: 1002,\r\n AUTH_INVITE_CODE_REQUIRED: 1003,\r\n AUTH_INVITE_CODE_INVALID: 1004,\r\n KEY_INVALID: 1101,\r\n KEY_SCOPE_DENIED: 1102,\r\n PAYMENT_METHOD_NOT_FOUND: 1401,\r\n PAYMENT_METHOD_DISABLED: 1402,\r\n INVALID_PAYMENT_METHOD: 1403,\r\n RESOURCE_NOT_FOUND: 2001,\r\n RESOURCE_CONFLICT: 2002,\r\n RESOURCE_STATE_INVALID: 2003,\r\n PARAM_INVALID: 2101,\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 2102,\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 2103,\r\n BILLING_MODE_MISMATCH: 3001,\r\n ACCOUNT_NOT_FOUND: 3101,\r\n ACCOUNT_SUSPENDED: 3102,\r\n ACCOUNT_INSUFFICIENT_BALANCE: 3103,\r\n PAYMENT_ORDER_NOT_FOUND: 3201,\r\n PAYMENT_ORDER_NOT_PAID: 3202,\r\n PAYMENT_ORDER_MISMATCH: 3203,\r\n PAYMENT_ORDER_ALREADY_CONSUMED: 3204,\r\n TOKEN_FEATURE_DISABLED: 4001,\r\n SERVICE_NOT_FOUND: 4101,\r\n VEHICLE_UNAVAILABLE: 4201,\r\n QUOTE_EXPIRED: 4202,\r\n BOOKING_FAILED: 4203,\r\n CANCELLATION_NOT_ALLOWED: 4204,\r\n PRICE_MISMATCH: 4205,\r\n VEHICLE_CLASS_MISMATCH: 4206,\r\n PAYMENT_METHOD_REQUIRED: 4207,\r\n QUOTE_CACHE_UNAVAILABLE: 4208,\r\n ARREARS_OUTSTANDING: 4209,\r\n CONTACT_REQUIRED: 4210,\r\n INVALID_PHONE: 4211,\r\n SEAT_LIMIT_EXCEEDED: 4213,\r\n RIDE_NOT_FOUND: 4212,\r\n NO_AVAILABILITY: 4301,\r\n PRICE_CHANGED: 4302,\r\n NAME_FORMAT_INVALID: 4303,\r\n HOTEL_ORDER_NOT_FOUND: 4304,\r\n ALREADY_CANCELLED: 4305,\r\n CHECKOUT_NOT_ALLOWED: 4306,\r\n CHECKOUT_TASK_NOT_FOUND: 4307,\r\n PAY_PER_CALL_NOT_AVAILABLE: 4308,\r\n HOTEL_NOT_FOUND: 4309,\r\n BOOKING_RESTRICTED: 4310,\r\n PAYORDER_FAILED: 4311,\r\n PAYORDER_FAILED_AFTER_PAYMENT: 4312,\r\n OFFER_UNAVAILABLE: 4401,\r\n RATE_LIMITED: 5001,\r\n UPSTREAM_ERROR: 5101,\r\n INTERNAL_ERROR: 5201,\r\n NOT_IMPLEMENTED: 5300,\r\n CLIENT_NOT_SIGNED_IN: 9001,\r\n CLIENT_LOGIN_TIMEOUT: 9002,\r\n CLIENT_ORG_NOT_LOCAL: 9003,\r\n CLIENT_ORG_WRONG_ENV: 9004,\r\n CLIENT_NO_PAYMENT_METHOD: 9005,\r\n CLIENT_CARD_NOT_MATCHED: 9006,\r\n CLIENT_ABORTED: 9007,\r\n UPGRADE_REQUIRED: 9008,\r\n};\r\n\r\n/** Look up the numeric code for a string error code. */\r\nexport function codeNum(code: ErrorCode): number {\r\n return CODE_NUM[code];\r\n}\r\n","import { type ErrorCode, CODE_NUM, codeNum } from './error-catalog.js';\r\nimport type { ApiError, UpstreamError } from '../api-client/client.js';\r\n\r\n/** Base class for all CLI errors. Carries the CLI-facing error code (§8.4). */\r\nexport class CliError extends Error {\r\n constructor(\r\n public readonly code: ErrorCode,\r\n message: string,\r\n public readonly statusCode?: number,\r\n public readonly requestId?: string,\r\n public readonly upstream?: UpstreamError,\r\n /**\r\n * The backend's own raw message for this error (e.g. a Pydantic\r\n * validation detail such as \"child_seat_count: must be between 0 and 5\",\r\n * or a provider adapter's `user_hint`). Kept SEPARATE from `message`\r\n * (the stable, catalog-owned text for `code`) so callers always get a\r\n * predictable top-level message while still being able to see exactly\r\n * what the backend said. Surfaced in the envelope as `backend_message`\r\n * when present and different from the stable message.\r\n */\r\n public readonly backendMessage?: string,\r\n /** Safe structured error data that callers may use for recovery. */\r\n public readonly data?: Record<string, unknown>,\r\n ) {\r\n super(message);\r\n this.name = 'CliError';\r\n }\r\n\r\n /**\r\n * Map a backend ApiError to a CLI-facing code (§8.5 transitional mapping).\r\n * Backend numeric codes / HTTP status are translated to §8.4 string codes.\r\n * The top-level `message` is always the stable, catalog-owned text for the\r\n * resolved code (§8.1 principle 4 — never let raw backend text become the\r\n * primary/stable message). The backend's own message is NOT discarded,\r\n * though: it is preserved on `backendMessage` and surfaced in the envelope\r\n * as `backend_message` so the caller can see the real reason (e.g. which\r\n * field failed validation) alongside the stable code/message.\r\n *\r\n * The optional `opts.auth` selects the auth semantics for the 401 mapping:\r\n * - `'bearer'` (default, admin-cli Bearer Token): 401 → `AUTH_SESSION_EXPIRED`.\r\n * - `'api-key'` (token-cli `X-Api-Key`): 401 → `KEY_INVALID`.\r\n * 403 maps to `KEY_SCOPE_DENIED` under both auth modes. Omitting `opts`\r\n * preserves the original Bearer behavior exactly (§8.5 / requirement 6.4).\r\n *\r\n * Domain string-code routing (D3 / requirement 5.4): when the backend\r\n * supplies a string `error.code` in the v3 envelope that is a known §8 code\r\n * (present in {@link CODE_NUM}), it is used verbatim as the CLI-facing code\r\n * so ride/merchant-specific codes (`QUOTE_EXPIRED`, `VEHICLE_UNAVAILABLE`,\r\n * `BILLING_MODE_MISMATCH`, `PAYMENT_ORDER_*`, …) survive intact. Otherwise —\r\n * including when no string code is provided, as is the case for admin/token\r\n * today — mapping falls back to the HTTP-status table below, leaving the\r\n * existing Bearer/api-key behavior unchanged.\r\n */\r\n static fromApi(error: ApiError, opts?: { auth?: 'bearer' | 'api-key' }): CliError {\r\n // D3: prefer the backend's string code when it is a known §8 catalog code.\r\n if (error.code && isKnownErrorCode(error.code)) {\r\n return new CliError(\r\n error.code,\r\n STABLE_MESSAGE[error.code] ?? 'Request failed. Please check your input and retry.',\r\n error.statusCode,\r\n error.requestId,\r\n error.upstream,\r\n error.errorMessage,\r\n error.data,\r\n );\r\n }\r\n\r\n const status = error.statusCode;\r\n let code: ErrorCode;\r\n\r\n if (status === 401) code = opts?.auth === 'api-key' ? 'KEY_INVALID' : 'AUTH_SESSION_EXPIRED';\r\n else if (status === 403) code = 'KEY_SCOPE_DENIED';\r\n else if (status === 404) code = 'RESOURCE_NOT_FOUND';\r\n else if (status === 409) code = 'RESOURCE_CONFLICT';\r\n else if (status === 429) code = 'RATE_LIMITED';\r\n else if (status >= 500) code = 'INTERNAL_ERROR';\r\n else code = 'PARAM_INVALID'; // other 4xx (incl. 400/422)\r\n\r\n return new CliError(\r\n code,\r\n STABLE_MESSAGE[code] ?? 'Request failed. Please check your input and retry.',\r\n status,\r\n error.requestId,\r\n error.upstream,\r\n error.errorMessage,\r\n error.data,\r\n );\r\n }\r\n}\r\n\r\n/** Network / connectivity failure → UPSTREAM_ERROR. Never leak the internal URL/path. */\r\nexport class NetworkError extends CliError {\r\n constructor(_url: string, timeout?: number, _cause?: Error) {\r\n super(\r\n 'UPSTREAM_ERROR',\r\n timeout\r\n ? 'The request timed out. The service may be temporarily unavailable — please retry.'\r\n : 'Connection failed. The service may be temporarily unavailable — please retry.',\r\n );\r\n }\r\n}\r\n\r\n/** Auth / session failures. Code chosen by message intent (§8.4 AUTH_* / CLIENT_*). */\r\nexport class AuthError extends CliError {\r\n constructor(message: string, public readonly suggestion: string) {\r\n const m = message.toLowerCase();\r\n const code: ErrorCode = m.includes('not signed in')\r\n ? 'CLIENT_NOT_SIGNED_IN'\r\n : m.includes('time')\r\n ? 'CLIENT_LOGIN_TIMEOUT'\r\n : m.includes('magic link')\r\n ? 'AUTH_MAGIC_LINK_EXPIRED'\r\n : 'AUTH_SESSION_EXPIRED';\r\n super(code, message || 'Unknown error');\r\n }\r\n}\r\n\r\nexport class ConfigError extends CliError {\r\n constructor(message: string, public readonly filePath: string) {\r\n super('INTERNAL_ERROR', message || 'Unknown error');\r\n }\r\n}\r\n\r\nexport class ValidationError extends CliError {\r\n constructor(message: string) {\r\n super('PARAM_INVALID', message || 'Unknown error');\r\n }\r\n}\r\n\r\nexport class IdempotencyKeyRequiredError extends CliError {\r\n constructor(commandPath: string) {\r\n super(\r\n 'PARAM_IDEMPOTENCY_KEY_REQUIRED',\r\n `\\`${commandPath}\\` requires --idempotency-key <key>. Supply a unique key so the write can be safely retried.`,\r\n );\r\n }\r\n}\r\n\r\nexport class UpgradeRequiredError extends CliError {\r\n constructor(currentVersion: string, minVersion: string, upgradeCommand: string) {\r\n super(\r\n 'UPGRADE_REQUIRED',\r\n `agenzo-admin-cli ${currentVersion} is out of date — the server requires ${minVersion} or newer. To upgrade, run: ${upgradeCommand}`,\r\n );\r\n }\r\n}\r\n\r\nexport class UserCancelError extends CliError {\r\n constructor(message = 'Operation cancelled by user') {\r\n super('CLIENT_ABORTED', message || 'Unknown error');\r\n }\r\n}\r\n\r\n/** Type guard: is `value` a known §8 string error code (present in CODE_NUM)? */\r\nfunction isKnownErrorCode(value: string): value is ErrorCode {\r\n return Object.prototype.hasOwnProperty.call(CODE_NUM, value);\r\n}\r\n\r\n/**\r\n * Stable, CLI-owned message per code used when mapping opaque backend errors\r\n * (§8.1 principle 4: never surface raw backend detail).\r\n */\r\nconst STABLE_MESSAGE: Partial<Record<ErrorCode, string>> = {\r\n AUTH_SESSION_EXPIRED: 'Your session has expired. Please run `agenzo-admin-cli auth login` again.',\r\n AUTH_MAGIC_LINK_EXPIRED: 'Verification link is invalid or has expired. Please request a new one.',\r\n AUTH_INVITE_CODE_REQUIRED: 'An invitation code is required to register.',\r\n AUTH_INVITE_CODE_INVALID: 'The invitation code is invalid.',\r\n KEY_INVALID: 'The API key is invalid or has been revoked. Please check your --api-key and retry.',\r\n KEY_SCOPE_DENIED: 'This API key does not have the required scope for this command.',\r\n PAYMENT_METHOD_NOT_FOUND: 'Payment method not found.',\r\n PAYMENT_METHOD_DISABLED: 'This payment method has been disabled.',\r\n INVALID_PAYMENT_METHOD: 'The payment method is not available for this operation.',\r\n RESOURCE_NOT_FOUND: 'The resource was not found or does not belong to the current organization.',\r\n RESOURCE_CONFLICT: 'A resource with the same unique value already exists.',\r\n RESOURCE_STATE_INVALID: 'The resource is in a state that does not permit this operation.',\r\n RATE_LIMITED: 'Too many requests. Please back off and retry.',\r\n UPSTREAM_ERROR: 'A third-party service is temporarily unavailable. Please try again later.',\r\n INTERNAL_ERROR: 'Something went wrong on the server. Please retry and note the request_id.',\r\n PARAM_INVALID: 'One or more parameters are invalid. Please check your input and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'A request with this idempotency key was already processed with different parameters.',\r\n TOKEN_FEATURE_DISABLED: 'VCN creation is not supported yet. Coming soon.',\r\n BILLING_MODE_MISMATCH: 'The billing mode does not match this operation. Please verify your account billing configuration.',\r\n ACCOUNT_NOT_FOUND: 'The settlement account was not found.',\r\n ACCOUNT_SUSPENDED: 'The settlement account is suspended. Please contact support.',\r\n ACCOUNT_INSUFFICIENT_BALANCE: 'The settlement account has insufficient balance for this operation.',\r\n PAYMENT_ORDER_NOT_FOUND: 'The payment order was not found.',\r\n PAYMENT_ORDER_NOT_PAID: 'The payment order has not been paid. Please complete payment and retry.',\r\n PAYMENT_ORDER_MISMATCH: 'The payment order does not match this order. Please check the --payment-order-id.',\r\n PAYMENT_ORDER_ALREADY_CONSUMED: 'The payment order has already been consumed by another booking.',\r\n SERVICE_NOT_FOUND: 'The requested service was not found.',\r\n VEHICLE_UNAVAILABLE: 'No vehicle is available for the requested trip. Please try a different time or class.',\r\n QUOTE_EXPIRED: 'The quote has expired. Please request a new quote and retry.',\r\n BOOKING_FAILED: 'The booking could not be completed. Please retry.',\r\n PRICE_MISMATCH: 'The price does not match the quote. Re-quote and use the exact amount from the quote response.',\r\n VEHICLE_CLASS_MISMATCH: 'The vehicle class does not match the quote. Use the vehicle class from the quote response.',\r\n PAYMENT_METHOD_REQUIRED: 'Pay-per-call billing requires an active payment method. Please add a card first.',\r\n QUOTE_CACHE_UNAVAILABLE: 'Quote cache is temporarily unavailable. Please request a new quote and retry.',\r\n ARREARS_OUTSTANDING: 'You have outstanding arrears. Please settle your balance before booking a new ride.',\r\n CONTACT_REQUIRED: 'Passenger contact information is required. Please provide a passenger name and phone number.',\r\n INVALID_PHONE: 'The passenger phone number is not valid. Please provide a valid international number.',\r\n SEAT_LIMIT_EXCEEDED: 'The number of child/infant/toddler seats exceeds the vehicle capacity. Reduce seats or choose a larger vehicle.',\r\n RIDE_NOT_FOUND: 'The ride order was not found or does not belong to you.',\r\n CANCELLATION_NOT_ALLOWED: 'This order cannot be cancelled in its current state.',\r\n NO_AVAILABILITY: 'No rooms available for the selected hotel and dates.',\r\n PRICE_CHANGED: 'The price changed since the quote. Re-quote and confirm.',\r\n NAME_FORMAT_INVALID: 'The guest name format is not accepted; use Latin letters.',\r\n HOTEL_ORDER_NOT_FOUND: 'Hotel order not found.',\r\n ALREADY_CANCELLED: 'This hotel order is already cancelled.',\r\n CHECKOUT_NOT_ALLOWED: 'A partial check-out is not allowed in the current state.',\r\n CHECKOUT_TASK_NOT_FOUND: 'Check-out application not found.',\r\n PAY_PER_CALL_NOT_AVAILABLE: 'Pay-per-call billing is not available; use monthly_settlement.',\r\n HOTEL_NOT_FOUND: 'This hotel is no longer available from the supplier.',\r\n BOOKING_RESTRICTED:\r\n \"This room has a booking condition that your request doesn't meet. Please check the room's booking rules and adjust your request.\",\r\n PAYORDER_FAILED: 'The hotel order was created, but payment failed. Retry payment for the existing order.',\r\n PAYORDER_FAILED_AFTER_PAYMENT: 'Payment was received, but hotel confirmation failed. Contact support for reconciliation.',\r\n OFFER_UNAVAILABLE: 'The selected flight is no longer available. Please search again and pick another flight.',\r\n NOT_IMPLEMENTED: 'This operation is not implemented yet.',\r\n};\r\n\r\n/**\r\n * §8.2 error envelope: `{ error: { code, code_num, message, request_id?, upstream?, backend_message? } }`.\r\n *\r\n * `message` is always the stable, catalog-owned text for `code` — safe to\r\n * match on and never changes shape. `backend_message` (when present) is the\r\n * backend's own raw text for this specific failure (e.g. which field failed\r\n * validation, or a provider's real rejection reason) — diagnostic, not a\r\n * stable contract, but no longer discarded.\r\n */\r\nexport interface ErrorEnvelope {\r\n error: {\r\n code: ErrorCode;\r\n code_num: number;\r\n message: string;\r\n request_id?: string;\r\n upstream?: UpstreamError;\r\n backend_message?: string;\r\n data?: Record<string, unknown>;\r\n };\r\n}\r\n\r\n/**\r\n * Recovery detail lines for the human-readable (`table`) error output.\r\n *\r\n * `json` callers read `error.data` straight off the envelope, but the table\r\n * format used to print only `message` — so a `PAYORDER_FAILED` telling the\r\n * user to \"retry payment for the existing order\" left them without the order\r\n * id to retry against. Returns one ` Order: <order_id>` line when the error\r\n * carries a usable order id, and nothing otherwise.\r\n */\r\nexport function errorDetailLines(envelope: ErrorEnvelope): string[] {\r\n const orderId = envelope.error.data?.order_id;\r\n if (typeof orderId !== 'string' || orderId.length === 0) return [];\r\n return [` Order: ${orderId}`];\r\n}\r\n\r\nexport function toErrorEnvelope(error: unknown): ErrorEnvelope {\r\n if (error instanceof CliError) {\r\n const stableMessage = error.message || 'Unknown error';\r\n // Only surface backend_message when it adds information beyond the\r\n // stable message (avoid noisy duplication when they already match).\r\n const backendMessage =\r\n error.backendMessage && error.backendMessage !== stableMessage\r\n ? error.backendMessage\r\n : undefined;\r\n return {\r\n error: {\r\n code: error.code,\r\n code_num: codeNum(error.code),\r\n message: stableMessage,\r\n ...(error.requestId ? { request_id: error.requestId } : {}),\r\n ...(error.upstream ? { upstream: error.upstream } : {}),\r\n ...(backendMessage ? { backend_message: backendMessage } : {}),\r\n ...(error.data ? { data: error.data } : {}),\r\n },\r\n };\r\n }\r\n\r\n const message =\r\n error instanceof Error\r\n ? error.message\r\n : typeof error === 'string'\r\n ? error\r\n : 'Unexpected error';\r\n return {\r\n error: {\r\n code: 'INTERNAL_ERROR',\r\n code_num: codeNum('INTERNAL_ERROR'),\r\n message: message || 'Unknown error',\r\n },\r\n };\r\n}\r\n","/**\r\n * CLI version + min-version comparator.\r\n *\r\n * The CLI's current version is read from `package.json` at runtime. This is\r\n * the single source of truth — bumping `package.json` automatically updates\r\n * what the CLI reports and what it compares against the server-advertised\r\n * minimum (`X-CLI-Min-Version` response header, driven by\r\n * `AGENT_PAY_CLI_MIN_VERSION` on the server).\r\n *\r\n * Only numeric major.minor.patch segments are compared; pre-release and build\r\n * metadata suffixes are stripped. This matches our versioning scheme and\r\n * avoids pulling in `semver` for a single `<` check.\r\n */\r\n\r\nimport { readFileSync } from 'node:fs';\r\nimport { dirname, join } from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\n\r\n/** Command the user should run to pick up the latest CLI. */\r\nexport const UPGRADE_COMMAND = 'npm install -g agenzo-admin-cli@latest';\r\n\r\n/**\r\n * Hard-coded fallback used only when `package.json` cannot be read at runtime\r\n * (unusual packaging/bundling edge cases). Keep this in sync with\r\n * `package.json`'s `version` on every release so the reported version and\r\n * the User-Agent stay accurate even in the degraded path.\r\n */\r\nexport const FALLBACK_VERSION = '0.1.1';\r\n\r\nlet cachedVersion: string | null = null;\r\n\r\nexport function getCurrentVersion(): string {\r\n if (cachedVersion !== null) return cachedVersion;\r\n // Walk up from the compiled file (dist/index.js) or source layout to find\r\n // package.json. Both `dist/..` and `src/utils/../..` resolve to the project\r\n // root, which is where package.json lives in a published npm install.\r\n const here = dirname(fileURLToPath(import.meta.url));\r\n const candidates = [\r\n join(here, '..', 'package.json'), // dist/ → project root\r\n join(here, '..', '..', 'package.json'), // src/utils/ → project root\r\n ];\r\n for (const p of candidates) {\r\n try {\r\n const pkg = JSON.parse(readFileSync(p, 'utf-8')) as { version?: string };\r\n if (typeof pkg.version === 'string') {\r\n cachedVersion = pkg.version;\r\n return cachedVersion;\r\n }\r\n } catch {\r\n // try next candidate\r\n }\r\n }\r\n // Degrade gracefully instead of crashing the CLI: if we can't locate\r\n // package.json at runtime, report the hard-coded fallback. The User-Agent\r\n // and any min-version comparison will still behave sensibly. We write a\r\n // one-line warning to stderr so packaging regressions remain visible.\r\n cachedVersion = FALLBACK_VERSION;\r\n // eslint-disable-next-line no-console\r\n console.warn(\r\n `[agenzo-admin-cli] package.json not found; using fallback version ${FALLBACK_VERSION}`,\r\n );\r\n return cachedVersion;\r\n}\r\n\r\n/**\r\n * Returns negative / zero / positive like `Array.sort`, comparing `a` against `b`.\r\n * Non-numeric segments and suffixes are treated as zero.\r\n */\r\nexport function compareVersions(a: string, b: string): number {\r\n const parse = (v: string): [number, number, number] => {\r\n const clean = v.trim().replace(/^v/, '').split(/[-+]/)[0];\r\n const parts = clean.split('.');\r\n return [\r\n parseInt(parts[0] ?? '0', 10) || 0,\r\n parseInt(parts[1] ?? '0', 10) || 0,\r\n parseInt(parts[2] ?? '0', 10) || 0,\r\n ];\r\n };\r\n const [a1, a2, a3] = parse(a);\r\n const [b1, b2, b3] = parse(b);\r\n if (a1 !== b1) return a1 - b1;\r\n if (a2 !== b2) return a2 - b2;\r\n return a3 - b3;\r\n}\r\n\r\nexport function isBelow(current: string, minimum: string): boolean {\r\n return compareVersions(current, minimum) < 0;\r\n}\r\n","import { NetworkError, UpgradeRequiredError } from '../errors/errors.js';\r\nimport { getCurrentVersion, isBelow, UPGRADE_COMMAND } from '../version/version.js';\r\n\r\n/**\r\n * W3C Trace Context `traceparent` 格式:`<version>-<trace-id>-<parent-id>-<flags>`。\r\n * 全零 trace-id 按规范无效,由下游解析时一并拒绝。\r\n */\r\nconst TRACEPARENT_PATTERN = /^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$/;\r\n\r\n/**\r\n * W3C `baggage` 里的业务旅程关联键 `flow_id`,以及它的合法字符集。\r\n *\r\n * `flow_id` 是「用户的一次任务」的关联键:一笔订单会横跨十几个 trace(`trace_id` 的\r\n * 粒度是一个对话轮次)和两个 A2A session,trace_id 串不起整条链路。本进程只做转发。\r\n *\r\n * 形状与 py-commons 的 `_FLOW_ID_RE` 保持一致:`flw_` 前缀 + 8~60 个 `[A-Za-z0-9_-]`。\r\n * `flw_` 前缀与仓里业务 ID 的既有约定同款(`hho_` / `ffo_` / `rio_` / `ptk_`),让这个值\r\n * 在日志里一眼可辨;前缀是强制的,等于多一道来源校验。字符集刻意比 W3C 允许的范围窄\r\n * 得多:该值来自环境变量、会被转成请求头并进入下游日志,宽松接受等于把日志注入与头部\r\n * 膨胀的风险一起转发下去。校验不过就不发,和 TRACEPARENT 同样处理。\r\n *\r\n * 两处正则必须同步改——这是跨语言的同一条契约,py-commons 侧收紧而这里没跟上,会变成\r\n * 「CLI 发出去的头被下游拒掉」这种只在集成时才暴露的错位。\r\n */\r\nconst FLOW_ID_BAGGAGE_KEY = 'agenzo.flow_id';\r\nconst FLOW_ID_PATTERN = /^flw_[A-Za-z0-9_-]{8,60}$/;\r\n\r\n/**\r\n * HTTP 超时默认值(毫秒)。可被构造参数或 AGENZO_CLI_HTTP_TIMEOUT_MS 覆盖。\r\n *\r\n * 这个值是跨服务超时阶梯的一层,不能单独调:\r\n * App 120s > orchestrator 90s > **本项 70s** > provider 45s > ledger 5s\r\n * 每层都要比下一层留出余量,好让下游的结构化错误有机会回传上来;两层取同值会导致\r\n * 上游在下游写出错误原因之前就放弃。完整依据见 platform 仓\r\n * docs/00-平台设计文档/01-跨仓文档/16-信任边界与超时预算设计.md。\r\n */\r\nexport const DEFAULT_HTTP_TIMEOUT_MS = 70000;\r\n\r\n/**\r\n * 从环境变量读 HTTP 超时;缺失或非法(非数字、<=0)时返回 null 交由调用方回落默认值。\r\n *\r\n * CLI 通常是被 orchestrator spawn 的子进程,环境变量是最自然的注入口——与\r\n * TRACEPARENT 走同一条路。这也是递减 deadline 的前置:上游要能按剩余预算\r\n * 压缩本跳超时,就必须有地方把值传进来。\r\n */\r\nexport function httpTimeoutFromEnv(\r\n env: Record<string, string | undefined> = process.env,\r\n): number | null {\r\n const raw = env.AGENZO_CLI_HTTP_TIMEOUT_MS;\r\n if (raw === undefined || raw.trim() === '') return null;\r\n const parsed = Number(raw);\r\n if (!Number.isFinite(parsed) || parsed <= 0) return null;\r\n return parsed;\r\n}\r\n\r\n/** 递减 deadline 的 HTTP 头名(剩余毫秒)。与 py-commons 的 DEADLINE_HEADER 对齐。 */\r\nexport const DEADLINE_HEADER = 'x-deadline-ms';\r\n\r\n/** W3C Baggage 的 HTTP 头名。与 py-commons 的 BAGGAGE_HEADER 对齐。 */\r\nexport const BAGGAGE_HEADER = 'baggage';\r\n\r\n/**\r\n * 从环境变量读上游给的 `flow_id` 并拼成 `baggage` 头值;缺失或不合规时返回 null。\r\n *\r\n * orchestrator spawn 本进程时经 `BAGGAGE` 注入,与 TRACEPARENT / DEADLINE_MS 同一机制。\r\n * 接受的是完整 baggage 头值(可能含其他成员),本函数只挑出 `agenzo.flow_id` 这一个成员\r\n * **重新拼**,不原样透传整串:入站 baggage 可达 8192 字节且来自不受信上游,无条件转发\r\n * 等于让外部往内部调用链里塞任意键值。\r\n */\r\nexport function baggageFromEnv(\r\n env: Record<string, string | undefined> = process.env,\r\n): string | null {\r\n const raw = env.BAGGAGE;\r\n if (raw === undefined || raw.trim() === '') return null;\r\n for (const member of raw.split(',')) {\r\n // `;` 之后是成员属性,与值无关。\r\n const pair = member.split(';', 1)[0] ?? '';\r\n const eq = pair.indexOf('=');\r\n if (eq < 0) continue;\r\n if (pair.slice(0, eq).trim() !== FLOW_ID_BAGGAGE_KEY) continue;\r\n let value = pair.slice(eq + 1).trim();\r\n try {\r\n value = decodeURIComponent(value);\r\n } catch {\r\n // 畸形百分号编码视同缺失,不把脏值发给下游。\r\n return null;\r\n }\r\n return FLOW_ID_PATTERN.test(value)\r\n ? `${FLOW_ID_BAGGAGE_KEY}=${encodeURIComponent(value)}`\r\n : null;\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * 出站前为回程预留的毫秒数:下游返回后本进程还要解析 JSON、渲染输出、写回 stdout。\r\n * 与 py-commons 的 DEFAULT_RESERVE_MS 取同值,六仓对\"预留多少\"保持一致。\r\n */\r\nexport const DEADLINE_RESERVE_MS = 200;\r\n\r\n/**\r\n * 从环境变量读上游给的剩余预算(毫秒);缺失或非法时返回 null。\r\n *\r\n * orchestrator spawn 本进程时经 DEADLINE_MS 注入(见其 backend_gateway/universal.py),\r\n * 与 TRACEPARENT 同一机制。不接受浮点串——协议规定整数毫秒,容忍浮点会让不同语言的\r\n * 实现出现取整分歧。\r\n */\r\nexport function deadlineFromEnv(\r\n env: Record<string, string | undefined> = process.env,\r\n): number | null {\r\n const raw = env.DEADLINE_MS;\r\n if (raw === undefined || raw.trim() === '') return null;\r\n if (!/^\\d+$/.test(raw.trim())) return null;\r\n const parsed = Number(raw);\r\n if (!Number.isFinite(parsed) || parsed <= 0) return null;\r\n return parsed;\r\n}\r\n\r\nexport interface ApiClientConfig {\r\n baseUrl: string;\r\n /**\r\n * HTTP 超时(毫秒)。优先级:本字段 > AGENZO_CLI_HTTP_TIMEOUT_MS > 60000。\r\n *\r\n * 显式传值优先于环境变量,这样调用方能对单个 client 做例外(如长轮询),\r\n * 不受进程级设置牵连。\r\n */\r\n timeout?: number;\r\n}\r\n\r\nexport interface ApiResponse<T> {\r\n success: true;\r\n data: T;\r\n /** Server-provided message from the unified response envelope. */\r\n message?: string;\r\n}\r\n\r\n/** Upstream error details (diagnostic only, not stable). */\r\nexport interface UpstreamError {\r\n /** Upstream-specific error code (stringified). */\r\n code: string;\r\n /** Upstream-specific error message. */\r\n message: string;\r\n}\r\n\r\nexport interface ApiError {\r\n success: false;\r\n errorCode: number;\r\n errorMessage: string;\r\n statusCode: number;\r\n /**\r\n * Raw string code from the v3 response envelope (`{ code, message, data }`),\r\n * surfaced verbatim so {@link CliError.fromApi} can route domain-specific\r\n * §8 codes (e.g. `QUOTE_EXPIRED`, `VEHICLE_UNAVAILABLE`) by string code\r\n * before falling back to HTTP-status mapping. Absent when the backend does\r\n * not provide a string code (e.g. non-JSON error responses).\r\n */\r\n code?: string;\r\n /** Server-provided request correlation id, surfaced in the error envelope. */\r\n requestId?: string;\r\n /** Safe structured error data, including recoverable order identifiers. */\r\n data?: Record<string, unknown>;\r\n /** Upstream error details for diagnostic transparency. */\r\n upstream?: UpstreamError;\r\n}\r\n\r\nexport type ApiResult<T> = ApiResponse<T> | ApiError;\r\n\r\nexport type AuthMode =\r\n | { type: 'bearer'; token: string }\r\n | { type: 'api-key'; key: string }\r\n | { type: 'none' };\r\n\r\nexport class ApiClient {\r\n private readonly baseUrl: string;\r\n private readonly timeout: number;\r\n /**\r\n * Correlation id for this CLI invocation. Generated once per `ApiClient`\r\n * instance (i.e. once per command execution — each `apps/*` entrypoint\r\n * constructs exactly one `ApiClient` per process run) and sent as\r\n * `X-Request-Id` on every request this client makes. The backend's\r\n * `RequestIdMiddleware` adopts a client-supplied `X-Request-Id` verbatim as\r\n * both `trace_id` and `request_id` (only generating its own when the header\r\n * is absent), so every HTTP call belonging to one CLI operation — including\r\n * multi-step flows like `payment-methods add`'s create + poll + get — shares\r\n * a single trace_id server-side and can be followed as one chain in logs.\r\n */\r\n private readonly requestId: string;\r\n /**\r\n * 上游给的剩余预算(毫秒),来自 `DEADLINE_MS`;未注入时为 null。\r\n *\r\n * 进程启动时读一次而不是每请求读:一次 CLI 调用就是链路上的一跳,预算属于这一跳\r\n * 整体。每请求重读会让多步流程(如 `payment-methods add` 的 create + poll + get)\r\n * 各自拿到完整预算,等于凭空放大了本跳的时间上限。\r\n */\r\n private readonly deadlineMs: number | null;\r\n /** 本进程开始时刻(单调时钟),用于算已用时间。 */\r\n private readonly startedAt: number;\r\n\r\n constructor(config: ApiClientConfig) {\r\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\r\n this.deadlineMs = deadlineFromEnv();\r\n this.startedAt = performance.now();\r\n // 超时优先级:显式传参 > AGENZO_CLI_HTTP_TIMEOUT_MS > 默认值,再由剩余预算收紧。\r\n // 预算只能压小不能放大——它代表上游还愿意等多久,本跳没有权限超出。\r\n const configured = config.timeout ?? httpTimeoutFromEnv() ?? DEFAULT_HTTP_TIMEOUT_MS;\r\n this.timeout =\r\n this.deadlineMs === null\r\n ? configured\r\n : Math.min(configured, Math.max(1, this.deadlineMs - DEADLINE_RESERVE_MS));\r\n this.requestId = crypto.randomUUID();\r\n }\r\n\r\n /** 交给下游的剩余毫秒:扣掉本进程已用时间与回程预留;无预算时返回 null。 */\r\n private remainingDeadlineMs(): number | null {\r\n if (this.deadlineMs === null) return null;\r\n const elapsed = performance.now() - this.startedAt;\r\n return Math.max(0, Math.round(this.deadlineMs - elapsed - DEADLINE_RESERVE_MS));\r\n }\r\n\r\n private buildHeaders(auth: AuthMode): Record<string, string> {\r\n const headers: Record<string, string> = {\r\n 'User-Agent': `agenzo-admin-cli/${getCurrentVersion()}`,\r\n 'X-Request-Id': this.requestId,\r\n };\r\n // 递减 deadline:把扣除本进程已用时间后的剩余量传给 platform,它再往下传给\r\n // provider / ledger。每一跳都只能收紧,链路末端因此不会超出 App 的等待上限。\r\n // 已耗尽时仍然发(值为 0),让下游能立刻返回 DEADLINE_EXCEEDED 而不是白跑一趟。\r\n const remaining = this.remainingDeadlineMs();\r\n if (remaining !== null) {\r\n headers[DEADLINE_HEADER] = String(remaining);\r\n }\r\n // 续链上游 trace:orchestrator 以子进程方式调用 CLI 时,把 W3C traceparent 放在\r\n // TRACEPARENT 环境变量里(见 orchestrator app/backend_gateway/universal.py)。\r\n // 不转发的话 platform 只能看到本进程自生成的 X-Request-Id,链路在 CLI 这里断开。\r\n // 格式非法时不发,避免把脏值写进下游 trace_id。\r\n const traceparent = process.env.TRACEPARENT;\r\n if (traceparent && TRACEPARENT_PATTERN.test(traceparent.trim())) {\r\n headers['traceparent'] = traceparent.trim();\r\n }\r\n // 业务旅程关联键 flow_id:与 traceparent 同一机制(环境变量 → 请求头)。\r\n // 不转发的话链路在 CLI 这里断开,platform 侧按 flow_id 查不到锁房 / 扣款这些调用。\r\n const baggage = baggageFromEnv();\r\n if (baggage !== null) {\r\n headers[BAGGAGE_HEADER] = baggage;\r\n }\r\n if (auth.type === 'bearer') {\r\n headers['Authorization'] = `Bearer ${auth.token}`;\r\n } else if (auth.type === 'api-key') {\r\n headers['X-Api-Key'] = auth.key;\r\n }\r\n return headers;\r\n }\r\n\r\n async get<T>(\r\n path: string,\r\n auth: AuthMode,\r\n params?: Record<string, string>,\r\n ): Promise<ApiResult<T>> {\r\n let url = `${this.baseUrl}${path}`;\r\n if (params && Object.keys(params).length > 0) {\r\n const searchParams = new URLSearchParams(params);\r\n url += `?${searchParams.toString()}`;\r\n }\r\n return this.request<T>(url, {\r\n method: 'GET',\r\n headers: this.buildHeaders(auth),\r\n });\r\n }\r\n\r\n async post<T>(\r\n path: string,\r\n auth: AuthMode,\r\n body?: Record<string, unknown>,\r\n extraHeaders?: Record<string, string>,\r\n ): Promise<ApiResult<T>> {\r\n const url = `${this.baseUrl}${path}`;\r\n const headers = this.buildHeaders(auth);\r\n headers['Content-Type'] = 'application/json';\r\n if (extraHeaders) {\r\n Object.assign(headers, extraHeaders);\r\n }\r\n return this.request<T>(url, {\r\n method: 'POST',\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n }\r\n\r\n private async request<T>(url: string, init: RequestInit): Promise<ApiResult<T>> {\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n ...init,\r\n signal: controller.signal,\r\n });\r\n\r\n // Enforce server-advertised CLI version floor before doing any work\r\n // on the response. Throws UpgradeRequiredError which is rendered and\r\n // exits at the top level (src/index.ts).\r\n this.enforceMinVersion(response.headers.get('x-cli-min-version'));\r\n\r\n // Handle non-JSON responses (e.g. 500 Internal Server Error returns plain text)\r\n const contentType = response.headers.get('content-type') ?? '';\r\n let responseBody: Record<string, unknown>;\r\n if (contentType.includes('application/json')) {\r\n responseBody = await response.json() as Record<string, unknown>;\r\n } else {\r\n const text = await response.text();\r\n if (!response.ok) {\r\n const statusMsg = this.friendlyStatusMessage(response.status);\r\n return {\r\n success: false,\r\n errorCode: 0,\r\n errorMessage: statusMsg,\r\n statusCode: response.status,\r\n };\r\n }\r\n // Try parsing as JSON anyway (some servers don't set content-type)\r\n try {\r\n responseBody = JSON.parse(text) as Record<string, unknown>;\r\n } catch {\r\n return {\r\n success: false,\r\n errorCode: 0,\r\n errorMessage: `Unexpected response from server (${response.status})`,\r\n statusCode: response.status,\r\n };\r\n }\r\n }\r\n\r\n // Server uses unified format: { code: \"0000\", message: \"...\", data: {...} }\r\n const code = responseBody.code as string | undefined;\r\n const message = responseBody.message as string | undefined;\r\n\r\n // Success: HTTP 2xx AND code is \"0000\" (or no code field for raw responses)\r\n if (response.ok && (!code || code === '0000')) {\r\n // If the server wraps the payload in a \"data\" field, unwrap it —\r\n // including when `data` is explicitly null (a valid empty payload,\r\n // e.g. GET /accounts for a developer without a settlement account).\r\n // We must distinguish \"no data field\" (raw response → use the whole\r\n // body) from \"data field present but null\" (→ return null), since\r\n // `data ?? responseBody` would wrongly fall back to the envelope and\r\n // surface { code, message, data: null } as the payload.\r\n const hasDataField = Object.prototype.hasOwnProperty.call(responseBody, 'data');\r\n const payload = hasDataField ? responseBody.data : responseBody;\r\n return { success: true, data: payload as T, message };\r\n }\r\n\r\n // Error: either HTTP non-2xx or code !== \"0000\"\r\n const errorCode = code ? parseInt(code, 10) : 0;\r\n // Handle FastAPI 422 validation errors where detail is an array\r\n let errorMsg = message ?? response.statusText;\r\n if (!errorMsg || errorMsg === response.statusText) {\r\n const detail = responseBody.detail;\r\n if (Array.isArray(detail)) {\r\n errorMsg = detail.map((d: Record<string, unknown>) => {\r\n const loc = (d.loc as string[])?.slice(1).join('.') ?? '';\r\n return loc ? `${loc}: ${d.msg}` : String(d.msg);\r\n }).join('; ');\r\n } else if (typeof detail === 'string') {\r\n errorMsg = detail;\r\n }\r\n }\r\n\r\n // Prefer string error_code (CLI D3 routing) over numeric code string\r\n const errorCodeStr = responseBody.error_code as string | undefined;\r\n\r\n // Preserve object-shaped error data for recoverable operations and extract\r\n // provider diagnostics from the same safe structure.\r\n const dataValue = responseBody.data;\r\n const rawData = dataValue && typeof dataValue === 'object' && !Array.isArray(dataValue)\r\n ? dataValue as Record<string, unknown>\r\n : undefined;\r\n const upstream = (rawData?.upstream && typeof rawData.upstream === 'object')\r\n ? rawData.upstream as UpstreamError\r\n : undefined;\r\n\r\n return {\r\n success: false,\r\n errorCode: isNaN(errorCode) ? 0 : errorCode,\r\n errorMessage: errorMsg,\r\n statusCode: response.status,\r\n ...(errorCodeStr ? { code: errorCodeStr } : (typeof code === 'string' && code ? { code } : {})),\r\n requestId: (responseBody.request_id ?? responseBody.requestId) as string | undefined,\r\n ...(rawData ? { data: rawData } : {}),\r\n ...(upstream ? { upstream } : {}),\r\n };\r\n } catch (error) {\r\n // UpgradeRequiredError is a CliError and must propagate untouched to the\r\n // top-level handler; don't rewrap it as a NetworkError.\r\n if (error instanceof UpgradeRequiredError) {\r\n throw error;\r\n }\r\n if (error instanceof DOMException && error.name === 'AbortError') {\r\n throw new NetworkError(url, this.timeout);\r\n }\r\n throw new NetworkError(url, undefined, error instanceof Error ? error : undefined);\r\n } finally {\r\n clearTimeout(timeoutId);\r\n }\r\n }\r\n\r\n /**\r\n * Validate that the running CLI meets the server-advertised minimum.\r\n * Missing or empty header → skip (backward compat with servers that don't\r\n * advertise yet, and clients hitting legacy proxies).\r\n */\r\n private enforceMinVersion(headerValue: string | null): void {\r\n const minVersion = headerValue?.trim();\r\n if (!minVersion) return;\r\n const current = getCurrentVersion();\r\n if (isBelow(current, minVersion)) {\r\n throw new UpgradeRequiredError(current, minVersion, UPGRADE_COMMAND);\r\n }\r\n }\r\n\r\n private friendlyStatusMessage(status: number): string {\r\n const messages: Record<number, string> = {\r\n 400: 'Invalid request. Please check your input.',\r\n 401: 'Authentication failed. Please check your API key or login again.',\r\n 403: 'Access denied. You do not have permission for this operation.',\r\n 404: 'Resource not found. Please check the ID.',\r\n 409: 'Conflict. This resource may already exist.',\r\n 422: 'Invalid input. Please check the request parameters.',\r\n 429: 'Too many requests. Please wait and try again.',\r\n 500: 'Something went wrong on the server. Please try again later.',\r\n 502: 'Service is temporarily unavailable. Please try again in a moment.',\r\n 503: 'Service is temporarily unavailable. Please try again in a moment.',\r\n 504: 'The request took too long. Please try again.',\r\n };\r\n return messages[status] ?? `Something went wrong (${status}). Please try again later.`;\r\n }\r\n}\r\n","import { readFile, writeFile, readdir, unlink, access, mkdir, chmod } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\nimport { OrgCredential } from '../types/config.js';\r\n\r\nexport class CredentialStore {\r\n private readonly basePath: string;\r\n\r\n constructor(basePath?: string) {\r\n this.basePath = basePath ?? join(homedir(), '.agenzo-admin-cli', 'credentials');\r\n }\r\n\r\n private filePath(orgId: string): string {\r\n return join(this.basePath, `${orgId}.json`);\r\n }\r\n\r\n private async ensureDir(): Promise<void> {\r\n // Credentials hold long-lived Bearer tokens — dir must be owner-only (0700).\r\n // mkdir mode is subject to umask, so chmod afterwards to enforce it on\r\n // both freshly created and pre-existing directories.\r\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\r\n await chmod(this.basePath, 0o700);\r\n }\r\n\r\n async get(orgId: string): Promise<OrgCredential | null> {\r\n try {\r\n const content = await readFile(this.filePath(orgId), 'utf-8');\r\n return JSON.parse(content) as OrgCredential;\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async save(credential: OrgCredential): Promise<void> {\r\n await this.ensureDir();\r\n const path = this.filePath(credential.org_id);\r\n // Owner read/write only (0600); chmod after write so pre-existing files\r\n // created before this safeguard also get tightened.\r\n await writeFile(path, JSON.stringify(credential, null, 2), {\r\n encoding: 'utf-8',\r\n mode: 0o600,\r\n });\r\n await chmod(path, 0o600);\r\n }\r\n\r\n async delete(orgId: string): Promise<void> {\r\n try {\r\n await unlink(this.filePath(orgId));\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return;\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async listAll(): Promise<OrgCredential[]> {\r\n try {\r\n const files = await readdir(this.basePath);\r\n const jsonFiles = files.filter((f) => f.endsWith('.json'));\r\n const credentials: OrgCredential[] = [];\r\n for (const file of jsonFiles) {\r\n try {\r\n const content = await readFile(join(this.basePath, file), 'utf-8');\r\n credentials.push(JSON.parse(content) as OrgCredential);\r\n } catch {\r\n // Skip corrupted files\r\n }\r\n }\r\n return credentials;\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return [];\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async exists(orgId: string): Promise<boolean> {\r\n try {\r\n await access(this.filePath(orgId));\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n}\r\n","import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\r\nimport { dirname, join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\nimport { StoredApiKey } from '../types/config.js';\r\n\r\nexport class KeyStore {\r\n private readonly basePath: string;\r\n\r\n constructor(basePath?: string) {\r\n // API keys are shared across runtime-plane CLIs (token/merchant/payment).\r\n // Stored under the legacy path for backward compatibility; will migrate to\r\n // ~/.agenzo/keys/ in a future release.\r\n this.basePath = basePath ?? join(homedir(), '.agenzo-token-cli', 'api-keys');\r\n }\r\n\r\n private filePath(orgId: string): string {\r\n return join(this.basePath, `${orgId}.json`);\r\n }\r\n\r\n private async loadData(orgId: string): Promise<StoredApiKey[]> {\r\n try {\r\n const content = await readFile(this.filePath(orgId), 'utf-8');\r\n return JSON.parse(content) as StoredApiKey[];\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return [];\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n private async saveData(orgId: string, data: StoredApiKey[]): Promise<void> {\r\n // Stored API keys are plaintext secrets — dir 0700, file 0600.\r\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\r\n await chmod(this.basePath, 0o700);\r\n const path = this.filePath(orgId);\r\n await writeFile(path, JSON.stringify(data, null, 2), {\r\n encoding: 'utf-8',\r\n mode: 0o600,\r\n });\r\n await chmod(path, 0o600);\r\n }\r\n\r\n async add(orgId: string, key: StoredApiKey): Promise<void> {\r\n const data = await this.loadData(orgId);\r\n data.push(key);\r\n await this.saveData(orgId, data);\r\n }\r\n\r\n async update(orgId: string, keyId: string, newKeyValue: string): Promise<void> {\r\n const data = await this.loadData(orgId);\r\n const key = data.find((k) => k.key_id === keyId);\r\n if (key) {\r\n key.key_value = newKeyValue;\r\n await this.saveData(orgId, data);\r\n }\r\n }\r\n\r\n async list(orgId: string): Promise<StoredApiKey[]> {\r\n return this.loadData(orgId);\r\n }\r\n\r\n async get(orgId: string, keyId: string): Promise<StoredApiKey | null> {\r\n const data = await this.loadData(orgId);\r\n return data.find((k) => k.key_id === keyId) ?? null;\r\n }\r\n}\r\n","import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\nimport { AppConfig } from '../types/config.js';\r\nimport { ConfigError, ValidationError } from '../errors/errors.js';\r\n\r\n// §6 target routing: each product line is served under its own prefix\r\n// (/api/{line}/v1). The prefix is a per-binary constant injected into\r\n// ConfigManager (see constructor `apiPath`), NOT a single shared value — the\r\n// four CLIs hit different product lines under one shared api_host.\r\n// This default is the admin control-plane prefix; other CLIs override it.\r\nconst DEFAULT_API_PATH = '/api/admin/v1';\r\n\r\nconst DEFAULT_CONFIG: AppConfig = {\r\n active_org: null,\r\n active_developer_id: null,\r\n api_host: 'https://agent.agenzo.com',\r\n api_path: DEFAULT_API_PATH,\r\n};\r\n\r\nexport const BUILTIN_PROFILES: Record<string, string> = {\r\n production: 'https://agent.agenzo.com',\r\n testing: 'https://agent-dev.agenzo.com',\r\n};\r\n\r\n/**\r\n * Resolve a user-supplied host argument (a built-in profile name or an\r\n * explicit URL) to the concrete API host URL that gets persisted.\r\n * Pure (no I/O) so callers can compute the resolved value before/without a\r\n * config write — e.g. `config set-host` needs it to match stored credentials\r\n * by their resolved `api_host` rather than the raw profile name.\r\n * Throws `ValidationError` for unknown profiles / malformed URLs.\r\n */\r\nexport function resolveApiHost(host: string): string {\r\n if (BUILTIN_PROFILES[host]) {\r\n return BUILTIN_PROFILES[host];\r\n }\r\n\r\n let url: URL;\r\n try {\r\n url = new URL(host);\r\n } catch {\r\n throw new ValidationError(`Unknown profile or invalid URL: ${host}`);\r\n }\r\n\r\n if (url.protocol === 'https:') {\r\n return host;\r\n }\r\n\r\n if (\r\n url.protocol === 'http:'\r\n && (url.hostname === 'localhost' || url.hostname === '127.0.0.1')\r\n ) {\r\n return host;\r\n }\r\n\r\n // Allow HTTP for Docker internal container-to-container traffic (gated by env var)\r\n if (url.protocol === 'http:' && process.env.AGENZO_ALLOW_INSECURE_HOST === '1') {\r\n return host;\r\n }\r\n\r\n throw new ValidationError(\r\n `Insecure API host is not allowed: ${host}. Use HTTPS, except for localhost or 127.0.0.1.`,\r\n );\r\n}\r\n\r\nexport class ConfigManager {\r\n private readonly basePath: string;\r\n private readonly configPath: string;\r\n /**\r\n * Product-line API prefix this CLI targets (e.g. /api/admin/v1,\r\n * /api/token/v1). Injected per binary so the four CLIs share one api_host\r\n * but route to different product lines. Overrides any persisted api_path.\r\n */\r\n private readonly apiPath: string;\r\n\r\n constructor(basePath?: string, apiPath?: string) {\r\n this.basePath = basePath ?? join(homedir(), '.agenzo-admin-cli');\r\n this.configPath = join(this.basePath, 'config.json');\r\n this.apiPath = apiPath ?? DEFAULT_API_PATH;\r\n }\r\n\r\n /** The resolved product-line API prefix for this CLI (per-binary constant). */\r\n getApiPath(): string {\r\n return this.apiPath;\r\n }\r\n\r\n async ensureDirectories(): Promise<void> {\r\n // Base dir contains the credentials/ subtree → owner-only (0700).\r\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\r\n await chmod(this.basePath, 0o700);\r\n const credDir = join(this.basePath, 'credentials');\r\n await mkdir(credDir, { recursive: true, mode: 0o700 });\r\n await chmod(credDir, 0o700);\r\n }\r\n\r\n async load(): Promise<AppConfig> {\r\n try {\r\n const content = await readFile(this.configPath, 'utf-8');\r\n try {\r\n const raw = JSON.parse(content) as Record<string, unknown>;\r\n // Migrate old api_base_url format\r\n if (raw.api_base_url && !raw.api_host) {\r\n const url = String(raw.api_base_url);\r\n const pathIndex = url.indexOf('/api/');\r\n raw.api_host = pathIndex > 0 ? url.slice(0, pathIndex) : url;\r\n raw.api_path = pathIndex > 0 ? url.slice(pathIndex) : DEFAULT_CONFIG.api_path;\r\n delete raw.api_base_url;\r\n }\r\n return {\r\n active_org: (raw.active_org as string) ?? null,\r\n active_developer_id: (raw.active_developer_id as string) ?? null,\r\n api_host: (raw.api_host as string) ?? DEFAULT_CONFIG.api_host,\r\n api_path: (raw.api_path as string) ?? DEFAULT_CONFIG.api_path,\r\n };\r\n } catch {\r\n throw new ConfigError(\r\n `Invalid config file: ${this.configPath}`,\r\n this.configPath,\r\n );\r\n }\r\n } catch (error) {\r\n if (error instanceof ConfigError) throw error;\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return { ...DEFAULT_CONFIG };\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async save(config: AppConfig): Promise<void> {\r\n await this.ensureDirectories();\r\n await writeFile(this.configPath, JSON.stringify(config, null, 2), {\r\n encoding: 'utf-8',\r\n mode: 0o600,\r\n });\r\n await chmod(this.configPath, 0o600);\r\n }\r\n\r\n async getActiveOrg(): Promise<string | null> {\r\n const config = await this.load();\r\n return config.active_org;\r\n }\r\n\r\n async setActiveOrg(orgId: string): Promise<void> {\r\n const config = await this.load();\r\n config.active_org = orgId;\r\n await this.save(config);\r\n }\r\n\r\n async getApiBaseUrl(): Promise<string> {\r\n const config = await this.load();\r\n const host = resolveApiHost(config.api_host).replace(/\\/+$/, '');\r\n // Use the per-binary product-line prefix, not the persisted api_path —\r\n // the latter is shared across all CLIs and would route every binary to the\r\n // same product line. The injected prefix overrides any stale stored value.\r\n const path = this.apiPath.startsWith('/') ? this.apiPath : `/${this.apiPath}`;\r\n return `${host}${path}`;\r\n }\r\n\r\n async setApiHost(host: string): Promise<void> {\r\n const config = await this.load();\r\n config.api_host = resolveApiHost(host);\r\n await this.save(config);\r\n }\r\n\r\n async getApiHost(): Promise<string> {\r\n const config = await this.load();\r\n return resolveApiHost(config.api_host);\r\n }\r\n}\r\n","import { CliError } from '../errors/errors.js';\r\n\r\n/**\r\n * Exit-code mapper (cli-design §8.6 / cli-standard §5.4).\r\n *\r\n * Maps any thrown error reaching the top-level handler to one of the CLI's\r\n * non-zero exit codes. Normal completion implies `0` and never consults this.\r\n *\r\n * 1 — business / param: PARAM_* / RESOURCE_* / BILLING_* / ACCOUNT_* /\r\n * PAYMENT_ORDER_* / TOKEN_* / SERVICE_* / ride codes / CLIENT_* /\r\n * NOT_IMPLEMENTED, and unknown errors\r\n * 2 — upgrade required: UPGRADE_REQUIRED\r\n * 3 — auth-fail / invalid-key: AUTH_* / KEY_*\r\n * 4 — network / 5xx: UPSTREAM_ERROR / INTERNAL_ERROR / RATE_LIMITED\r\n * 5 — user-cancel: CLIENT_ABORTED\r\n */\r\nexport function exitCodeFor(error: unknown): 1 | 2 | 3 | 4 | 5 {\r\n if (!(error instanceof CliError)) {\r\n return 1;\r\n }\r\n\r\n const code = error.code;\r\n\r\n if (code === 'UPGRADE_REQUIRED') {\r\n return 2;\r\n }\r\n\r\n if (code === 'CLIENT_ABORTED') {\r\n return 5;\r\n }\r\n\r\n if (code.startsWith('AUTH_') || code.startsWith('KEY_')) {\r\n return 3;\r\n }\r\n\r\n if (\r\n code === 'UPSTREAM_ERROR' ||\r\n code === 'INTERNAL_ERROR' ||\r\n code === 'RATE_LIMITED'\r\n ) {\r\n return 4;\r\n }\r\n\r\n return 1;\r\n}\r\n","export type StatusPrefix = 'success' | 'error' | 'info' | 'warning' | 'loading';\r\n\r\nconst STATUS_ICONS: Record<StatusPrefix, string> = {\r\n success: '✓',\r\n error: '✗',\r\n info: 'ℹ',\r\n warning: '⚠',\r\n loading: '⠋',\r\n};\r\n\r\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\r\n\r\nexport interface Spinner {\r\n /** Update the spinner message while it's running */\r\n update(message: string): void;\r\n /** Stop the spinner and show a final status line */\r\n stop(type?: StatusPrefix, finalMessage?: string): void;\r\n}\r\n\r\n/**\r\n * Creates an animated terminal spinner that cycles through braille frames.\r\n * Call `spinner.stop()` when the async work is done.\r\n */\r\nexport function createSpinner(message: string, intervalMs = 60): Spinner {\r\n let frameIdx = 0;\r\n let currentMessage = message;\r\n\r\n const render = () => {\r\n process.stdout.write(`\\r\\x1b[K${SPINNER_FRAMES[frameIdx]} ${currentMessage}`);\r\n frameIdx = (frameIdx + 1) % SPINNER_FRAMES.length;\r\n };\r\n\r\n render();\r\n const timer = setInterval(render, intervalMs);\r\n\r\n return {\r\n update(msg: string) {\r\n currentMessage = msg;\r\n },\r\n stop(type?: StatusPrefix, finalMessage?: string) {\r\n clearInterval(timer);\r\n process.stdout.write('\\r\\x1b[K');\r\n if (type && finalMessage) {\r\n console.log(Formatter.status(type, finalMessage));\r\n }\r\n },\r\n };\r\n}\r\n\r\nexport class Formatter {\r\n /** Get display width of a string (CJK characters count as 2) */\r\n private static displayWidth(str: string): number {\r\n let width = 0;\r\n for (const char of str) {\r\n const code = char.codePointAt(0)!;\r\n // CJK Unified Ideographs and common fullwidth ranges\r\n if (\r\n (code >= 0x4e00 && code <= 0x9fff) || // CJK Unified\r\n (code >= 0x3000 && code <= 0x303f) || // CJK Punctuation\r\n (code >= 0x3400 && code <= 0x4dbf) || // CJK Extension A\r\n (code >= 0xff00 && code <= 0xffef) || // Fullwidth Forms\r\n (code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility\r\n (code >= 0x20000 && code <= 0x2a6df) // CJK Extension B\r\n ) {\r\n width += 2;\r\n } else {\r\n width += 1;\r\n }\r\n }\r\n return width;\r\n }\r\n\r\n /** Pad string to target display width (right-pad with spaces) */\r\n private static padEndDisplay(str: string, targetWidth: number): string {\r\n const currentWidth = Formatter.displayWidth(str);\r\n const padding = Math.max(0, targetWidth - currentWidth);\r\n return str + ' '.repeat(padding);\r\n }\r\n\r\n /** Pad string to target display width (left-pad with spaces) */\r\n private static padStartDisplay(str: string, targetWidth: number): string {\r\n const currentWidth = Formatter.displayWidth(str);\r\n const padding = Math.max(0, targetWidth - currentWidth);\r\n return ' '.repeat(padding) + str;\r\n }\r\n\r\n /** Table output for list commands — columns aligned by max width */\r\n static table(headers: string[], rows: string[][]): string {\r\n const colWidths = headers.map((h, i) => {\r\n const cellWidths = rows.map((r) => Formatter.displayWidth(r[i] ?? ''));\r\n return Math.max(Formatter.displayWidth(h), ...cellWidths);\r\n });\r\n\r\n const sep = ' ';\r\n\r\n const headerLine = headers.map((h, i) => Formatter.padEndDisplay(h, colWidths[i])).join(sep);\r\n const divider = colWidths.map((w) => '-'.repeat(w)).join(sep);\r\n const dataLines = rows.map((row) =>\r\n row.map((cell, i) => Formatter.padEndDisplay(cell ?? '', colWidths[i])).join(sep),\r\n );\r\n\r\n return [headerLine, divider, ...dataLines].join('\\n');\r\n }\r\n\r\n /** Key-value output for detail commands — keys left-aligned */\r\n static keyValue(entries: [string, string][]): string {\r\n const maxKeyWidth = Math.max(...entries.map(([k]) => Formatter.displayWidth(k)));\r\n return entries\r\n .map(([key, value]) => `${Formatter.padEndDisplay(key, maxKeyWidth)} ${value}`)\r\n .join('\\n');\r\n }\r\n\r\n /** Status-prefixed message */\r\n static status(type: StatusPrefix, message: string): string {\r\n return `${STATUS_ICONS[type]} ${message}`;\r\n }\r\n\r\n /** Mask sensitive info, keeping only the prefix */\r\n static maskKey(key: string, prefixLength = 8): string {\r\n if (key.length <= prefixLength) {\r\n return key;\r\n }\r\n return key.slice(0, prefixLength) + '*'.repeat(key.length - prefixLength);\r\n }\r\n\r\n /**\r\n * Format ISO 8601 timestamp to local timezone display.\r\n * Automatically uses the user's system timezone.\r\n * e.g. \"2026-05-07T03:24:53+00:00\" → \"2026-05-07 11:24:53\" (in CST)\r\n * \"2026-05-07T03:24:53+00:00\" → \"2026-05-06 20:24:53\" (in PDT)\r\n * Returns the original string if parsing fails or input is empty.\r\n */\r\n static formatTime(iso: string | null | undefined): string {\r\n if (!iso) return '';\r\n const date = new Date(iso);\r\n if (isNaN(date.getTime())) return iso;\r\n const pad = (n: number) => String(n).padStart(2, '0');\r\n const y = date.getFullYear();\r\n const m = pad(date.getMonth() + 1);\r\n const d = pad(date.getDate());\r\n const h = pad(date.getHours());\r\n const min = pad(date.getMinutes());\r\n const s = pad(date.getSeconds());\r\n const offsetMin = -date.getTimezoneOffset();\r\n const sign = offsetMin >= 0 ? '+' : '-';\r\n const absOffset = Math.abs(offsetMin);\r\n const tzH = pad(Math.floor(absOffset / 60));\r\n const tzM = pad(absOffset % 60);\r\n return `${y}-${m}-${d} ${h}:${min}:${s} (UTC${sign}${tzH}:${tzM})`;\r\n }\r\n}\r\n","import type { CommandResult } from '../types/commands.js';\r\nimport { Formatter, type StatusPrefix } from './formatter.js';\r\n\r\n/**\r\n * Central output renderer.\r\n *\r\n * Single choke point that turns a {@link CommandResult} into stdout bytes,\r\n * switching between machine-readable JSON and a human-readable table view.\r\n * This is what lets command handlers stop calling `console.log` directly:\r\n * they build a `CommandResult` and hand it here.\r\n *\r\n * Contract (cli-standard §5.1/§5.2):\r\n * - stdout carries ONLY the business payload — a single JSON value\r\n * (`--format json`) or human-readable text (`--format table`).\r\n * - logs, spinners, prompts, hints and progress lines belong on stderr and\r\n * are NEVER written here.\r\n *\r\n * Recorded deviation from cli-standard §5.1: the default format is `table`\r\n * (not `json`), and the flag values are `json | table` (not `json | text`).\r\n */\r\n\r\n/** The two supported output formats. */\r\nexport type OutputFormat = 'json' | 'table';\r\n\r\n/** Options consumed by {@link render}. */\r\nexport interface RenderOptions {\r\n format: OutputFormat;\r\n}\r\n\r\n/** The default format used when nothing valid is supplied (deliberate deviation: `table`). */\r\nconst DEFAULT_FORMAT: OutputFormat = 'table';\r\n\r\n/** Narrow an arbitrary string to a known {@link OutputFormat}. */\r\nfunction isOutputFormat(value: string): value is OutputFormat {\r\n return value === 'json' || value === 'table';\r\n}\r\n\r\n/**\r\n * Resolve the active output format.\r\n *\r\n * Precedence: `--format` flag > `AGENZO_FORMAT` env var > default `table`.\r\n * Any invalid value falls back to the default. The result is always one of\r\n * `'json' | 'table'`.\r\n *\r\n * The `--format` flag is authoritative when provided: a provided-but-invalid\r\n * flag falls back to the default rather than deferring to the environment.\r\n */\r\nexport function resolveFormat(\r\n flag?: string,\r\n env: string | undefined = process.env.AGENZO_FORMAT,\r\n): OutputFormat {\r\n // 1. --format flag is authoritative when provided.\r\n if (flag !== undefined) {\r\n return isOutputFormat(flag) ? flag : DEFAULT_FORMAT;\r\n }\r\n // 2. AGENZO_FORMAT environment value, when set to a valid format.\r\n if (env !== undefined && isOutputFormat(env)) {\r\n return env;\r\n }\r\n // 3. Default.\r\n return DEFAULT_FORMAT;\r\n}\r\n\r\n/**\r\n * Emit a successful command result to stdout in the chosen format.\r\n *\r\n * - `json`: writes `JSON.stringify(result.data, null, 2)` (the machine payload\r\n * only — never the text-mode chrome).\r\n * - `table`: writes the lazy human presenter `result.text()`.\r\n *\r\n * Only the payload reaches stdout; status/progress lines must go to stderr by\r\n * the caller. A trailing newline is appended so the output pipes cleanly into\r\n * tools like `jq`.\r\n */\r\nexport function render<T>(result: CommandResult<T>, opts: RenderOptions): void {\r\n if (opts.format === 'json') {\r\n process.stdout.write(`${JSON.stringify(result.data, null, 2)}\\n`);\r\n return;\r\n }\r\n process.stdout.write(`${result.text()}\\n`);\r\n}\r\n\r\n/**\r\n * Emit a human-facing status line (✓ / ℹ / ⚠) to stderr — but ONLY in `table`\r\n * mode. In `json` mode the output is consumed by other agents/scripts, so any\r\n * decorative status text (even on stderr) is noise that can confuse parsing;\r\n * `json` mode therefore stays completely silent here. Errors are NOT routed\r\n * through this helper — they are owned by the top-level handler in index.ts.\r\n *\r\n * This is the single choke point for command success/progress notices, so the\r\n * `json`-silence rule is enforced in one place rather than scattered across\r\n * every handler.\r\n */\r\nexport function notify(\r\n format: OutputFormat,\r\n type: StatusPrefix,\r\n message: string,\r\n): void {\r\n if (format === 'json') {\r\n return;\r\n }\r\n console.error(Formatter.status(type, message));\r\n}\r\n","/**\r\n * Shared JSON envelope renderer (cli-design §7.7.2 BACK-011).\r\n *\r\n * In `--format json` mode, every command's payload is prefixed with two\r\n * client-assembled context fields:\r\n * - `profile`: the active environment name (production / testing / custom),\r\n * derived by reverse-looking-up the api_host in BUILTIN_PROFILES.\r\n * - `endpoint`: the api **host only** (e.g. https://agent.agenzo.com) —\r\n * NEVER the internal API path (/api/admin/v1), so internal\r\n * routing is not leaked to agent consumers.\r\n *\r\n * `result.data` is expected to be an object (single-resource payloads are flat\r\n * field maps; list payloads are `{ <namedKey>: [...], page: {...} }`). The two\r\n * context fields are spread in front of it.\r\n *\r\n * In `--format table` mode this is a passthrough to the standard `render`.\r\n *\r\n * This lives in `@agenzo/cli-core` (BACK-011) so every CLI shares one\r\n * implementation rather than copying it per app.\r\n */\r\nimport type { CommandResult } from '../types/commands.js';\r\nimport { type RenderOptions, render } from './output.js';\r\nimport { ConfigManager, BUILTIN_PROFILES } from '../config/config-manager.js';\r\n\r\nexport async function renderWithContext<T>(\r\n result: CommandResult<T>,\r\n opts: RenderOptions,\r\n configManager: ConfigManager,\r\n): Promise<void> {\r\n if (opts.format !== 'json') {\r\n render(result, opts);\r\n return;\r\n }\r\n\r\n const config = await configManager.load();\r\n const host = config.api_host.replace(/\\/+$/, '');\r\n const profile =\r\n Object.entries(BUILTIN_PROFILES).find(([, v]) => v === host)?.[0] ?? 'custom';\r\n\r\n const dataObj =\r\n result.data && typeof result.data === 'object'\r\n ? (result.data as Record<string, unknown>)\r\n : { value: result.data };\r\n\r\n const payload = {\r\n profile,\r\n endpoint: host,\r\n ...dataObj,\r\n };\r\n\r\n render({ ...result, data: payload } as CommandResult<typeof payload>, opts);\r\n}\r\n","import { input, password, select } from '@inquirer/prompts';\r\n\r\ninterface PromptConfig {\r\n message: string;\r\n type?: 'input' | 'password' | 'select';\r\n choices?: { name: string; value: string }[];\r\n validate?: (input: string) => boolean | string;\r\n}\r\n\r\nexport class PromptEngine {\r\n /** Return flagValue directly if provided, otherwise prompt interactively */\r\n static async resolveInput(\r\n flagValue: string | undefined,\r\n config: PromptConfig,\r\n ): Promise<string> {\r\n if (flagValue !== undefined) {\r\n return flagValue;\r\n }\r\n\r\n if (config.type === 'password') {\r\n return password({ message: config.message, mask: '*' });\r\n }\r\n\r\n if (config.type === 'select' && config.choices) {\r\n return select({\r\n message: config.message,\r\n choices: config.choices,\r\n });\r\n }\r\n\r\n return input({\r\n message: config.message,\r\n validate: config.validate,\r\n });\r\n }\r\n}\r\n","/**\r\n * Shared `--member <id>` attribution flag (order write + list verbs).\r\n *\r\n * `member_id` is an OPTIONAL, caller-supplied end-user label. The platform\r\n * stores it and filters by it; it is never registered, validated for existence\r\n * or used as an ownership boundary (ownership stays `developer_id` +\r\n * `organization_id`, both derived server-side from the API Key). See\r\n * `doc/member-id-attribution-design.md`.\r\n *\r\n * Why one module: the same description, the same trimming rule and the same\r\n * `source: 'session'` schema entry are needed by 7 verbs across 4 nouns. Keeping\r\n * them here means the attribution semantics are stated once.\r\n *\r\n * `source: 'session'` marks the flag as supplied by the EXECUTION layer (the\r\n * orchestrator injects the authenticated end-user id), so it is hidden from the\r\n * LLM tool schema — an agent must not be able to choose whose orders it writes\r\n * or reads.\r\n */\r\nimport type { Command } from 'commander';\r\nimport type { FlagSchema } from './verb-schema.js';\r\n\r\n/** Option description — identical wording on every verb that accepts it. */\r\nexport const MEMBER_OPTION_DESCRIPTION =\r\n 'End-user member id this order is attributed to (optional, max 128 chars). '\r\n + 'On write it is stored on the order; on list it filters to that member only '\r\n + '(orders without a member_id are excluded).';\r\n\r\n/** Verb-schema entry for the `member` flag. Hidden from LLM tool schemas. */\r\nexport const MEMBER_FLAG_SCHEMA: FlagSchema = {\r\n type: 'string',\r\n required: false,\r\n source: 'session',\r\n description: MEMBER_OPTION_DESCRIPTION,\r\n constraints: '1-128 characters; any character set. Omit to keep the order unattributed.',\r\n};\r\n\r\n/** Register `--member <id>` on a command. */\r\nexport function attachMemberOption(cmd: Command): Command {\r\n return cmd.option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n}\r\n\r\n/**\r\n * Read `--member` from parsed options, trimmed. Returns `undefined` when absent\r\n * or blank so callers omit the field entirely rather than sending `\"\"` (the\r\n * platform rejects an empty/blank `member_id` with 422 — a caller that meant to\r\n * attribute an order must not silently get an unattributed one).\r\n */\r\nexport function memberIdOf(opts: Record<string, unknown>): string | undefined {\r\n const raw = opts.member;\r\n if (typeof raw !== 'string') return undefined;\r\n const trimmed = raw.trim();\r\n return trimmed.length > 0 ? trimmed : undefined;\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError } from '@agenzo/cli-core';\r\nimport type { FlagSchema } from './verb-schema';\r\n\r\n/**\r\n * 价格批注(原价 / 优惠金额)—— 四个结算入口共用的 flag 声明、注册与 body 透传。\r\n *\r\n * 语义(与 platform `app/core/price_annotation.py` 同源):**纯记录字段**。平台把它落在\r\n * 自己的 MongoDB(统一流水 `ap_upi_transactions` + 订单 `auth_snapshot`)并在响应 /\r\n * 订单详情里回显,但**绝不**发给收单网关(evo-cli / EVO HTTP 直连都看不到),也**绝不**\r\n * 参与扣款金额的推导或「实扣额 == 锁单权威价」那道核验 —— 结算金额仍只取订单锁单落库的\r\n * 权威价与令牌铸造时冻结的金额。\r\n *\r\n * 收敛到一处的理由:这两个 flag 要同时出现在 `hotel-redaug pay-order`、\r\n * `flight-flink pay-order`、`flight-flink change-pay`、`ride-elife pay-order` 上。四处各写\r\n * 一遍描述与解析,必然漂移成四种说法(`payment-token-id` 的描述已经踩过这个坑)。\r\n */\r\n\r\nconst ORIGINAL_DESCRIPTION =\r\n 'Original (pre-discount) price in integer cents. Optional, RECORD-ONLY: stored on our own ' +\r\n 'order / charge record and echoed back in the order detail, never sent to the acquiring ' +\r\n 'gateway and never used to derive or validate the amount charged (that always comes from the ' +\r\n \"order's locked authoritative price).\";\r\n\r\nconst DISCOUNT_DESCRIPTION =\r\n 'Discount amount in integer cents. Optional, RECORD-ONLY: same semantics as ' +\r\n '--original-amount-cents.';\r\n\r\n/** `verb-schema.ts` 用的 flag 声明片段(展开进各 verb 的 `flags`)。 */\r\nexport const PRICE_ANNOTATION_FLAGS: Record<string, FlagSchema> = {\r\n 'original-amount-cents': {\r\n type: 'int',\r\n required: false,\r\n description: ORIGINAL_DESCRIPTION,\r\n constraints: 'non-negative integer cents',\r\n },\r\n 'discount-amount-cents': {\r\n type: 'int',\r\n required: false,\r\n description: DISCOUNT_DESCRIPTION,\r\n constraints: 'non-negative integer cents',\r\n },\r\n};\r\n\r\n/** 给一个 commander 命令挂上两个 option(链式返回,便于接在既有 `.option()` 之后)。 */\r\nexport function withPriceAnnotationOptions(cmd: Command): Command {\r\n return cmd\r\n .option('--original-amount-cents <cents>', ORIGINAL_DESCRIPTION)\r\n .option('--discount-amount-cents <cents>', DISCOUNT_DESCRIPTION);\r\n}\r\n\r\n/**\r\n * 把批注写进请求 body(只在 flag 真的出现时写键)。\r\n *\r\n * 本地就把非整数 / 负数挡成 `PARAM_INVALID`,不让一个纯记录字段的格式错误变成 422 往返。\r\n * `0` 是合法取值(优惠 0 = 明确声明「这单没有优惠」),所以判据是 `< 0` 而非 `< 1`,\r\n * 且用 present 判断(`!== undefined`)而非真值判断 —— 真值判断会把 `0` 折叠成「没给」。\r\n */\r\nexport function applyPriceAnnotation(\r\n body: Record<string, unknown>,\r\n opts: Record<string, unknown>,\r\n): void {\r\n const mappings = [\r\n ['--original-amount-cents', 'originalAmountCents', 'original_amount_cents'],\r\n ['--discount-amount-cents', 'discountAmountCents', 'discount_amount_cents'],\r\n ] as const;\r\n\r\n for (const [flag, optKey, bodyKey] of mappings) {\r\n const raw = opts[optKey] as string | number | undefined;\r\n if (raw === undefined) continue;\r\n const cents = Number(raw);\r\n if (!Number.isInteger(cents) || cents < 0) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `Invalid ${flag} \"${raw}\". Expected a non-negative integer number of cents (e.g. 10000 for 100.00).`,\r\n );\r\n }\r\n body[bodyKey] = cents;\r\n }\r\n}\r\n","import type { ApiClient } from '@agenzo/cli-core';\r\nimport { CliError } from '@agenzo/cli-core';\r\nimport type { GetOrderResponse } from '../types/api.js';\r\n\r\n/**\r\n * NDJSON status-polling for `ride-elife get --watch` (§4.4.1.3 polling /\r\n * design Property 2). Merchant-domain logic — stays in the app per\r\n * requirement 4.4 (NOT pushed down to cli-core).\r\n *\r\n * The watch stream is a line stream: each poll result is written as ONE\r\n * independent, compact JSON line on stdout. It is deliberately NOT routed\r\n * through `renderWithContext`, so the profile/endpoint envelope is never\r\n * wrapped around the stream (an agent consumes it with a line reader).\r\n *\r\n * The polling engine is split from its I/O so it can be unit/PBT-tested with a\r\n * fake clock and shortened constants (task 6.5): `fetchStatus`, `writeLine`,\r\n * `sleep` and `now` are all injected.\r\n */\r\n\r\n/**\r\n * Terminal ride statuses (schema `polling.terminal_statuses`). Once the order\r\n * reaches one of these, `--watch` stops polling. CASE-SENSITIVE — must match\r\n * the server casing exactly.\r\n */\r\nexport const TERMINAL_STATUSES: ReadonlySet<string> = new Set([\r\n 'At destination',\r\n 'Cancelled',\r\n 'Rejected',\r\n 'Customer no show',\r\n 'Driver no show',\r\n]);\r\n\r\n/** Schema `polling.recommended_interval_seconds`. */\r\nexport const DEFAULT_WATCH_INTERVAL_SECONDS = 5;\r\n/** Safety cap so `--watch` can never poll forever. */\r\nexport const DEFAULT_WATCH_TIMEOUT_SECONDS = 600;\r\n\r\n/**\r\n * Pure terminal-state predicate (exported for direct unit/PBT testing). A\r\n * missing/undefined status is never terminal, so polling continues until a\r\n * known terminal status or the timeout.\r\n */\r\nexport function isTerminalStatus(status: string | undefined | null): boolean {\r\n return status !== undefined && status !== null && TERMINAL_STATUSES.has(status);\r\n}\r\n\r\n/** Read the case-sensitive `status` field off a poll result. */\r\nexport function statusOf(data: GetOrderResponse): string | undefined {\r\n const status = (data as { status?: unknown }).status;\r\n return typeof status === 'string' ? status : undefined;\r\n}\r\n\r\n/** The final NDJSON line emitted when polling gives up before a terminal status. */\r\nexport interface WatchTimeoutLine {\r\n watch_status: 'timeout';\r\n message: string;\r\n last_status: string | null;\r\n}\r\n\r\n/** I/O + clock seams the polling engine depends on (all injectable for tests). */\r\nexport interface WatchEngineDeps {\r\n /** Fetch one status snapshot (throws to abort the whole stream). */\r\n fetchStatus: () => Promise<GetOrderResponse>;\r\n /** Write one NDJSON record as a single compact line. */\r\n writeLine: (record: unknown) => void;\r\n /** Resolve after `ms` (real timer in prod; fake clock in tests). */\r\n sleep: (ms: number) => Promise<void>;\r\n /** Current epoch millis (real `Date.now` in prod; fake clock in tests). */\r\n now: () => number;\r\n}\r\n\r\n/** Interval / timeout budget for one watch run, in milliseconds. */\r\nexport interface WatchEngineOptions {\r\n intervalMs: number;\r\n timeoutMs: number;\r\n}\r\n\r\n/**\r\n * Poll `fetchStatus`, writing each result as an NDJSON line, until the order\r\n * reaches a terminal status or the timeout elapses. On timeout the FINAL line\r\n * is `{ watch_status: 'timeout', ... }` (requirement 3.2 / Property 2).\r\n *\r\n * Termination: every iteration either returns (terminal status) or, when the\r\n * next poll would land at/after the deadline, emits the timeout line and\r\n * returns. With a monotonically advancing clock (real time, or a fake clock\r\n * advanced by `sleep`) the deadline is always reached, so the loop is\r\n * guaranteed to terminate for any status sequence.\r\n */\r\nexport async function runWatch(\r\n deps: WatchEngineDeps,\r\n opts: WatchEngineOptions,\r\n): Promise<void> {\r\n const deadline = deps.now() + opts.timeoutMs;\r\n for (;;) {\r\n const data = await deps.fetchStatus();\r\n deps.writeLine(data);\r\n\r\n const status = statusOf(data);\r\n if (isTerminalStatus(status)) {\r\n return;\r\n }\r\n\r\n if (deps.now() + opts.intervalMs >= deadline) {\r\n const timeoutLine: WatchTimeoutLine = {\r\n watch_status: 'timeout',\r\n message: `Polling stopped after ${opts.timeoutMs / 1000}s without reaching a terminal status.`,\r\n last_status: status ?? null,\r\n };\r\n deps.writeLine(timeoutLine);\r\n return;\r\n }\r\n\r\n await deps.sleep(opts.intervalMs);\r\n }\r\n}\r\n\r\n/**\r\n * Parse a positive `--watch-*` seconds flag, falling back to a default when\r\n * absent or non-positive (mirrors the standalone reference behaviour). Returns\r\n * a value in SECONDS.\r\n */\r\nexport function resolveSeconds(value: string | undefined, fallback: number): number {\r\n if (value === undefined) return fallback;\r\n const n = Number(value);\r\n return Number.isFinite(n) && n > 0 ? n : fallback;\r\n}\r\n\r\n/** Real-timer sleep used by the production watch path. */\r\nexport const realSleep = (ms: number): Promise<void> =>\r\n new Promise((resolve) => setTimeout(resolve, ms));\r\n\r\n/** Compact single-line NDJSON writer used by the production watch path. */\r\nexport const ndjsonWriteLine = (record: unknown): void => {\r\n process.stdout.write(`${JSON.stringify(record)}\\n`);\r\n};\r\n\r\n/**\r\n * Production wiring for `ride-elife get --watch`: bind the polling engine to a\r\n * live `ApiClient` (status endpoint + api-key auth), the compact NDJSON stdout\r\n * writer, real timers and the system clock. A network/backend failure on any\r\n * poll surfaces as a `CliError` to the top-level handler, exactly like the\r\n * single-shot path.\r\n */\r\nexport async function watchRideStatus(\r\n apiClient: ApiClient,\r\n apiKey: string,\r\n orderId: string,\r\n opts: { intervalSeconds: number; timeoutSeconds: number },\r\n): Promise<void> {\r\n const path = `/ride/${encodeURIComponent(orderId)}/status`;\r\n await runWatch(\r\n {\r\n fetchStatus: async () => {\r\n const result = await apiClient.get<GetOrderResponse>(path, {\r\n type: 'api-key',\r\n key: apiKey,\r\n });\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n return result.data;\r\n },\r\n writeLine: ndjsonWriteLine,\r\n sleep: realSleep,\r\n now: () => Date.now(),\r\n },\r\n {\r\n intervalMs: opts.intervalSeconds * 1000,\r\n timeoutMs: opts.timeoutSeconds * 1000,\r\n },\r\n );\r\n}\r\n","/**\r\n * `--help --format json` verb-level schema (§4.4.1.3) — merchant domain only.\r\n *\r\n * Every ride-elife verb supports `--help --format json`, which prints a single\r\n * machine-readable JSON object describing the verb instead of commander's\r\n * default text help. This is the standard way an Agent discovers a verb's\r\n * flags, response shape, example invocation and (where relevant) error-recovery\r\n * and polling guidance locally, without a network round-trip.\r\n *\r\n * admin-cli / token-cli have no such mode, so this lives in the app (not in\r\n * cli-core) per requirement 4.4.\r\n *\r\n * Mechanism (commander v14): `attachSchemaHelp` overrides a command's\r\n * `helpInformation`. Commander resolves `--help` BEFORE later argv tokens are\r\n * applied to options, so the parsed `--format` value is not yet available when\r\n * help renders — we therefore read it straight from `process.argv`. Only an\r\n * explicit `--format json` switches to the JSON schema; bare `--help` and\r\n * `--help --format table` keep commander's default text help.\r\n */\r\nimport type { Command } from 'commander';\r\nimport { MEMBER_FLAG_SCHEMA } from './member.js';\r\nimport { PRICE_ANNOTATION_FLAGS } from './price-annotation.js';\r\nimport { TERMINAL_STATUSES, DEFAULT_WATCH_INTERVAL_SECONDS } from './ride-elife/watch.js';\r\n\r\nconst CLI_NAME = 'agenzo-merchant-cli';\r\nconst NOUN = 'ride-elife';\r\n/** Hotel noun (command group) — the `hotel-redaug/*` verbs share this. */\r\nexport const HOTEL_NOUN = 'hotel-redaug';\r\n/** Flight noun (command group) — the `flight-flink/*` verbs share this. */\r\nexport const FLIGHT_NOUN = 'flight-flink';\r\n\r\n// ============================================================\r\n// Schema shape (§4.4.1.3 verb-level schema)\r\n// ============================================================\r\n\r\n/** One flag descriptor: type / required / optional default / description / constraints. */\r\nexport interface FlagSchema {\r\n type: string;\r\n /** `true` / `false`, or the literal `'conditional'` for mode-dependent flags. */\r\n required: boolean | 'conditional';\r\n default?: unknown;\r\n description: string;\r\n constraints?: string;\r\n /**\r\n * Where the value comes from when a non-human agent drives the CLI.\r\n *\r\n * `'session'` — supplied by the execution layer from the authenticated\r\n * session (e.g. the orchestrator injects `--member` from the caller's JWT).\r\n * Consumers that build LLM tool schemas MUST hide such flags: letting a model\r\n * choose the value would let it act on another end-user's data.\r\n *\r\n * Omitted means the flag is ordinary agent/human input.\r\n */\r\n source?: 'session';\r\n}\r\n\r\n/** A complete, copy-pasteable example invocation plus what to read from the output. */\r\nexport interface ExampleSchema {\r\n command: string;\r\n output_summary: string;\r\n}\r\n\r\n/**\r\n * Polling guidance — status-query verbs (`get`, `get-checkout`) carry this block.\r\n *\r\n * `terminal_statuses` / `in_progress_statuses` are `Array<string | number>`\r\n * because hotel `get` keys off the INTEGER `order_status_code` set (`[3,4,5]` /\r\n * `[2]`), while ride `get` and hotel `get-checkout` use STRING statuses. The\r\n * widened element type keeps both valid in the same shared interface.\r\n */\r\nexport interface PollingSchema {\r\n recommended_interval_seconds: number;\r\n terminal_statuses: Array<string | number>;\r\n in_progress_statuses: Array<string | number>;\r\n field_availability?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * The verb-level schema object emitted by `--help --format json`\r\n * (§4.4.1.3): `{ cli, noun, verb, description, flags, response, example,\r\n * [error_recovery], [polling] }`. `error_recovery` / `polling` are optional and\r\n * present only where the verb warrants them.\r\n */\r\nexport interface VerbSchema {\r\n cli: string;\r\n noun: string;\r\n verb: string;\r\n description: string;\r\n flags: Record<string, FlagSchema>;\r\n /** Key response fields + type descriptions (nested objects allowed). */\r\n response: Record<string, unknown>;\r\n example: ExampleSchema;\r\n error_recovery?: Record<string, string>;\r\n polling?: PollingSchema;\r\n}\r\n\r\n// ============================================================\r\n// Emit + attach mechanism\r\n// ============================================================\r\n\r\n/**\r\n * True only when `--format json` is explicitly present in `argv`. Commander\r\n * resolves `--help` before applying later option tokens, so the parsed format\r\n * is not yet available at help-render time; we read argv directly. Bare `--help`\r\n * and `--help --format table` deliberately return false (keep text help), even\r\n * though the program defaults `--format` to json — the default is never written\r\n * into argv.\r\n */\r\nexport function wantsJsonSchema(argv: string[] = process.argv): boolean {\r\n for (let i = 0; i < argv.length; i++) {\r\n const a = argv[i];\r\n if (a === '--format=json') return true;\r\n if (a === '--format' && argv[i + 1] === 'json') return true;\r\n }\r\n return false;\r\n}\r\n\r\n/** Print a verb schema as a single pretty-printed JSON object to stdout. */\r\nexport function emitSchema(schema: VerbSchema): void {\r\n console.log(JSON.stringify(schema, null, 2));\r\n}\r\n\r\n/**\r\n * Attach `--help --format json` schema output to a command. When help is\r\n * requested with an explicit `--format json`, the schema is printed to stdout\r\n * and an empty string is returned so commander prints nothing further and exits\r\n * cleanly. Otherwise the original (text) help is rendered unchanged.\r\n */\r\nexport function attachSchemaHelp(cmd: Command, schema: VerbSchema): Command {\r\n const baseHelp = cmd.helpInformation.bind(cmd);\r\n cmd.helpInformation = (context) => {\r\n if (!wantsJsonSchema()) return baseHelp(context);\r\n emitSchema(schema);\r\n return '';\r\n };\r\n return cmd;\r\n}\r\n\r\n// ============================================================\r\n// Ride-elife verb schemas\r\n// ============================================================\r\n//\r\n// Flags / response are kept aligned with each command's ACTUAL flags and the\r\n// cli-core response types (QuoteResponse / BookResponse / GetOrderResponse /\r\n// CancelResponse / ListOrdersResponse). Notably: quote's passenger fields are\r\n// optional here (the command only sends them when set); get's pickup/dropoff\r\n// are `from_location` / `to_location` (v3 snake_case, NOT elife from/to);\r\n// amounts are decimal currency units (NOT cents).\r\n\r\n/** `ride-elife quote` schema (§4.4.1.3 quote schema). */\r\nexport const quoteSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'quote',\r\n description: 'Request fare quotes for a ride between two points',\r\n flags: {\r\n 'pickup-lat': { type: 'float', required: true, description: 'Pickup latitude', constraints: '-90 to 90' },\r\n 'pickup-lng': { type: 'float', required: true, description: 'Pickup longitude', constraints: '-180 to 180' },\r\n 'pickup-name': { type: 'string', required: true, description: 'Pickup location name' },\r\n 'dropoff-lat': { type: 'float', required: true, description: 'Dropoff latitude', constraints: '-90 to 90' },\r\n 'dropoff-lng': { type: 'float', required: true, description: 'Dropoff longitude', constraints: '-180 to 180' },\r\n 'dropoff-name': { type: 'string', required: true, description: 'Dropoff location name' },\r\n 'pickup-time': {\r\n type: 'int|string',\r\n required: true,\r\n description: \"Epoch seconds or the literal 'now'\",\r\n },\r\n 'passenger-name': { type: 'string', required: false, description: 'Lead passenger full name' },\r\n 'passenger-phone': { type: 'string', required: false, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\r\n 'passenger-count': { type: 'int', required: false, description: 'Number of passengers' },\r\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\r\n 'passenger-email': { type: 'string', required: false, description: 'Passenger email address' },\r\n 'children-count': { type: 'int', required: false, description: 'Number of children' },\r\n 'infant-count': { type: 'int', required: false, description: 'Number of infants (passenger breakdown; affects seat pricing)' },\r\n 'toddler-count': { type: 'int', required: false, description: 'Number of toddlers (passenger breakdown; affects seat pricing)' },\r\n },\r\n response: {\r\n vehicle_classes: {\r\n type: 'array',\r\n description: 'Available vehicle options with pricing',\r\n items: {\r\n vehicle_class: { type: 'string', description: 'Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\r\n 'price.amount': { type: 'float', description: 'Price in currency units (e.g. 42.50), NOT cents' },\r\n 'price.currency': { type: 'string', description: 'ISO 4217 (e.g. USD)' },\r\n 'price.quote_id': { type: 'string', description: 'Use this in `ride-elife book --quote-id`' },\r\n passenger_capacity: { type: 'int', description: 'Max passengers' },\r\n luggage_capacity: { type: 'int', description: 'Max luggage items' },\r\n },\r\n },\r\n meet_and_greet: { type: 'object|null', description: 'Meet & greet availability and price' },\r\n is_airport_transfer: { type: 'bool', description: 'Whether this is an airport transfer' },\r\n airport_direction: { type: 'string|null', description: 'pickup / dropoff / null' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife quote --pickup-lat 37.7937 --pickup-lng -122.3956 --pickup-name \"1 Market St\" --dropoff-lat 37.6213 --dropoff-lng -122.3790 --dropoff-name \"SFO Airport\" --pickup-time now',\r\n output_summary:\r\n 'Returns vehicle_classes[] with a quote_id per option. Use quote_id and vehicle_class for booking.',\r\n },\r\n error_recovery: {\r\n VEHICLE_UNAVAILABLE: 'No vehicles for this route/time. Try a different pickup-time or location. Do NOT blindly retry.',\r\n PARAM_INVALID: 'Fix the offending flag (coordinates must be numbers; required pickup/dropoff/pickup-time present), then retry.',\r\n },\r\n};\r\n\r\n/** `ride-elife book` schema (§4.4.1.3 book schema). Write op (W/Y). */\r\nexport const bookSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'book',\r\n description: 'Book a ride using a quote_id returned by a previous quote call',\r\n flags: {\r\n 'quote-id': { type: 'string', required: true, description: 'Quote id from quote response (vehicle_classes[].price.quote_id)' },\r\n 'vehicle-class': { type: 'string', required: true, description: 'Vehicle class: Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\r\n 'price-amount': { type: 'float', required: true, description: 'Fare in decimal currency units (NOT cents), from the quote' },\r\n 'price-currency': { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code' },\r\n 'payment-order-id': {\r\n type: 'string',\r\n required: 'conditional',\r\n description: 'Required when billing_mode=pay_per_call (a PAID payment order). Forbidden when billing_mode=monthly_settlement',\r\n },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Bound payment method id to charge (pay_per_call only). Opaque id from `token payment-methods list`; ignored for monthly_settlement',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'DEPRECATED — use `ride-elife create-order` + `pay-order` for network-token direct charge. A single-step book carrying a network token hits Charge_Service strict order↔token binding and is rejected server-side with a retriable=false guidance error. Kept only for backward compatibility; monthly_settlement / EVO / no-credential booking still work via book',\r\n },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'passenger-name': { type: 'string', required: true, description: 'Passenger full name' },\r\n 'passenger-phone': { type: 'string', required: true, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\r\n 'passenger-email': { type: 'string', required: true, description: 'Passenger email (required by eLife for booking)' },\r\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\r\n 'special-requests': { type: 'string', required: false, description: 'Free-text special requests or notes' },\r\n 'pickup-lat': { type: 'float', required: false, description: 'Pickup latitude (must match the quote)', constraints: '-90 to 90' },\r\n 'pickup-lng': { type: 'float', required: false, description: 'Pickup longitude (must match the quote)', constraints: '-180 to 180' },\r\n 'pickup-name': { type: 'string', required: false, description: 'Pickup location name (must match the quote)' },\r\n 'dropoff-lat': { type: 'float', required: false, description: 'Dropoff latitude (must match the quote)', constraints: '-90 to 90' },\r\n 'dropoff-lng': { type: 'float', required: false, description: 'Dropoff longitude (must match the quote)', constraints: '-180 to 180' },\r\n 'dropoff-name': { type: 'string', required: false, description: 'Dropoff location name (must match the quote)' },\r\n 'pickup-time': { type: 'int|string', required: false, description: \"Epoch seconds or 'now' (must match the quote)\" },\r\n 'meet-and-greet': { type: 'bool', required: false, default: false, description: 'Enable meet & greet service' },\r\n 'meet-and-greet-price': { type: 'float', required: false, description: 'Meet & greet surcharge from the quote (meet_and_greet.price.amount)' },\r\n 'welcome-sign': { type: 'string', required: false, description: 'Welcome sign text (meet & greet)' },\r\n 'child-seat-count': { type: 'int', required: false, description: 'Number of child seats needed', constraints: '0 to 5' },\r\n 'infant-seat-count': { type: 'int', required: false, description: 'Number of infant seats needed', constraints: '0 to 5' },\r\n 'toddler-seat-count': { type: 'int', required: false, description: 'Number of toddler seats needed', constraints: '0 to 5' },\r\n 'arrival-flight-no': { type: 'string', required: false, description: 'Arrival flight number (airport pickup)' },\r\n 'arrival-airline': { type: 'string', required: false, description: 'Arrival airline name' },\r\n 'departure-flight-no': { type: 'string', required: false, description: 'Departure flight number (airport dropoff)' },\r\n 'departure-airline': { type: 'string', required: false, description: 'Departure airline name' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Ride identifier — use for `ride-elife get` / `ride-elife cancel`' },\r\n order_id: { type: 'string|int', description: 'Internal order id for reconciliation' },\r\n status: { type: 'string', description: 'Ride status (case-sensitive server casing)' },\r\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride; false = realtime' },\r\n order_type: { type: 'string', description: \"'realtime' or 'airport'\" },\r\n price: { type: 'object', description: '{ amount, currency, quote_id }' },\r\n payment_status: { type: 'string', description: 'PAID (pay_per_call) or ON_ACCOUNT (monthly_settlement)' },\r\n billing_entry_id: { type: 'string|absent', description: 'Only in monthly_settlement mode' },\r\n payment_order_id: { type: 'string|absent', description: 'Only in pay_per_call mode (echoes the request)' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife book --quote-id qte_01HZXD --vehicle-class Sedan --price-amount 42.50 --passenger-name \"Alice\" --passenger-phone +14155551234 --idempotency-key book-123',\r\n output_summary: 'Returns ride_id. Use ride_id in `ride-elife get` to poll status.',\r\n },\r\n error_recovery: {\r\n QUOTE_EXPIRED: \"Re-invoke 'quote' for a fresh quote_id, then retry 'book' with the SAME --idempotency-key.\",\r\n BILLING_MODE_MISMATCH: 'Check Developer.billing_mode. pay_per_call requires --payment-order-id; monthly_settlement forbids it.',\r\n PAYMENT_ORDER_NOT_PAID: 'Wait for the payment order status=PAID, then retry with the SAME --idempotency-key.',\r\n PAYMENT_ORDER_ALREADY_CONSUMED: 'Create a new payment order, then retry with the new payment-order-id and a NEW --idempotency-key.',\r\n ACCOUNT_INSUFFICIENT_BALANCE: 'Top up the settlement account (offline) or pick a cheaper vehicle_class, then retry.',\r\n BOOKING_FAILED: 'elife rejected after settlement. The message contains a ref: for manual reconciliation. Do NOT auto-retry.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/**\r\n * `ride-elife create-order` schema (ride-network-token-direct-charge R11.1).\r\n * Write op (W/Y). Lock-only first step of the two-step network-token flow:\r\n * locks the fare + returns the authoritative `order_ref`, and does NOT charge\r\n * or call eLife. Carries the SAME trip/quote/passenger/surcharge context as\r\n * `book` MINUS every payment credential — funding is deferred to `pay-order`.\r\n */\r\nexport const rideCreateOrderSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'create-order',\r\n description:\r\n 'Lock a ride fare without charging (status AWAITING_PAYMENT). Returns the authoritative order_ref to bind as the network token external_transaction_id, then settle with pay-order. No payment credentials here — funding happens in pay-order',\r\n flags: {\r\n 'quote-id': { type: 'string', required: true, description: 'Quote id from quote response (vehicle_classes[].price.quote_id)' },\r\n 'vehicle-class': { type: 'string', required: true, description: 'Vehicle class: Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\r\n 'price-amount': { type: 'float', required: true, description: 'Fare in decimal currency units (NOT cents), from the quote' },\r\n 'price-currency': { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'passenger-name': { type: 'string', required: true, description: 'Passenger full name' },\r\n 'passenger-phone': { type: 'string', required: true, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\r\n 'passenger-email': { type: 'string', required: true, description: 'Passenger email (persisted at lock; eLife needs it when pay-order creates the ride)' },\r\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\r\n 'special-requests': { type: 'string', required: false, description: 'Free-text special requests or notes' },\r\n 'pickup-lat': { type: 'float', required: false, description: 'Pickup latitude (must match the quote)', constraints: '-90 to 90' },\r\n 'pickup-lng': { type: 'float', required: false, description: 'Pickup longitude (must match the quote)', constraints: '-180 to 180' },\r\n 'pickup-name': { type: 'string', required: false, description: 'Pickup location name (must match the quote)' },\r\n 'dropoff-lat': { type: 'float', required: false, description: 'Dropoff latitude (must match the quote)', constraints: '-90 to 90' },\r\n 'dropoff-lng': { type: 'float', required: false, description: 'Dropoff longitude (must match the quote)', constraints: '-180 to 180' },\r\n 'dropoff-name': { type: 'string', required: false, description: 'Dropoff location name (must match the quote)' },\r\n 'pickup-time': { type: 'int|string', required: false, description: \"Epoch seconds or 'now' (must match the quote)\" },\r\n 'meet-and-greet': { type: 'bool', required: false, default: false, description: 'Enable meet & greet service' },\r\n 'meet-and-greet-price': { type: 'float', required: false, description: 'Meet & greet surcharge from the quote (meet_and_greet.price.amount)' },\r\n 'welcome-sign': { type: 'string', required: false, description: 'Welcome sign text (meet & greet)' },\r\n 'child-seat-count': { type: 'int', required: false, description: 'Number of child seats needed', constraints: '0 to 5' },\r\n 'infant-seat-count': { type: 'int', required: false, description: 'Number of infant seats needed', constraints: '0 to 5' },\r\n 'toddler-seat-count': { type: 'int', required: false, description: 'Number of toddler seats needed', constraints: '0 to 5' },\r\n 'arrival-flight-no': { type: 'string', required: false, description: 'Arrival flight number (airport pickup)' },\r\n 'arrival-airline': { type: 'string', required: false, description: 'Arrival airline name' },\r\n 'departure-flight-no': { type: 'string', required: false, description: 'Departure flight number (airport dropoff)' },\r\n 'departure-airline': { type: 'string', required: false, description: 'Departure airline name' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Authoritative order_ref (rio_…, = order document _id). Bind it as the network token external_transaction_id and pass it to pay-order' },\r\n status: { type: 'string', description: 'AWAITING_PAYMENT after a successful lock' },\r\n payment_status: { type: 'string', description: 'PENDING after lock (funds untouched)' },\r\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride; false = realtime' },\r\n order_type: { type: 'string', description: \"'realtime' or 'airport'\" },\r\n price: { type: 'object', description: '{ amount, currency, quote_id } — the authoritative amount + currency the token must match' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife create-order --quote-id qte_01HZXD --vehicle-class Sedan --price-amount 42.50 --passenger-name \"Alice\" --passenger-phone +14155551234 --passenger-email alice@example.com --idempotency-key ride-create-123',\r\n output_summary:\r\n 'Returns order_id (the order_ref). Bind it as the token external_transaction_id, mint the token for price.amount, then settle with `ride-elife pay-order --order-id <order_ref>`.',\r\n },\r\n error_recovery: {\r\n QUOTE_EXPIRED: \"Re-invoke 'quote' for a fresh quote_id, then retry 'create-order' with the SAME --idempotency-key.\",\r\n VEHICLE_CLASS_MISMATCH: 'The vehicle-class does not match the quote. Re-quote and pass the exact vehicle_class back.',\r\n PRICE_MISMATCH: 'The submitted total does not equal the authoritative fare. Re-quote and pass price-amount from the fresh quote.',\r\n IDEMPOTENCY_CONFLICT: 'Same --idempotency-key reused with different order params. Use a fresh idempotency-key.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/**\r\n * `ride-elife pay-order` schema (ride-network-token-direct-charge\r\n * R11.2/R11.4/R11.5). Write op (W/Y). Settlement second step of the two-step\r\n * network-token flow: charges the locked AWAITING_PAYMENT order and creates the\r\n * ride upstream, pushing it to PAID / SETTLED. Funds move HERE, not in\r\n * create-order. Exactly one of --payment-token-id / --payment-method-id is\r\n * required (mutually exclusive) — both missing or both present is rejected\r\n * locally as PARAM_INVALID before any request is sent.\r\n */\r\nexport const ridePayOrderSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'pay-order',\r\n description:\r\n 'Settle a locked ride order created by create-order. Charging happens in this step (create-order only locks the fare and moves no money). Provide EXACTLY ONE of --payment-token-id (network-token direct charge — the main path; charge(order_id=order_ref) triggers strict order↔token binding) or --payment-method-id (EVO bound-card fallback); both missing or both present is rejected as PARAM_INVALID before any request. The amount/currency are NOT accepted here — the platform settles at the order-locked authoritative amount and the token minted amount. On success the order becomes status=PAID / payment_status=SETTLED',\r\n flags: {\r\n 'order-id': {\r\n type: 'string',\r\n required: true,\r\n description: 'The authoritative order_ref (rio_…) from create-order.response.order_id to settle',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: 'conditional',\r\n description:\r\n 'Network-token id (UnionPay/Visa) for the direct-charge main path. Bind order_ref as its external_transaction_id first. Exactly one of --payment-token-id / --payment-method-id is required (mutually exclusive)',\r\n },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: 'conditional',\r\n description:\r\n 'Bound-card id to charge via EVO preauth+capture (fallback path). Exactly one of --payment-token-id / --payment-method-id is required (mutually exclusive)',\r\n },\r\n 'authorized-merchant-trans-id': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Resume a 3DS challenge: merchant trans id of an already-authorised EVO preauth returned by a prior AUTHENTICATION_REQUIRED response',\r\n },\r\n 'evo-explicit': {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description:\r\n '[方案 B/R16] Explicit opt-in to settle this pay_per_call ride via the EVO bound-card fallback rail. Set true ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side. Ignored for monthly_settlement and on the payment-token-id direct-charge path.',\r\n },\r\n authenticate: {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description:\r\n 'Opt-in to require cardholder 3DS on the network-token direct charge (payment-token-id, EVO/Mastercard). On step-up the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume via authorized-charge-no. Default off = frictionless. Ignored on the EVO preauth path and for UnionPay/Visa.',\r\n },\r\n 'return-url': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Optional 3DS/passkey return URL for the network-token authenticate path; falls back to the platform EVO_3DS_RETURN_URL.',\r\n },\r\n 'authorized-charge-no': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Resume a network-token 3DS challenge: charge_no from a prior AUTHENTICATION_REQUIRED response (settled via resume_token). Relaxes the exactly-one-credential rule (continuation, not a fresh charge).',\r\n },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n ...PRICE_ANNOTATION_FLAGS,\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Authoritative order_ref (rio_…, = order document _id) that was settled' },\r\n ride_id: { type: 'string|int', description: 'eLife upstream ride id, assigned once create_ride succeeds — use for `ride-elife get`' },\r\n status: { type: 'string', description: 'PAID after a successful settlement' },\r\n payment_status: { type: 'string', description: 'SETTLED after a successful network-token direct charge' },\r\n payment_channel: { type: 'string', description: \"'upi_agent' for the network-token direct-charge path\" },\r\n price: { type: 'object', description: '{ amount, currency, quote_id } — the authoritative amount the token matched' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife pay-order --order-id rio_01HZXD --payment-token-id ntk_01J2ABC --idempotency-key ride-pay-123',\r\n output_summary:\r\n 'Settles the order via network-token direct charge and creates the ride. Returns order_id + ride_id; the order becomes status=PAID / payment_status=SETTLED. Poll `ride-elife get --order-id <ride_id>` for driver dispatch.',\r\n },\r\n error_recovery: {\r\n PARAM_INVALID:\r\n 'Provide EXACTLY ONE of --payment-token-id or --payment-method-id (both missing or both present is invalid), and a non-empty --order-id.',\r\n TOKEN_ORDER_MISMATCH:\r\n \"The token's external_transaction_id is not this order_ref. Mint a token bound to THIS order_ref (external_transaction_id = order_ref) and retry; no funds moved.\",\r\n RESOURCE_STATE_INVALID:\r\n 'The order is not in AWAITING_PAYMENT (it may already be PAID or CANCELLED). Check status via get; do NOT retry pay-order.',\r\n RIDE_NOT_FOUND: 'No order for this --order-id. Verify it is the order_ref returned by create-order. Do NOT retry.',\r\n QUOTE_EXPIRED:\r\n \"The quote expired before settlement. Re-quote; if the authoritative price is unchanged retry pay-order with the SAME order_ref + SAME token and a NEW --idempotency-key, otherwise create a new order.\",\r\n BOOKING_FAILED:\r\n 'eLife create_ride failed after a successful charge; the charge was reversed and the order stays AWAITING_PAYMENT. Retry with a NEW --idempotency-key.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/** `ride-elife get` schema (§4.4.1.3 get schema). Read-only, supports `--watch`. */\r\nexport const rideGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'get',\r\n description: 'Retrieve a ride order status by id; with --watch, poll until a terminal status',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'The numeric ride_id (e.g. 4112961) — use the `ride_id` field from book/list-orders responses, NOT the rio_... order_id' },\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll until a terminal status, emitting one NDJSON line per update' },\r\n 'watch-interval': { type: 'int', required: false, default: DEFAULT_WATCH_INTERVAL_SECONDS, description: 'Seconds between polls when --watch is set' },\r\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll before giving up' },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Ride identifier' },\r\n status: { type: 'string', description: 'Pending / Accepted / On my way / Waiting / On board / At destination / Rejected / Cancelled / Customer no show / Driver no show' },\r\n source: { type: 'string', description: \"'local_cache' when served from the local fallback; 'mock' in sandbox\" },\r\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride' },\r\n from_location: { type: 'object', description: 'Pickup { lat, lng, name, address } (v3 snake_case, NOT elife from/to)' },\r\n to_location: { type: 'object', description: 'Dropoff { lat, lng, name, address }' },\r\n pickup_time: { type: 'int|string', description: 'Pickup time' },\r\n vehicle_class: { type: 'string|null', description: 'Vehicle class' },\r\n price: { type: 'object', description: '{ amount, currency, quote_id }' },\r\n final_amount: { type: 'float|null', description: 'Final settled fare (realtime, after final-fare settlement)' },\r\n final_settlement_status: { type: 'string', description: 'pending / settled / no_adjustment / settlement_pending / not_applicable' },\r\n driver: { type: 'object|null', description: '{ name, phone_number } — available after a driver is assigned' },\r\n vehicle: { type: 'object|null', description: '{ make, model, color, license_plate, image_url } — available after a driver is assigned' },\r\n created_at: { type: 'string', description: 'Order creation time' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife get --order-id EL-20260527-1023456',\r\n output_summary:\r\n 'Returns current status and driver/vehicle info. Terminal statuses: At destination, Cancelled, Rejected, Customer no show, Driver no show.',\r\n },\r\n polling: {\r\n recommended_interval_seconds: DEFAULT_WATCH_INTERVAL_SECONDS,\r\n terminal_statuses: [...TERMINAL_STATUSES],\r\n in_progress_statuses: ['Pending', 'Accepted', 'On my way', 'Waiting', 'On board'],\r\n field_availability: {\r\n driver: \"Populated from status 'Accepted' onwards (after a driver is dispatched). Null in 'Pending'.\",\r\n vehicle: \"Populated from status 'Accepted' onwards. Null in 'Pending'.\",\r\n },\r\n },\r\n error_recovery: {\r\n VEHICLE_UNAVAILABLE: 'Order not found. Verify --order-id is the ride_id from book. Do NOT retry.',\r\n BOOKING_FAILED: 'Transient elife error. Retry once after 5s.',\r\n },\r\n};\r\n\r\n/** `ride-elife cancel` schema (§4.4.1.3 cancel schema). Write op (W/Y). */\r\nexport const cancelSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'cancel',\r\n description: 'Cancel a ride order by id (a cancellation fee may apply depending on ride status)',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'The numeric ride_id (e.g. 4112961) to cancel — use the `ride_id` field from book/list-orders responses, NOT the rio_... order_id' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Cancelled ride id' },\r\n ride_stat: { type: 'string', description: \"Status after cancellation (typically 'Cancelled')\" },\r\n cancellation: {\r\n type: 'object|null',\r\n description: 'Cancellation details',\r\n properties: {\r\n cancellation_fee: { type: 'float', description: 'Fee charged for cancellation' },\r\n reversal_amount: { type: 'float', description: 'Amount reversed/refunded' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code' },\r\n },\r\n },\r\n refund_amount: { type: 'float', description: 'Amount credited back to the settlement balance (paid − cancellation_fee)' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife cancel --order-id EL-20260527-1023456 --idempotency-key cancel-456',\r\n output_summary: 'Returns cancellation fee and refund amount.',\r\n },\r\n error_recovery: {\r\n CANCELLATION_NOT_ALLOWED: 'The ride is in a non-cancellable state. Do NOT retry; query status with `ride-elife get`.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/**\r\n * `ride-elife update` schema (elife-capability-parity). Write op (W/Y).\r\n *\r\n * Flag names MUST stay identical to `verbs.update.flags` in ride-elife.json —\r\n * `scripts/check_ride_elife_schema.py` Property 11 diffs the two sets.\r\n *\r\n * No fare flags here, deliberately. The platform holds a pre-authorization and a\r\n * ledger entry made at the booked amount, and nothing on the update path re-checks\r\n * the fare the way book does (VEHICLE_CLASS_MISMATCH against the monthly quote, the\r\n * surcharge check against Quote_Cache). Exposing quote-id / vehicle-class / price-*\r\n * would let an agent produce an order where upstream charges the new fare and the\r\n * platform still has the old one. Cancel and book again to change the fare.\r\n */\r\nexport const rideUpdateSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'update',\r\n description:\r\n 'Modify an existing ride booking: trip details (time / route / flight info) and/or passenger details. Fare changes are rejected — cancel and book again instead',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'The numeric ride_id (e.g. 4112961) to modify — use the `ride_id` field from book/list-orders responses, NOT the rio_... order_id' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n 'pickup-lat': { type: 'float', required: false, description: 'New pickup latitude', constraints: '-90 to 90' },\r\n 'pickup-lng': { type: 'float', required: false, description: 'New pickup longitude', constraints: '-180 to 180' },\r\n 'pickup-name': { type: 'string', required: false, description: 'New pickup location name' },\r\n 'dropoff-lat': { type: 'float', required: false, description: 'New dropoff latitude', constraints: '-90 to 90' },\r\n 'dropoff-lng': { type: 'float', required: false, description: 'New dropoff longitude', constraints: '-180 to 180' },\r\n 'dropoff-name': { type: 'string', required: false, description: 'New dropoff location name' },\r\n 'pickup-time': { type: 'int|string', required: false, description: \"New pickup time: epoch seconds or 'now'\" },\r\n 'welcome-sign': { type: 'string', required: false, description: 'New welcome sign text (meet & greet)' },\r\n 'arrival-flight-no': { type: 'string', required: false, description: 'New arrival flight number' },\r\n 'arrival-airline': { type: 'string', required: false, description: 'New arrival airline name' },\r\n 'departure-flight-no': { type: 'string', required: false, description: 'New departure flight number' },\r\n 'departure-airline': { type: 'string', required: false, description: 'New departure airline name' },\r\n 'service-area-id': { type: 'string', required: false, description: 'Service area id, when the upstream requires re-scoping the ride' },\r\n 'passenger-name': { type: 'string', required: false, description: 'New passenger full name (passing any passenger-* flag triggers a passenger update)' },\r\n 'passenger-phone': { type: 'string', required: false, description: 'New passenger phone in E.164 format (e.g. +14155551234)' },\r\n 'passenger-email': { type: 'string', required: false, description: 'New passenger email' },\r\n 'luggage-count': { type: 'int', required: false, description: 'New luggage count' },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Modified ride id' },\r\n status: { type: 'string', description: \"Result status, 'updated' when the modification was applied\" },\r\n ride_updated: { type: 'bool', description: 'true when trip-side fields were sent upstream' },\r\n passenger_updated: { type: 'bool', description: 'true when passenger fields were sent upstream' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife update --order-id 4112961 --pickup-time 1780000000 --idempotency-key update-789',\r\n output_summary: 'Returns which sides were applied (ride_updated / passenger_updated).',\r\n },\r\n error_recovery: {\r\n PARAM_INVALID: 'No modifiable field was supplied. Pass at least one trip field or one passenger-* flag.',\r\n RIDE_NOT_FOUND: 'The ride does not exist or belongs to another developer. Verify --order-id is the ride_id from book.',\r\n CANCELLATION_NOT_ALLOWED: 'The ride is past the modifiable window. Query with `ride-elife get`; cancel and re-book if the user needs a different trip.',\r\n UPSTREAM_ERROR: 'Partial update: one side applied upstream, the other failed (see data.partial_update). The upstream has NO rollback — re-issue update for the failed side ONLY, then confirm with `ride-elife get`.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/**\r\n * `ride-elife trip-status` schema (elife-capability-parity). Read-only.\r\n *\r\n * Flag names MUST stay identical to `verbs.trip-status.flags` in ride-elife.json.\r\n */\r\nexport const rideTripStatusSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'trip-status',\r\n description: 'Query the status and driver location points of a single leg of a multi-leg ride',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'The numeric ride_id (e.g. 4112961) — use the `ride_id` field from book/list-orders responses' },\r\n 'trip-no': { type: 'int', required: false, default: 1, description: '1-based leg index; defaults to the first leg' },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Ride identifier' },\r\n trip_no: { type: 'int', description: 'Leg number this status refers to' },\r\n status: { type: 'string', description: 'Leg status, same vocabulary as `ride-elife get`' },\r\n points: {\r\n type: 'array|null',\r\n description: 'Driver location points for this leg',\r\n items: { lat: { type: 'float' }, lng: { type: 'float' }, utc_timestamp: { type: 'int' } },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife trip-status --order-id 4112961 --trip-no 2',\r\n output_summary: 'Returns the leg status plus its driver location points.',\r\n },\r\n polling: {\r\n recommended_interval_seconds: DEFAULT_WATCH_INTERVAL_SECONDS,\r\n terminal_statuses: [...TERMINAL_STATUSES],\r\n in_progress_statuses: ['Pending', 'Accepted', 'On my way', 'Waiting', 'On board'],\r\n field_availability: {\r\n points: 'Populated only after the driver starts moving on this leg; empty or null before that.',\r\n },\r\n },\r\n error_recovery: {\r\n RIDE_NOT_FOUND: 'The ride or the requested leg does not exist. Confirm the ride has multiple legs via `ride-elife get` first.',\r\n UPSTREAM_ERROR: 'Upstream Trip Status errored. Legs only exist after a driver is dispatched — use get.response.next_trip_no and only query once the ride has started. As of 2026-08 the sandbox returns 502 here for rides with no dispatched legs regardless of --trip-no; fall back to `ride-elife get`.',\r\n BOOKING_FAILED: 'Transient upstream error. Retry once after 5s, or fall back to `ride-elife get` for whole-ride status.',\r\n },\r\n};\r\n\r\n// ── ride-elife callback-* (status-event forwarding to the caller's endpoint) ──\r\n\r\nconst RIDE_ORDER_ID_FLAG: FlagSchema = {\r\n type: 'string',\r\n required: true,\r\n description: 'The numeric ride_id returned by book (NOT the rio_... order_id)',\r\n};\r\nconst CALLBACK_IDEMPOTENCY_FLAG: FlagSchema = {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n};\r\nconst CALLBACK_SUBSCRIPTION_FLAGS: Record<string, FlagSchema> = {\r\n 'callback-url': { type: 'string', required: true, description: 'https URL that receives status events; internal addresses are rejected by the platform' },\r\n adapter: { type: 'string', required: false, default: 'techtanium_v1', description: 'Outbound event shape' },\r\n 'signature-mode': { type: 'string', required: false, default: 'off', description: 'off / optional / required' },\r\n 'callback-api-key': { type: 'string', required: false, description: 'API key sent to your endpoint; omit to keep the stored one (never echoed back)' },\r\n 'rotate-secret': { type: 'bool', required: false, default: false, description: 'Issue a new signing secret; the old one stops verifying' },\r\n 'idempotency-key': CALLBACK_IDEMPOTENCY_FLAG,\r\n};\r\nconst CALLBACK_SUBSCRIPTION_RESPONSE = {\r\n callback_url: { type: 'string', description: 'Registered destination' },\r\n adapter: { type: 'string', description: 'Outbound event shape' },\r\n signature_mode: { type: 'string', description: 'off / optional / required' },\r\n status: { type: 'string', description: 'Registration status' },\r\n callback_secret: { type: 'string', description: 'Signing secret — present ONLY in the set response that issued it; store it, it cannot be read back' },\r\n};\r\nconst CALLBACK_ERRORS = {\r\n RIDE_NOT_FOUND: 'The ride is not yours or does not exist; check the ride_id from book/list-orders.',\r\n PARAM_INVALID: 'Fix the flag named in the message (https URL, signature-mode, ranges) and retry.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n};\r\n\r\n/** `ride-elife callback-set` schema. Write op: per-ride callback destination. */\r\nexport const rideCallbackSetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-set',\r\n description: \"Register (or update) where one ride's status events are forwarded; takes priority over the default\",\r\n flags: { 'order-id': RIDE_ORDER_ID_FLAG, ...CALLBACK_SUBSCRIPTION_FLAGS },\r\n response: { ride_id: { type: 'string|int', description: 'Ride id' }, order_id: { type: 'string', description: 'rio_... order id' }, ...CALLBACK_SUBSCRIPTION_RESPONSE },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife callback-set --order-id 4112961 --callback-url https://example.com/ride-events --idempotency-key cb-1',\r\n output_summary: 'Returns the registration; the first registration also returns callback_secret once.',\r\n },\r\n error_recovery: CALLBACK_ERRORS,\r\n};\r\n\r\n/** `ride-elife callback-get` schema. Read-only. */\r\nexport const rideCallbackGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-get',\r\n description: \"Show one ride's callback registration (the signing secret is never returned)\",\r\n flags: { 'order-id': RIDE_ORDER_ID_FLAG },\r\n response: { ride_id: { type: 'string|int', description: 'Ride id' }, order_id: { type: 'string', description: 'rio_... order id' }, ...CALLBACK_SUBSCRIPTION_RESPONSE },\r\n example: { command: 'agenzo-merchant-cli ride-elife callback-get --order-id 4112961', output_summary: 'Returns the registration without the secret.' },\r\n error_recovery: { RIDE_NOT_FOUND: CALLBACK_ERRORS.RIDE_NOT_FOUND },\r\n};\r\n\r\n/** `ride-elife callback-default-set` schema. Write op: developer-wide fallback. */\r\nexport const rideCallbackDefaultSetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-default-set',\r\n description: 'Register (or update) the developer-wide fallback used by rides that have no callback of their own',\r\n flags: CALLBACK_SUBSCRIPTION_FLAGS,\r\n response: { developer_id: { type: 'string', description: 'Owner of the default' }, ...CALLBACK_SUBSCRIPTION_RESPONSE },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife callback-default-set --callback-url https://example.com/ride-events --idempotency-key cbd-1',\r\n output_summary: 'Configure once so events for rides booked later are never dropped.',\r\n },\r\n error_recovery: { PARAM_INVALID: CALLBACK_ERRORS.PARAM_INVALID, PARAM_IDEMPOTENCY_KEY_REQUIRED: CALLBACK_ERRORS.PARAM_IDEMPOTENCY_KEY_REQUIRED },\r\n};\r\n\r\n/** `ride-elife callback-default-get` schema. Read-only. */\r\nexport const rideCallbackDefaultGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-default-get',\r\n description: 'Show the developer-wide fallback callback (the signing secret is never returned)',\r\n flags: {},\r\n response: { developer_id: { type: 'string', description: 'Owner of the default' }, ...CALLBACK_SUBSCRIPTION_RESPONSE },\r\n example: { command: 'agenzo-merchant-cli ride-elife callback-default-get', output_summary: 'Returns the default without the secret.' },\r\n};\r\n\r\n/** `ride-elife callback-deliveries` schema. Read-only. */\r\nexport const rideCallbackDeliveriesSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-deliveries',\r\n description: \"List one ride's callback forwarding records (pending / delivered / dead)\",\r\n flags: {\r\n 'order-id': RIDE_ORDER_ID_FLAG,\r\n limit: { type: 'int', required: false, default: 50, description: 'Page size 1-100' },\r\n offset: { type: 'int', required: false, default: 0, description: 'Records to skip' },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Ride id' },\r\n limit: { type: 'int', description: 'Page size used' },\r\n offset: { type: 'int', description: 'Offset used' },\r\n count: { type: 'int', description: 'Records in this page' },\r\n deliveries: { type: 'array', description: 'Forwarding records: event_id, status, attempts, last_error, timestamps' },\r\n },\r\n example: { command: 'agenzo-merchant-cli ride-elife callback-deliveries --order-id 4112961', output_summary: 'Shows what was forwarded and where it stalled.' },\r\n error_recovery: { RIDE_NOT_FOUND: CALLBACK_ERRORS.RIDE_NOT_FOUND, PARAM_INVALID: CALLBACK_ERRORS.PARAM_INVALID },\r\n};\r\n\r\n/** `ride-elife callback-replay` schema. Write op: requeue dead/failed records. */\r\nexport const rideCallbackReplaySchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-replay',\r\n description: \"Requeue one ride's dead (or failed) callback records; delivered records are never re-sent\",\r\n flags: {\r\n 'order-id': RIDE_ORDER_ID_FLAG,\r\n 'event-id': { type: 'string', required: false, description: 'Requeue only this record (default: all dead records)' },\r\n 'include-failed': { type: 'bool', required: false, default: false, description: 'Also requeue pending records that already failed' },\r\n 'reset-attempts': { type: 'bool', required: false, default: false, description: 'Reset the retry counter of requeued records' },\r\n 'idempotency-key': CALLBACK_IDEMPOTENCY_FLAG,\r\n },\r\n response: {\r\n ride_id: { type: 'string', description: 'Ride id' },\r\n requeued: { type: 'int', description: 'Number of records set back to pending' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife callback-replay --order-id 4112961 --idempotency-key rp-1',\r\n output_summary: 'Requeues dead records; the delivery worker re-sends them on its next pass.',\r\n },\r\n error_recovery: CALLBACK_ERRORS,\r\n};\r\n\r\n/** `ride-elife list-orders` schema (§4.4.1.3 list-orders schema). Read-only. */\r\nexport const listOrdersSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'list-orders',\r\n description: 'List previously placed ride orders with optional filters and pagination',\r\n flags: {\r\n status: { type: 'string', required: false, description: 'Filter by ride status (case-sensitive server casing)' },\r\n 'order-type': { type: 'string', required: false, description: 'Filter by order type (e.g. realtime / airport)' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n page: { type: 'int', required: false, default: 1, description: 'Page number', constraints: '>= 1' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page', constraints: '>= 1' },\r\n },\r\n response: {\r\n orders: {\r\n type: 'array',\r\n description: 'List of ride orders (slim list-item shape)',\r\n items: {\r\n order_id: { type: 'string', description: 'Internal order id' },\r\n member_id: { type: 'string|null', description: 'End-user this order is attributed to; null when unattributed' },\r\n ride_id: { type: 'string', description: 'Ride id (same as ride_id from book)' },\r\n status: { type: 'string', description: 'Current ride status' },\r\n vehicle_class: { type: 'string', description: 'Vehicle class' },\r\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport, false = realtime' },\r\n scheduled_at: { type: 'string', description: 'ISO 8601 datetime; empty for realtime orders' },\r\n price_amount: { type: 'float|null', description: 'Price in decimal currency units (NOT cents)' },\r\n final_amount: { type: 'float|null', description: 'Final settled amount' },\r\n price_currency: { type: 'string', description: 'ISO 4217 currency code' },\r\n payment_status: { type: 'string', description: 'Payment status' },\r\n final_settlement_status: { type: 'string', description: 'pending / settled / no_adjustment / settlement_pending / not_applicable' },\r\n cancellation_fee: { type: 'float|null', description: 'Cancellation fee for cancelled orders; null otherwise' },\r\n provider: { type: 'string', description: 'Service provider (elife)' },\r\n created_at: { type: 'string|null', description: 'Order creation time (ISO 8601)' },\r\n updated_at: { type: 'string|null', description: 'Last update time (ISO 8601)' },\r\n },\r\n },\r\n total: { type: 'int', description: 'Total matching orders' },\r\n page: { type: 'int', description: 'Current page' },\r\n page_size: { type: 'int', description: 'Items per page' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife list-orders --status Pending --page 1 --page-size 10',\r\n output_summary: 'Returns a paginated list of ride orders with status and amount info.',\r\n },\r\n error_recovery: {\r\n INTERNAL_ERROR: 'Transient backend error. Retry once after a short delay.',\r\n PARAM_INVALID: 'Ensure --page / --page-size are positive integers, then retry.',\r\n },\r\n};\r\n\r\n// ============================================================\r\n// Hotel-redaug verb schemas\r\n// ============================================================\r\n//\r\n// Flags / response are kept aligned with each command's ACTUAL flags\r\n// (requirements 2.1 / 3.1 / 4.1 / 5.1 / 6.1 / 7.1 / 8.1 / 9.1) and the live\r\n// response types in `types/hotel.ts` (NOT the capability schema where they\r\n// diverge). Three deliberate reconciliations vs the capability schema:\r\n// - `order_status` is the std STRING on the wire; `get` also carries the\r\n// integer `order_status_code` (2/3/4/5). There is NO `order_status_std`.\r\n// - `cancel` models both the confirmed and accepted-but-pending shapes.\r\n// - `checkout` returns `{ order_id, task_order_code, apply_status,\r\n// checkout_status }`.\r\n// Amounts are decimal currency units paired with a currency code (never minor\r\n// units). `error_recovery` guidance is taken from the capability schema's\r\n// `error_recovery[code].agent_action`, keyed on the REAL wire codes\r\n// (`HOTEL_ORDER_NOT_FOUND` / `CHECKOUT_TASK_NOT_FOUND`, not the agent-facing\r\n// `ORDER_NOT_FOUND` / `TASK_NOT_FOUND` aliases).\r\n//\r\n// `--api-key`, `--yes` and `--format` are cross-cutting flags resolved by the\r\n// program/top-level handler; like the ride-elife schemas, they are intentionally\r\n// omitted from the per-verb `flags` block (which declares only domain flags).\r\n\r\n/** `hotel-redaug search` schema. Read-only, supports both location branches. */\r\nexport const hotelSearchSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'search',\r\n description:\r\n 'Search hotels near a coordinate OR within a destination for the given stay dates. Two location branches: --destination-id (from find-destination) XOR --lat/--lng (geocoded by the Agent backend). Exactly one branch must be supplied',\r\n flags: {\r\n 'destination-id': { type: 'string', required: 'conditional', description: 'Destination ID from find-destination (alternative to --lat/--lng)', constraints: 'Exactly one location branch: --destination-id XOR (--lat + --lng)' },\r\n lat: { type: 'float', required: 'conditional', description: 'Latitude of the search center (geocoded by the Agent backend, not by the CLI)', constraints: '-90 to 90; requires --lng; mutually exclusive with --destination-id' },\r\n lng: { type: 'float', required: 'conditional', description: 'Longitude of the search center (geocoded by the Agent backend, not by the CLI)', constraints: '-180 to 180; requires --lat; mutually exclusive with --destination-id' },\r\n distance: { type: 'int', required: false, default: 20, description: 'Search radius in kilometers', constraints: 'Agent infers from phrasing — small (2-5) for \"right next to a spot\", larger (15-30) for a whole city. Do NOT ask the user for a number' },\r\n 'check-in': { type: 'string', required: true, description: 'Check-in date', constraints: 'YYYY-MM-DD, today or later' },\r\n 'check-out': { type: 'string', required: true, description: 'Check-out date', constraints: 'YYYY-MM-DD, strictly after check-in' },\r\n adults: { type: 'int', required: false, default: 2, description: 'Number of adults', constraints: '1-9 per room' },\r\n children: { type: 'int', required: false, default: 0, description: 'Number of children' },\r\n 'room-num': { type: 'int', required: false, default: 1, description: 'Number of rooms requested' },\r\n star: { type: 'int', required: false, description: 'Minimum hotel star rating filter', constraints: 'Enum 3 / 4 / 5' },\r\n keyword: { type: 'string', required: false, description: 'Optional hotel name keyword to narrow results' },\r\n 'price-min': { type: 'float', required: false, description: 'Minimum price filter' },\r\n 'price-max': { type: 'float', required: false, description: 'Maximum price filter' },\r\n 'sort-by': { type: 'string', required: false, description: 'Sort field' },\r\n page: { type: 'int', required: false, default: 1, description: 'Page number', constraints: '>= 1' },\r\n 'page-size': { type: 'int', required: false, default: 10, description: 'Results per page', constraints: '>= 1' },\r\n 'hotel-facility-codes': { type: 'string', required: false, description: 'Hotel facility codes (comma-separated or JSON array, from hotel-filters)' },\r\n 'room-facility-codes': { type: 'string', required: false, description: 'Room facility codes (comma-separated or JSON array, from hotel-filters)' },\r\n 'hotel-brand-codes': { type: 'string', required: false, description: 'Hotel brand codes (comma-separated or JSON array, from hotel-filters)' },\r\n 'plate-codes': { type: 'string', required: false, description: 'Plate codes (comma-separated or JSON array, from hotel-filters)' },\r\n 'hotel-label-ids': { type: 'string', required: false, description: 'Hotel label IDs (comma-separated or JSON array, from hotel-filters)' },\r\n 'hotel-sub-category-ids': { type: 'string', required: false, description: 'Hotel sub-category IDs (comma-separated or JSON array, from hotel-filters)' },\r\n },\r\n response: {\r\n hotels: {\r\n type: 'array',\r\n description: 'Matching hotels for the location and dates. Empty when nothing was found (rendered as a successful empty result, not an error).',\r\n items: {\r\n hotel_id: { type: 'string|int', description: 'Opaque hotel identifier. Pass verbatim to quote --hotel-id. Do NOT interpret.' },\r\n hotel_name: { type: 'string', description: 'Hotel name.' },\r\n star: { type: 'int|null', description: 'Star rating.' },\r\n address: { type: 'string|null', description: 'Hotel address.' },\r\n distance_km: { type: 'float|null', description: 'Approximate distance from the search center, in km.' },\r\n city_name: { type: 'string|null', description: 'City name.' },\r\n district_name: { type: 'string|null', description: 'District name.' },\r\n business_name: { type: 'string|null', description: 'Business area name.' },\r\n score: { type: 'float|null', description: 'Hotel score/rating.' },\r\n main_image: { type: 'string|null', description: 'Main hotel image URL.' },\r\n lowest_price: {\r\n type: 'object|null',\r\n description: 'Indicative nightly starting price (not the bookable total — get the real price from quote).',\r\n properties: {\r\n amount: { type: 'float', description: 'Starting price in DECIMAL units (NOT cents).' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code.' },\r\n },\r\n },\r\n },\r\n },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli hotel-redaug search --destination-id D12345 --check-in 2026-07-04 --check-out 2026-07-05 --adults 2',\r\n output_summary: 'Returns hotels[] for the location. Pick one and use hotels[].hotel_id in hotel-redaug quote. Alternatively use --lat/--lng instead of --destination-id.',\r\n },\r\n error_recovery: {\r\n NO_AVAILABILITY: 'No hotels near this coordinate for these dates. Widen --distance, try different dates, or have the Agent backend geocode a nearby area. As a last resort try another category=hotel service (see cross_service_recovery).',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff. Otherwise surface to user.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug quote` schema. Read-only. */\r\nexport const hotelQuoteSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'quote',\r\n description:\r\n 'Get real-time room types and bookable rates for one hotel and stay. Returns rates each carrying an opaque product_token and per-night price_items that must be passed verbatim to create-order. Run immediately before create-order — availability and prices change in real time',\r\n flags: {\r\n 'hotel-id': { type: 'string', required: true, description: 'Hotel chosen from search results (search.response.hotels[].hotel_id)' },\r\n 'check-in': { type: 'string', required: true, description: 'Check-in date (match search)', constraints: 'YYYY-MM-DD' },\r\n 'check-out': { type: 'string', required: true, description: 'Check-out date (match search)', constraints: 'YYYY-MM-DD, strictly after check-in' },\r\n adults: { type: 'int', required: false, default: 2, description: 'Adults per room (match search)' },\r\n children: { type: 'int', required: false, default: 0, description: 'Children per room (match search)' },\r\n 'room-num': { type: 'int', required: false, default: 1, description: 'Number of rooms (match search)' },\r\n nationality: { type: 'string', required: false, default: 'CN', description: 'Guest nationality (ISO country code). Affects rate eligibility for some hotels' },\r\n },\r\n response: {\r\n rates: {\r\n type: 'array',\r\n description: 'Bookable room+rate options. Empty when the hotel has no rooms for these dates (treat as NO_AVAILABILITY: re-quote another hotel or change dates).',\r\n items: {\r\n product_token: { type: 'string', description: 'Opaque token packing room/rate/supply identifiers. Pass verbatim to create-order --product-token. Do NOT interpret or reuse across quotes.' },\r\n room_name: { type: 'string', description: 'Room type name.' },\r\n rate_plan_name: { type: 'string|null', description: \"Rate plan name (e.g. 'Breakfast included, free cancellation').\" },\r\n breakfast: { type: 'int|null', description: 'Breakfast enum for the rate (-1=bed breakfast, 0=no breakfast, 1+=N breakfasts). Display only.' },\r\n free_cancellation: { type: 'bool|null', description: 'Whether this rate is currently in a free-cancellation window. Prefer when the user wants flexibility.' },\r\n total_price: {\r\n type: 'object',\r\n description: 'Total bookable price for the whole stay and room count.',\r\n properties: {\r\n amount: { type: 'float', description: 'Total price in DECIMAL units. Pass verbatim to create-order --total-amount.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code. Pass to create-order --currency.' },\r\n },\r\n },\r\n price_items: {\r\n type: 'array',\r\n description: 'Per-night price breakdown. Pass this array verbatim to create-order --price-items.',\r\n items: {\r\n sale_date: { type: 'string', description: 'Night date YYYY-MM-DD.' },\r\n sale_price: { type: 'float', description: 'Price for that night in DECIMAL units.' },\r\n breakfast_num: { type: 'int', description: 'Breakfast enum for that night (-1=bed breakfast, 0=no breakfast, 1+=N). Copy verbatim into create-order; never alter.' },\r\n },\r\n },\r\n },\r\n },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli hotel-redaug quote --hotel-id 10583772 --check-in 2026-08-20 --check-out 2026-08-21 --adults 2',\r\n output_summary: 'Returns rates[]. Use rates[].product_token, total_price.amount/currency and price_items[] in hotel-redaug create-order.',\r\n },\r\n error_recovery: {\r\n NO_AVAILABILITY: 'This hotel has no bookable rooms for these dates (upstream roomItems empty). Re-quote a different hotel from the search result, or re-search with other dates. Do NOT retry the same hotel/dates.',\r\n PRICE_CHANGED: 'Rates shifted since search. Use the prices returned here; do not reuse search lowest_price. No action other than informing the user if materially higher.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug create-order` schema. Write op (W/Y) — lock inventory, no charge. */\r\nexport const hotelCreateOrderSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'create-order',\r\n description:\r\n 'Create a hotel order WITHOUT charging any account (re-check availability + createOrder upstream), using a product_token and price_items from a recent quote. The order enters AWAITING_PAYMENT — no money is moved until pay-order. check-in/check-out, guest counts, total-amount and price-items must match the quote',\r\n flags: {\r\n 'product-token': { type: 'string', required: true, description: 'Chosen rate token from quote (quote.response.rates[].product_token). Pass verbatim' },\r\n 'total-amount': { type: 'float', required: true, description: 'Total price for the stay (quote.response.rates[].total_price.amount)', constraints: 'DECIMAL units (NOT cents), 0.01–999999999.99. Must equal the chosen rate total_price.amount' },\r\n currency: { type: 'string', required: true, description: 'ISO 4217 currency code from the chosen rate (quote.response.rates[].total_price.currency)', constraints: 'Exactly 3 uppercase letters' },\r\n 'price-items': { type: 'string', required: true, description: 'Per-night price breakdown from quote, copied verbatim (including breakfast_num)', constraints: 'JSON array of {sale_date, sale_price, breakfast_num}; copy breakfast_num verbatim from quote (-1/0/1+ are distinct breakfast products, never alter); else PARAM_INVALID' },\r\n 'check-in': { type: 'string', required: true, description: 'Check-in date (match quote)', constraints: 'YYYY-MM-DD' },\r\n 'check-out': { type: 'string', required: true, description: 'Check-out date (match quote)', constraints: 'YYYY-MM-DD, strictly after check-in' },\r\n 'room-num': { type: 'int', required: false, default: 1, description: 'Number of rooms (match quote)' },\r\n adults: { type: 'int', required: false, default: 2, description: 'Adults per room (match quote)', constraints: '1-20' },\r\n children: { type: 'int', required: false, default: 0, description: 'Children per room (match quote)', constraints: '0-10' },\r\n nationality: { type: 'string', required: false, default: 'CN', description: 'Guest nationality (match quote)' },\r\n 'guest-name': { type: 'string', required: true, description: 'Primary guest name', constraints: 'Use the name as the user gives it. If a supplier returns NAME_FORMAT_INVALID, re-collect in Latin letters and retry' },\r\n 'room-guests': { type: 'string', required: false, description: \"Per-room primary guests, listed in room order, for booking several rooms under different names. Omit it and every room reuses guest-name (backward compatible); guest-name stays required either way\", constraints: 'JSON array of {guest_name (non-empty string)}; room_index is optional and filled in from the array position (1-based, validated against room-num by the platform) — pass it explicitly only to override; else PARAM_INVALID' },\r\n 'contact-name': { type: 'string', required: true, description: 'Booking contact name (may equal guest-name)' },\r\n 'contact-phone': { type: 'string', required: true, description: 'Booking contact phone number', constraints: 'Digits; collect country code separately in --contact-country-code' },\r\n 'contact-country-code': { type: 'string', required: false, default: '86', description: \"Phone country calling code without '+'\" },\r\n 'contact-email': { type: 'string', required: false, description: 'Booking contact email' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'arrive-time': { type: 'string', required: false, description: 'Expected arrival time', constraints: 'HH:mm, hotel local time' },\r\n 'special-requests': { type: 'string', required: false, description: 'Free-text special requests (non-binding)' },\r\n tips: { type: 'string', required: false, description: \"FCG 客户自测点5 提示信息: the chosen quote rate's tips (tips[].tipsDetails[]) as a JSON array [{title,text}], captured at booking. Stored on the order for the order-detail page only; platform-local, not sent upstream\", constraints: 'JSON array of {title (string, optional), text (string, optional)}; else PARAM_INVALID' },\r\n cancellation: {\r\n type: 'string',\r\n required: false,\r\n description: 'Cancellation policy snapshot copied from the selected quote rate and stored on the order.',\r\n constraints: 'JSON object; else PARAM_INVALID',\r\n },\r\n 'hotel-timezone': {\r\n type: 'string',\r\n required: false,\r\n description: \"Hotel timezone from quote (for example 'UTC+8'), used to evaluate cancellation deadlines.\",\r\n },\r\n 'bed-type': {\r\n type: 'string',\r\n required: false,\r\n description: \"Product bed-type code from the chosen quote rate's beds[].code (e.g. 'L000000' King / '1000000' Queen). Forwarded verbatim to upstream createOrder bedType; upstream recommends passing the product-dimension bed type at booking.\",\r\n },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Optional bound-card id (pay_per_call / EVO path). When set, the platform settles this order by pre-authorizing + capturing on that specific bound card; omit to let billing_mode decide.',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'UPI Agent Pay only: payment token id from an already-completed UnionPay network-token capture (funds already charged). When set, the platform skips EVO preauth/capture and only locks the order.',\r\n },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Derive from business intent (e.g. hash(user_id + product_token + check_in)) and reuse the SAME key when retrying the same order creation',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Our order reference (coOrderCode). Use as --order-id in pay-order / get / cancel.' },\r\n fc_order_code: { type: 'string', description: 'Supplier order reference. Needed as --fc-order-code in cancel and checkout.' },\r\n total_amount: { type: 'float', description: 'Amount to be paid in pay-order (DECIMAL units). The order is locked in AWAITING_PAYMENT — no charge has been made.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code for the payment.' },\r\n },\r\n example: {\r\n command:\r\n `agenzo-merchant-cli hotel-redaug create-order --product-token <tok> --total-amount 10.00 --currency CNY --price-items '[{\"sale_date\":\"2026-08-20\",\"sale_price\":10.00,\"breakfast_num\":0}]' --check-in 2026-08-20 --check-out 2026-08-21 --adults 2 --guest-name \"Zhang San\" --contact-name \"Zhang San\" --contact-phone 13800138000 --idempotency-key create-h1n2`,\r\n output_summary: 'Returns {order_id, fc_order_code, total_amount, currency}. The order is AWAITING_PAYMENT (no charge). Use order_id as --order-id in pay-order to settle.',\r\n },\r\n error_recovery: {\r\n NO_AVAILABILITY: 'Availability vanished between quote and create-order. Re-quote the same hotel; if still empty, quote another hotel or change dates. Use a NEW idempotency-key for the new product_token.',\r\n PRICE_CHANGED: 'The price/price_items no longer match upstream. Re-quote to get fresh total_price and price_items, confirm the new price with the user, then create-order with the new values and a NEW idempotency-key.',\r\n NAME_FORMAT_INVALID: 'The supplier requires the guest name in a specific format (commonly Latin first/last name for international properties). Re-collect guest-name in Latin letters and retry with the SAME idempotency-key.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Add a unique --idempotency-key derived from business intent and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'The same idempotency-key was used with different parameters. Retry with the original parameters, or generate a NEW key for the new parameters.',\r\n UPSTREAM_ERROR: 'Transient upstream error during checkBooking or createOrder. Retry once after ~2s backoff with the SAME idempotency-key.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug pay-order` schema. Write op (W/Y) — settle a created order. */\r\nexport const hotelPayOrderSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'pay-order',\r\n description:\r\n 'Settle an existing AWAITING_PAYMENT order created by create-order. Charging happens in this step — platform create-order only locks inventory/price and moves no money (lock-then-pay). Optional payment credentials (--payment-method-id / --payment-token-id / --authorized-merchant-trans-id) are forwarded to the pay body; omit them to let the platform settle by billing_mode (monthly_settlement deducts credit; pay_per_call selects the developer default card / EVO preauth). Token wins over method id server-side. On EVO cardholder authentication the response is AUTHENTICATION_REQUIRED with a three_ds_url + merchant_trans_id; resume by re-calling pay-order with --authorized-merchant-trans-id. On success the order becomes PAID. Supports --watch to poll on PAYMENT_NOT_COMPLETED until PAID',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Order to settle (create-order.response.order_id).' },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Optional bound-card id to charge (pay_per_call / EVO preauth). Ignored for monthly_settlement and when payment-token-id is set.',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Optional network-token id (UnionPay/Visa). When set the platform settles via network-token direct charge instead of EVO preauth+capture. Wins over payment-method-id.',\r\n },\r\n 'authorized-merchant-trans-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Resume a 3DS challenge: merchant trans id of an already-authorised preauth returned by a prior AUTHENTICATION_REQUIRED response. Reuses that authorization instead of creating a new one (pay_per_call only).',\r\n },\r\n 'evo-explicit': {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description: '[方案 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set true ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side. Ignored for monthly_settlement and on the payment-token-id direct-charge path.',\r\n },\r\n authenticate: {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description: 'Opt-in to require cardholder 3DS on the network-token direct charge (payment-token-id, EVO/Mastercard). On step-up the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume via authorized-charge-no. Default off = frictionless. Ignored on the EVO preauth path and for UnionPay/Visa.',\r\n },\r\n 'return-url': {\r\n type: 'string',\r\n required: false,\r\n description: 'Optional 3DS/passkey return URL for the network-token authenticate path; falls back to the platform EVO_3DS_RETURN_URL.',\r\n },\r\n 'authorized-charge-no': {\r\n type: 'string',\r\n required: false,\r\n description: 'Resume a network-token 3DS challenge: charge_no from a prior AUTHENTICATION_REQUIRED response (settled via resume_token), then triggers upstream payOrder on success (pay_per_call only).',\r\n },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Derive from business intent (e.g. hash(order_id + attempt)) and reuse the SAME key when retrying the same payment',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n ...PRICE_ANNOTATION_FLAGS,\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll automatically on PAYMENT_NOT_COMPLETED until PAID or timeout. Each iteration emits one NDJSON line' },\r\n 'watch-interval': { type: 'int', required: false, default: 5, description: 'Seconds between poll attempts in --watch mode' },\r\n 'watch-timeout': { type: 'int', required: false, default: 300, description: 'Total seconds before giving up in --watch mode' },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Order reference.' },\r\n settlement_path: { type: 'string', description: \"Which billing path was used: 'monthly_settlement' or 'pay_per_call' (same tokens as billing_mode).\" },\r\n amount: { type: 'float', description: 'Settled amount in DECIMAL units.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code of the settlement.' },\r\n pay_status: { type: 'int', description: 'Upstream pay status (1 = paid). The order internal status is now PAID.' },\r\n settled_at: { type: 'string', description: 'ISO 8601 settlement timestamp. On idempotent replay, the original first settled_at is returned unchanged.' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli hotel-redaug pay-order --order-id hho_01KWC63Z5CD6CKBM33Q7SC2ZDT --idempotency-key pay-h1n2',\r\n output_summary: 'Settlement path is chosen server-side by billing_mode. monthly_settlement: deducts from the credit account, confirms with the supplier. Returns {order_id, settlement_path:\"monthly_settlement\", amount, currency, pay_status:1, settled_at}. Order becomes PAID. For pay_per_call the user must have already paid via EVO using the order_id as the merchantTransID; the same command settles it (settlement_path:\"pay_per_call\").',\r\n },\r\n error_recovery: {\r\n PAYMENT_NOT_COMPLETED: 'pay_per_call only: EVO has not yet confirmed the payment for this order_id. Retry with the SAME idempotency-key after a delay, or use --watch to poll automatically until PAID.',\r\n PAYMENT_NOT_FOUND: 'No EVO transaction found for this order_id. Confirm the user paid via EVO using the order_id as the merchantTransID; do NOT retry blindly.',\r\n PAYMENT_AMOUNT_MISMATCH: 'The EVO-confirmed amount/currency does not match the order. The user must pay the exact order amount in the exact currency under the order_id. Do NOT retry until corrected.',\r\n PAYMENT_QUERY_FAILED: 'EVO gateway query failed (transport/timeout). Retry once after ~5s with the SAME idempotency-key.',\r\n BILLING_MODE_MISMATCH: 'The order billing_mode is not a recognized settlement mode (only monthly_settlement and pay_per_call are valid). Check the developer billing_mode; do NOT retry blindly.',\r\n INVALID_ORDER_STATE: 'The order is not in AWAITING_PAYMENT (it may already be PAID or CANCELLED). Check status via get; do NOT retry pay-order.',\r\n ORDER_NOT_FOUND: 'No order for this --order-id. Verify it is the order_id returned by create-order. Do NOT retry.',\r\n ACCOUNT_INSUFFICIENT_BALANCE: 'Settlement credit is insufficient (check via admin-cli accounts get). Direct the user to top up offline.',\r\n ACCOUNT_NOT_FOUND: 'Developer has no settlement account. Direct the user to complete contract signing.',\r\n ACCOUNT_SUSPENDED: 'The settlement account is suspended. Direct the user to contact support; do NOT retry.',\r\n PAYORDER_FAILED: 'Upstream payOrder failed after a successful deduction; the deduction was reversed and the order stays AWAITING_PAYMENT. Retry with the SAME idempotency-key after a delay.',\r\n PAYORDER_FAILED_AFTER_PAYMENT: 'EVO payment confirmed but upstream payOrder failed. The order is recoverable (the EVO payment under the order_id is preserved). Contact support for reconciliation; do NOT retry automatically.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Add a unique --idempotency-key and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'Same idempotency-key used with different parameters. Use the original parameters, or generate a NEW key.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug get` schema. Read-only, supports `--watch`. Long-running. */\r\nexport const hotelGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'get',\r\n description:\r\n 'Query a hotel order status by id; with --watch, poll until a terminal status. Confirmation from the property is asynchronous, so order_status is usually PROCESSING (2) immediately after book — poll until CONFIRMED (3)',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Our order reference (coOrderCode) returned by book (book.response.order_id)' },\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll until a terminal status, emitting one NDJSON line per update' },\r\n 'watch-interval': { type: 'int', required: false, default: 5, description: 'Seconds between polls when --watch is set' },\r\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll before giving up' },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Our order reference.' },\r\n fc_order_code: { type: 'string', description: 'Supplier order reference.' },\r\n order_status: { type: 'string', description: 'Std STRING: PROCESSING | CONFIRMED | CANCELLED | COMPLETED | INIT. There is no order_status_std field.' },\r\n order_status_code: { type: 'int', description: '2 = Processing, 3 = Confirmed, 4 = Cancelled, 5 = Completed. Provider path only; absent on the local-cache fallback.' },\r\n channel_state: { type: 'string|null', description: \"Channel-level state (e.g. 'paid' = settled).\" },\r\n hotel_confirm_no: { type: 'string|null', description: 'Property confirmation number. Populated once order_status reaches CONFIRMED (3); null while PROCESSING (2).' },\r\n hotel_name: { type: 'string|null', description: 'Hotel name.' },\r\n room_name: { type: 'string|null', description: 'Booked room type.' },\r\n check_in: { type: 'string|null', description: 'Check-in date YYYY-MM-DD.' },\r\n check_out: { type: 'string|null', description: 'Check-out date YYYY-MM-DD.' },\r\n total_amount: { type: 'float|null', description: 'Total amount in DECIMAL units.' },\r\n source: { type: 'string', description: \"'provider' (live upstream, carries order_status_code) or 'local_cache' (fallback, string status only).\" },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug get --order-id E2E1750000000',\r\n output_summary: 'Returns order_status (string) + order_status_code (int). Poll every 5s until CONFIRMED (3); hotel_confirm_no appears once confirmed.',\r\n },\r\n polling: {\r\n recommended_interval_seconds: 5,\r\n terminal_statuses: [3, 4, 5],\r\n in_progress_statuses: [2],\r\n field_availability: {\r\n hotel_confirm_no: 'Populated only after order_status reaches CONFIRMED (3). Null while PROCESSING (2).',\r\n },\r\n },\r\n error_recovery: {\r\n HOTEL_ORDER_NOT_FOUND: 'No order for this --order-id. Verify it is the order_id returned by book. Do NOT retry.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after 5s; if still failing, surface to user.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug cancel` schema. Write op (W/Y) — acknowledgement is not proof. */\r\nexport const hotelCancelSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'cancel',\r\n description:\r\n 'Cancel an entire hotel order within the cancellation policy (a cancellation fee may apply). Returns synchronously, but a successful call is acceptance only, NOT proof: poll get until order_status=CANCELLED (4). For partial-night or out-of-policy cancellation, use checkout instead',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Our order reference (coOrderCode) to cancel (book.response.order_id)' },\r\n 'fc-order-code': { type: 'string', required: true, description: 'Supplier order reference (book.response.fc_order_code)' },\r\n reason: { type: 'string', required: false, description: 'Cancellation reason' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Reuse the SAME key when retrying the same cancellation',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Cancelled order reference.' },\r\n order_status: { type: 'string', description: \"Status after the cancel request. Acceptance is NOT proof — poll get until 'CANCELLED' (order_status_code 4).\" },\r\n cancellation: {\r\n type: 'object|null',\r\n description: 'Confirmed-cancellation details (confirmed shape).',\r\n properties: {\r\n cancellation_fee: { type: 'float', description: 'Fee charged for cancellation, in DECIMAL units.' },\r\n reversal_amount: { type: 'float', description: 'Amount reversed/refunded, in DECIMAL units.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code.' },\r\n },\r\n },\r\n cancellation_fee: { type: 'float|null', description: 'Fee charged for cancellation (confirmed shape), in DECIMAL units.' },\r\n refund_amount: { type: 'float', description: 'Amount credited back to the settlement balance (paid - cancellation_fee), in DECIMAL units.' },\r\n cancel_status: { type: 'string|absent', description: \"'cancel_pending' when accepted upstream but not yet observed as CANCELLED (accepted-but-pending shape).\" },\r\n cancel_result: { type: 'unknown|absent', description: 'Upstream cancel acknowledgement (pending shape). NOT proof of cancellation — confirm via get.' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli hotel-redaug cancel --order-id E2E1750000000 --fc-order-code FC1750000000 --idempotency-key cancel-h1n2',\r\n output_summary: 'Returns the cancellation acknowledgement and any fee/refund. Then poll get until order_status=CANCELLED (4) to confirm.',\r\n },\r\n error_recovery: {\r\n CANCELLATION_NOT_ALLOWED: 'The order is outside its free/allowed cancellation window or already terminal. Do NOT retry cancel. If the user still wants out (e.g. drop some nights or request a waiver), use checkout instead.',\r\n ALREADY_CANCELLED: 'Order is already cancelled (order_status=4). Treat as success; confirm via get.',\r\n HOTEL_ORDER_NOT_FOUND: 'Verify --order-id / --fc-order-code from the book response. Do NOT retry.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after 5s with the SAME idempotency-key, then poll get to check whether the cancellation actually took effect.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Add a unique --idempotency-key derived from business intent and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'The same idempotency-key was used with different parameters. Retry with the original parameters, or generate a NEW key for the new parameters.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug checkout` schema. Write op (W/Y) — async application. */\r\nexport const hotelCheckoutSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'checkout',\r\n description:\r\n 'Request a partial check-out or an out-of-policy cancellation (drop some nights, or cancel after the free window so the property must approve). This is an APPLICATION: it returns a task_order_code synchronously, then the supplier decides asynchronously — poll get-checkout. Use cancel for a simple whole-order in-policy cancellation',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Our order reference (coOrderCode) for the URL path (book.response.order_id)' },\r\n 'fc-order-code': { type: 'string', required: true, description: 'Supplier order reference of the booking to change (book.response.fc_order_code)' },\r\n reason: { type: 'string', required: true, description: 'Why the partial check-out / out-of-policy cancellation is requested' },\r\n 'checkout-rooms': {\r\n type: 'string',\r\n required: true,\r\n description: 'Which booked rooms to check out of, taken from the book response (book.response.rooms[]). room_index and guest_name come verbatim from book — do NOT ask the user for them',\r\n constraints: 'JSON array of {room_index, guest_name, cancel_check_in_date}; else PARAM_INVALID. cancel_check_in_date is the check-in date of the night(s) being dropped (YYYY-MM-DD)',\r\n },\r\n 'refund-type': { type: 'int', required: false, default: 1, description: 'Requested refund handling (upstream refund-type code; default to the standard refund flow when unsure)' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Reuse the SAME key when retrying the same application',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Our order reference (echoes the path order_id).' },\r\n task_order_code: { type: 'string', description: 'Check-out application id. Poll get-checkout --task-order-code to track approval and refund.' },\r\n apply_status: { type: 'string|null', description: 'Initial application status (e.g. submitted / pending).' },\r\n checkout_status: { type: 'string|absent', description: \"'checkout_pending' — async; poll get-checkout for the outcome.\" },\r\n },\r\n example: {\r\n command:\r\n `agenzo-merchant-cli hotel-redaug checkout --order-id E2E1750000000 --fc-order-code FC1750000000 --reason \"guest leaving early\" --checkout-rooms '[{\"room_index\":\"1\",\"guest_name\":\"San Zhang\",\"cancel_check_in_date\":\"2026-07-05\"}]' --idempotency-key checkout-h1n2`,\r\n output_summary: 'Returns task_order_code. Poll hotel-redaug get-checkout --task-order-code <code> until the application is approved/rejected/refunded.',\r\n },\r\n error_recovery: {\r\n CHECKOUT_NOT_ALLOWED: 'The order state does not permit a check-out application (e.g. not yet confirmed, or already completed). Surface to user; do NOT retry.',\r\n HOTEL_ORDER_NOT_FOUND: 'Verify --order-id / --fc-order-code from the book response. Do NOT retry.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after 5s with the SAME idempotency-key.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Add a unique --idempotency-key derived from business intent and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'The same idempotency-key was used with different parameters. Retry with the original parameters, or generate a NEW key for the new parameters.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug get-checkout` schema. Read-only, supports `--watch`. Long-running. */\r\nexport const hotelGetCheckoutSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'get-checkout',\r\n description:\r\n 'Poll the status and refund outcome of a check-out application created by checkout. The supplier decides asynchronously; with --watch, keep polling until a terminal refund_status',\r\n flags: {\r\n 'task-order-code': { type: 'string', required: true, description: 'Check-out application id from checkout (checkout.response.task_order_code)' },\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll until a terminal status, emitting one NDJSON line per update' },\r\n 'watch-interval': { type: 'int', required: false, default: 10, description: 'Seconds between polls when --watch is set' },\r\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll before giving up' },\r\n },\r\n response: {\r\n task_order_code: { type: 'string', description: 'Check-out application id.' },\r\n refund_status: { type: 'string', description: 'Application/refund status: pending | approved | rejected | refunded.' },\r\n refund: {\r\n type: 'object|null',\r\n description: 'Final refund once approved. Populated only once refund_status is approved or refunded.',\r\n properties: {\r\n amount: { type: 'float', description: 'Refunded amount in DECIMAL units.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code.' },\r\n },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug get-checkout --task-order-code TASK1750000000',\r\n output_summary: 'Returns refund_status. Poll every 10s until approved/rejected/refunded; refund appears once approved.',\r\n },\r\n polling: {\r\n recommended_interval_seconds: 10,\r\n terminal_statuses: ['approved', 'rejected', 'refunded'],\r\n in_progress_statuses: ['pending'],\r\n field_availability: {\r\n refund: 'Populated only once refund_status is approved or refunded.',\r\n },\r\n },\r\n error_recovery: {\r\n CHECKOUT_TASK_NOT_FOUND: 'Verify --task-order-code from the checkout response. Do NOT retry.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after 10s.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug list-orders` schema. Read-only. */\r\nexport const hotelListOrdersSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'list-orders',\r\n description: 'List the developer\\'s hotel orders with optional status filtering and pagination',\r\n flags: {\r\n status: { type: 'string', required: false, description: 'Filter by order status (e.g. PROCESSING / CONFIRMED / CANCELLED / COMPLETED). Omitted entirely when absent (all statuses)' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n page: { type: 'int', required: false, default: 1, description: 'Page number', constraints: '>= 1' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page', constraints: '>= 1 (platform caps at 100 server-side)' },\r\n },\r\n response: {\r\n orders: {\r\n type: 'array',\r\n description: 'List of hotel orders (slim list-item shape).',\r\n items: {\r\n order_id: { type: 'string', description: 'Our order reference.' },\r\n member_id: { type: 'string|null', description: 'End-user this order is attributed to; null when unattributed' },\r\n fc_order_code: { type: 'string', description: 'Supplier order reference.' },\r\n status: { type: 'string', description: 'Current order status (string).' },\r\n provider: { type: 'string', description: \"Service provider ('redaug').\" },\r\n check_in: { type: 'string|null', description: 'Check-in date YYYY-MM-DD.' },\r\n check_out: { type: 'string|null', description: 'Check-out date YYYY-MM-DD.' },\r\n room_num: { type: 'int|null', description: 'Number of rooms booked.' },\r\n price_amount: { type: 'float|null', description: 'Total price in DECIMAL units (NOT cents).' },\r\n price_currency: { type: 'string', description: 'ISO 4217 currency code.' },\r\n payment_status: { type: 'string', description: \"Payment status (e.g. 'ON_ACCOUNT').\" },\r\n hotel_confirm_no: { type: 'string|null', description: 'Property confirmation number (once confirmed).' },\r\n cancellation_fee: { type: 'float|null', description: 'Cancellation fee for cancelled orders; null otherwise.' },\r\n refund_amount: { type: 'float|null', description: 'Amount refunded on cancellation/checkout; null otherwise.' },\r\n created_at: { type: 'string', description: 'Order creation time (ISO 8601).' },\r\n updated_at: { type: 'string', description: 'Last update time (ISO 8601).' },\r\n },\r\n },\r\n total: { type: 'int', description: 'Total matching orders.' },\r\n page: { type: 'int', description: 'Current page.' },\r\n page_size: { type: 'int', description: 'Items per page.' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug list-orders --status CONFIRMED --page 1 --page-size 10',\r\n output_summary: 'Returns a paginated list of hotel orders with status, dates and amount info.',\r\n },\r\n error_recovery: {\r\n INTERNAL_ERROR: 'Transient backend error. Retry once after a short delay.',\r\n PARAM_INVALID: 'Ensure --page / --page-size are positive integers, then retry.',\r\n },\r\n};\r\n\r\n// ============================================================\r\n// Hotel-redaug Addendum A verb schemas (4 new read-only verbs)\r\n// ============================================================\r\n\r\n/** `hotel-redaug find-destination` schema. Read-only. */\r\nexport const hotelFindDestinationSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'find-destination',\r\n description:\r\n 'Search for a destination by keyword (city, landmark, airport, etc.). Returns a list of destinations whose destination_id can be passed to search --destination-id or hotel-filters --destination-id',\r\n flags: {\r\n keyword: { type: 'string', required: true, description: 'Destination search keyword (city name, landmark, airport code, etc.)' },\r\n 'data-type': { type: 'string', required: false, description: 'Optional data type filter to narrow result categories' },\r\n },\r\n response: {\r\n destinations: {\r\n type: 'array',\r\n description: 'Matching destinations. Empty when nothing matches the keyword (rendered as a successful empty result, not an error).',\r\n items: {\r\n destination_id: { type: 'string|null', description: 'Opaque destination identifier. Pass to search --destination-id or hotel-filters --destination-id.' },\r\n type: { type: 'string|int|null', description: 'Destination type (city, landmark, airport, etc.).' },\r\n name: { type: 'string|null', description: 'Destination name.' },\r\n city_name: { type: 'string|null', description: 'City name.' },\r\n city_code: { type: 'string|null', description: 'City code.' },\r\n country_name: { type: 'string|null', description: 'Country name.' },\r\n lat: { type: 'float|null', description: 'Latitude (can also be used with search --lat).' },\r\n lng: { type: 'float|null', description: 'Longitude (can also be used with search --lng).' },\r\n },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug find-destination --keyword \"Shanghai\"',\r\n output_summary: 'Returns destinations[]. Use destinations[].destination_id in search --destination-id or hotel-filters --destination-id.',\r\n },\r\n error_recovery: {\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n PARAM_INVALID: 'Ensure --keyword is non-empty, then retry.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug hotel-filters` schema. Read-only. */\r\nexport const hotelFiltersSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'hotel-filters',\r\n description:\r\n 'Get available filter options (stars, brands, groups, labels, sub-categories, hotel/room facilities) for a location. Each item\\'s code maps directly to the corresponding search filter flag (e.g. hotel_facilities[].code → search --hotel-facility-codes)',\r\n flags: {\r\n 'destination-id': { type: 'string', required: 'conditional', description: 'Destination ID (alternative to --lat/--lng)', constraints: 'Exactly one location branch: --destination-id XOR (--lat + --lng)' },\r\n lat: { type: 'float', required: 'conditional', description: 'Latitude (-90 to 90, requires --lng)', constraints: '-90 to 90; mutually exclusive with --destination-id' },\r\n lng: { type: 'float', required: 'conditional', description: 'Longitude (-180 to 180, requires --lat)', constraints: '-180 to 180; mutually exclusive with --destination-id' },\r\n distance: { type: 'int', required: false, default: 20, description: 'Search radius in kilometers' },\r\n },\r\n response: {\r\n stars: { type: 'array', description: 'Star rating options [{code, name, count}]. code → search --star.' },\r\n brands: { type: 'array', description: 'Hotel brand options [{code, name, count}]. code → search --hotel-brand-codes.' },\r\n groups: { type: 'array', description: 'Hotel group options [{code, name, count}].' },\r\n labels: { type: 'array', description: 'Hotel label options [{code, name, count}]. code → search --hotel-label-ids.' },\r\n sub_categories: { type: 'array', description: 'Hotel sub-category options [{code, name, count}]. code → search --hotel-sub-category-ids.' },\r\n hotel_facilities: { type: 'array', description: 'Hotel facility options [{code, name, count, type}]. code → search --hotel-facility-codes.' },\r\n room_facilities: { type: 'array', description: 'Room facility options [{code, name, count, type}]. code → search --room-facility-codes.' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug hotel-filters --destination-id D12345',\r\n output_summary: 'Returns filter groups. Use the code values in search filter flags (e.g. search --hotel-facility-codes code1,code2).',\r\n },\r\n error_recovery: {\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n PARAM_INVALID: 'Supply exactly one location branch (--destination-id OR --lat/--lng). Coordinates must be within valid ranges.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug list-cities` schema. Read-only. */\r\nexport const hotelListCitiesSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'list-cities',\r\n description:\r\n 'List cities available for hotel booking in a given country. Each city provides a destination_id (for search --destination-id) and/or lat/lng coordinates (for search --lat/--lng)',\r\n flags: {\r\n country: { type: 'string', required: true, description: 'ISO country code (e.g. CN, US, TH)' },\r\n },\r\n response: {\r\n cities: {\r\n type: 'array',\r\n description: 'Cities for the country. Empty when no cities are available (rendered as success, not an error).',\r\n items: {\r\n city_code: { type: 'string', description: 'City code.' },\r\n city_name: { type: 'string', description: 'City name.' },\r\n destination_id: { type: 'string|null', description: 'Destination ID for this city. Pass to search --destination-id.' },\r\n province_code: { type: 'string|null', description: 'Province code.' },\r\n province_name: { type: 'string|null', description: 'Province name.' },\r\n country_code: { type: 'string|null', description: 'Country code.' },\r\n country_name: { type: 'string|null', description: 'Country name.' },\r\n lat: { type: 'float|null', description: 'Latitude (can be used with search --lat).' },\r\n lng: { type: 'float|null', description: 'Longitude (can be used with search --lng).' },\r\n time_zone: { type: 'string|null', description: 'Time zone identifier.' },\r\n popularity_score: { type: 'float|null', description: 'Popularity score for sorting/ranking.' },\r\n },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug list-cities --country CN',\r\n output_summary: 'Returns cities[]. Use cities[].destination_id in search --destination-id, or cities[].lat/lng in search --lat/--lng.',\r\n },\r\n error_recovery: {\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n PARAM_INVALID: 'Ensure --country is a non-empty ISO country code, then retry.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug hotel-detail` schema. Read-only. */\r\nexport const hotelDetailSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'hotel-detail',\r\n description:\r\n \"Get detailed information about a specific hotel including facilities, images, location, check-in/check-out times. Use to show the user hotel details before quoting/booking. hotel_id is stable but hotel_name/room_name may change upstream without notice. special_instructions (when requested via --settings hotelTextPolicies) MUST be shown to the user — the upstream data provider does not accept liability for booking issues caused by it not being displayed.\",\r\n flags: {\r\n 'hotel-id': { type: 'string', required: true, description: 'Hotel ID from search results (search.response.hotels[].hotel_id)' },\r\n 'with-images': { type: 'bool', required: false, default: true, description: 'Include hotel images in the response (set false to reduce payload)' },\r\n settings: {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Optional on-demand upstream fields, comma-separated or JSON array — request only what you need: hotelFacilityNew, breakfast, importantNotices, parking, chargingParking, hotelCertificates, comment, hotelMeetingInfos, hotelVideoInfos, hotelTextPolicies (includes special_instructions), hotelStructuredPolicies.childPolicy, hotelStructuredPolicies.extraBedPolicy, hotelStructuredPolicies.petPolicy. Omitted codes are NOT returned by upstream (an upstream requirement, not a display choice). Pass hotelTextPolicies to get special_instructions.',\r\n },\r\n },\r\n response: {\r\n hotel_id: { type: 'string|int', description: 'Hotel identifier.' },\r\n hotel_name: { type: 'string|null', description: 'Hotel name.' },\r\n hotel_eng_name: { type: 'string|null', description: 'English hotel name.' },\r\n star: { type: 'int|null', description: 'Star rating.' },\r\n address: { type: 'string|null', description: 'Hotel address.' },\r\n intro: { type: 'string|null', description: 'Hotel introduction/description.' },\r\n appearance_image: { type: 'string|null', description: 'Main appearance image URL.' },\r\n telephone: { type: 'string|null', description: 'Hotel telephone number.' },\r\n country_name: { type: 'string|null', description: 'Country name.' },\r\n province_name: { type: 'string|null', description: 'Province name.' },\r\n city_name: { type: 'string|null', description: 'City name.' },\r\n district_name: { type: 'string|null', description: 'District name.' },\r\n business_name: { type: 'string|null', description: 'Business area name.' },\r\n lat: { type: 'float|null', description: 'Latitude.' },\r\n lng: { type: 'float|null', description: 'Longitude.' },\r\n check_in_time: { type: 'string|null', description: 'Hotel check-in time.' },\r\n check_out_time: { type: 'string|null', description: 'Hotel check-out time.' },\r\n room_num: { type: 'int|null', description: 'Number of rooms available.' },\r\n facilities: {\r\n type: 'array',\r\n description: 'Hotel facilities list.',\r\n items: {\r\n name: { type: 'string', description: 'Facility name.' },\r\n type: { type: 'string|null', description: 'Facility type/category.' },\r\n },\r\n },\r\n images: {\r\n type: 'array',\r\n description: 'Hotel-level images. Empty array when --with-images false.',\r\n items: {\r\n url: { type: 'string', description: 'Image URL.' },\r\n is_main: { type: 'bool', description: 'Whether this is the main image.' },\r\n type: { type: 'int|null', description: 'Image type/category.' },\r\n },\r\n },\r\n rooms: {\r\n type: 'array',\r\n description: \"Room types with STATIC info only (area/floor/beds/max occupancy/images) — NOT live rates. room_id is the SAME id space as quote's roomItems[].roomId, so relate a room here to its live rate/price/product_token by matching room_id to quote's rates. ALWAYS use quote for price/availability/product_token; this verb never has them. Present this alongside quote's rate options so the user sees what the room actually looks like (area, beds, photos) before picking a rate, not just the one-line room_name from quote.\",\r\n items: {\r\n room_id: { type: 'int|string|null', description: \"Room type id. Matches quote's roomItems[].roomId — use to relate this room's detail to a specific quoted rate.\" },\r\n room_name: { type: 'string|null', description: 'Room type name.' },\r\n area_sqm: { type: 'string|null', description: 'Room area (upstream unit, commonly square meters), as a string.' },\r\n floor: { type: 'string|null', description: 'Floor(s) this room type is on (may be a range, e.g. \"10-15\").' },\r\n max_person: { type: 'int|null', description: 'Max total occupancy.' },\r\n max_adults: { type: 'int|null', description: 'Max adults.' },\r\n max_child: { type: 'int|null', description: 'Max children.' },\r\n allow_smoking: { type: 'bool|null', description: 'Whether smoking is allowed in this room type.' },\r\n beds: {\r\n type: 'array',\r\n description: 'Bed configuration for the room area.',\r\n items: {\r\n name: { type: 'string|null', description: 'Bed type name (e.g. \"King Bed\").' },\r\n width: { type: 'string|null', description: 'Bed width, upstream unit.' },\r\n num: { type: 'string|null', description: 'Number of this bed type.' },\r\n },\r\n },\r\n living_room_beds: {\r\n type: 'array',\r\n description: 'Bed configuration for a separate living-room area, when the room type has one. Same shape as beds.',\r\n items: {\r\n name: { type: 'string|null', description: 'Bed type name.' },\r\n width: { type: 'string|null', description: 'Bed width, upstream unit.' },\r\n num: { type: 'string|null', description: 'Number of this bed type.' },\r\n },\r\n },\r\n images: {\r\n type: 'array',\r\n description: 'Photos of this specific room type. Empty when --with-images false, or when upstream has none for this room.',\r\n items: {\r\n url: { type: 'string', description: 'Image URL.' },\r\n is_main: { type: 'bool', description: 'Whether this is the main image for the room.' },\r\n type: { type: 'int|null', description: 'Image type/category.' },\r\n },\r\n },\r\n },\r\n },\r\n comment: {\r\n type: 'array',\r\n description: \"Guest review scores per channel. Empty unless --settings included 'comment'.\",\r\n items: {\r\n channel: { type: 'string|null', description: 'Review source channel (e.g. EPS).' },\r\n average_score: { type: 'float|null', description: 'Average review score for that channel.' },\r\n },\r\n },\r\n hotel_certificates: {\r\n type: 'array',\r\n description: \"Hotel business certificates/qualifications, when the property has any. Empty unless --settings included 'hotelCertificates' (and the property may simply have none).\",\r\n items: {\r\n unify_code: { type: 'string|null', description: 'Unified business registration code.' },\r\n certification_name: { type: 'string|null', description: 'Certificate name.' },\r\n file_url: { type: 'string|null', description: 'Certificate image URL.' },\r\n },\r\n },\r\n hotel_text_policies: {\r\n type: 'array',\r\n description: \"Free-text hotel policies keyed by code (hotelPolicy/instructions/specialInstructions/mandatoryFees/optionalFees/cleanAndSafety/importantNotices/ageLimit/checkInCheckOut). Empty unless --settings included 'hotelTextPolicies'. special_instructions below is also pulled from this same data, surfaced separately because it MUST be shown to the user.\",\r\n items: {\r\n code: { type: 'string|null', description: 'Policy code, e.g. \"specialInstructions\".' },\r\n code_name: { type: 'string|null', description: 'Display name of the policy code (e.g. \"特别入住说明\").' },\r\n text: { type: 'string|null', description: 'Policy text (may contain HTML list markup from upstream).' },\r\n },\r\n },\r\n hotel_structured_policies: {\r\n type: 'object|null',\r\n description: \"Structured child/extra-bed/pet policies (raw upstream shape, snake_cased). null unless --settings included the relevant hotelStructuredPolicies.* code(s).\",\r\n properties: {\r\n child_policy: { type: 'object|null', description: 'Child stay/breakfast policy.' },\r\n extra_bed_policy: { type: 'object|null', description: 'Extra-bed charge policy by age range.' },\r\n pet_policy: { type: 'object|null', description: 'Pet/service-animal policy.' },\r\n },\r\n },\r\n special_instructions: {\r\n type: 'string|null',\r\n description: \"IMPORTANT: the property's 'special check-in instructions' (upstream code specialInstructions, distinct from the general 'instructions' code). The Agent/caller MUST surface this to the user in the booking UI when present — the upstream data provider does not accept liability for booking problems caused by this not being displayed. Only populated when --settings included 'hotelTextPolicies'; null otherwise (does not mean the hotel has none — it means it wasn't requested).\",\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug hotel-detail --hotel-id 10583772',\r\n output_summary: \"Returns full hotel details including facilities, hotel images, AND rooms[] (per-room-type static info + photos). Use to present both the hotel and its room types before quoting — rooms[].room_id matches quote's roomItems[].roomId so the two can be shown together.\",\r\n },\r\n error_recovery: {\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n PARAM_INVALID: 'Ensure --hotel-id is a non-empty string, then retry.',\r\n HOTEL_NOT_FOUND: 'The hotel is no longer available from the supplier (no matching hotel node in the upstream response). Do not retry with the same hotel_id — drop it from any local cache/mapping and re-search.',\r\n },\r\n};\r\n\r\n// ============================================================\r\n// Unified cross-provider orders verb schemas (\"orders\" noun)\r\n// ============================================================\r\n//\r\n// `orders` is the read-only index spanning ride, hotel, flight, and future\r\n// providers. Use it for generic order history and common filters; use a\r\n// domain-specific list command only when provider-specific columns are needed.\r\n\r\nexport const ORDERS_NOUN = 'orders';\r\n\r\n/** `orders list` schema — cross-provider order list (`GET /orders`). Read-only. */\r\nexport const unifiedOrdersListSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: ORDERS_NOUN,\r\n verb: 'list',\r\n description:\r\n 'List orders across ALL providers (ride + hotel + flight) with common filters and offset/cursor pagination. Use domain-specific list-orders only for provider-specific fields.',\r\n flags: {\r\n 'order-type': { type: 'string', required: false, description: 'Legacy single order type: ride | hotel | flight' },\r\n 'order-types': { type: 'string', required: false, description: 'Comma-separated order types: ride,hotel,flight' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n status: { type: 'string', required: false, description: 'Legacy single normalized status: PENDING | CONFIRMED | COMPLETED | CANCELLED | FAILED' },\r\n statuses: { type: 'string', required: false, description: 'Comma-separated normalized statuses' },\r\n 'created-from': { type: 'string', required: false, description: 'ISO 8601 created-at lower bound (inclusive)' },\r\n 'created-to': { type: 'string', required: false, description: 'ISO 8601 created-at upper bound (exclusive)' },\r\n cursor: { type: 'string', required: false, description: 'Opaque cursor returned by the previous page' },\r\n page: { type: 'int', required: false, default: 1, description: 'Legacy 1-based page number', constraints: '>= 1' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page', constraints: '1-100' },\r\n },\r\n response: {\r\n orders: {\r\n type: 'array',\r\n description: 'Slim cross-provider index items. Call `orders get` for business-specific detail.',\r\n items: {\r\n order_id: { type: 'string', description: 'Order id (rio_..., hho_..., or ffo_...). Pass to `orders get`.' },\r\n member_id: { type: 'string|null', description: 'Attributed end-user id; null when unattributed' },\r\n order_type: { type: 'string', description: 'ride | hotel | flight' },\r\n status: { type: 'string', description: 'Original provider-domain status for display' },\r\n unified_status: { type: 'string', description: 'PENDING | CONFIRMED | COMPLETED | CANCELLED | FAILED' },\r\n amount: { type: 'float|null', description: 'Order amount in decimal currency units' },\r\n currency: { type: 'string|null', description: 'ISO 4217 currency code' },\r\n created_at: { type: 'string|null', description: 'ISO 8601 datetime' },\r\n updated_at: { type: 'string|null', description: 'ISO 8601 datetime' },\r\n },\r\n },\r\n total: { type: 'int', description: 'Total matching orders across all providers' },\r\n page: { type: 'int', description: 'Legacy current page' },\r\n page_size: { type: 'int', description: 'Items per page' },\r\n next_cursor: { type: 'string|null', description: 'Opaque cursor for the next page; null at the end' },\r\n has_more: { type: 'bool', description: 'Whether another page is available' },\r\n applied_filters: { type: 'object', description: 'Normalized filters applied by the platform' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli orders list --order-types flight,hotel --created-from 2026-07-01T00:00:00Z --page-size 20',\r\n output_summary: 'Returns ride, hotel, and flight orders with stable pagination metadata.',\r\n },\r\n error_recovery: {\r\n INVALID_REQUEST: 'Fix invalid type/status/date/cursor filters and retry.',\r\n INTERNAL_ERROR: 'Transient backend error. Retry once after a short delay.',\r\n PARAM_INVALID: 'Fix conflicting or invalid CLI options, then retry.',\r\n },\r\n};\r\n\r\n/** `orders get` schema — cross-provider order detail (`GET /orders/{id}`). Read-only. */\r\nexport const unifiedOrdersGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: ORDERS_NOUN,\r\n verb: 'get',\r\n description:\r\n 'Get a ride, hotel, or flight order detail by id. The platform resolves order_id to the owning domain and returns that domain detail shape.',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Order id from `orders list` (rio_..., hho_..., or ffo_...)' },\r\n },\r\n response: {\r\n '(varies by order_type)': {\r\n type: 'object',\r\n description:\r\n 'Delegated ride, hotel, or flight detail. Treat the result as an opaque domain object and surface the returned fields.',\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli orders get --order-id ffo_01K...',\r\n output_summary: \"Returns the order's provider-domain detail.\",\r\n },\r\n error_recovery: {\r\n ORDER_NOT_FOUND: 'The order_id does not exist or does not belong to this developer/org. Verify the id from `orders list`.',\r\n INTERNAL_ERROR: \"The order's provider detail lookup is temporarily unavailable. Retry once after a short delay.\",\r\n },\r\n};\r\n\r\n/**\r\n * `orders pay-batch` schema — 行程聚合支付:以**一份支付凭证**对一批订单\r\n * (`order_ids[]`,可混合 `hho_`/`ffo_`/`rio_` 三域)一次结算合计总额。Write op (W/Y)。\r\n *\r\n * 这是逻辑写工具名 `orders__aggregate__pay-batch` 的物理落点(`POST /orders/pay-batch`):\r\n * 编排层 trip-aggregate schema 的 `pay-orders` write verb 经 `UniversalGateway` 调用它,\r\n * **只在唯一一次二次确认门通过后执行、绝不暴露给 LLM**。金额取各订单锁单落库的权威价、由\r\n * 后端求和——**调用方不传各订单金额**。凭证按双轨二选一或都不带(月结 / 平台默认选卡):\r\n * 轨 A `--payment-token-id`(以合计总额created、`external_transaction_id` 绑定到本次\r\n * payment_group 的网络令牌,银联/Visa 一次 passkey);轨 B `--payment-method-id`(EVO\r\n * 绑卡一次 3DS)。声明风格对齐既有写 verb(`hotel-redaug pay-order` / `ride-elife pay-order`)。\r\n */\r\nexport const ordersPayBatchSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: ORDERS_NOUN,\r\n verb: 'pay-batch',\r\n description:\r\n 'Settle a batch of orders (may mix ride/hotel/flight — hho_/ffo_/rio_) in ONE aggregate payment via a single payment credential. Physical landing point of the logical write tool orders__aggregate__pay-batch, invoked by the trip-aggregate pay-orders write verb through UniversalGateway (executed only after the single confirmation gate; never exposed to the LLM). Amounts are NOT passed here — the platform sums each order\\'s locked authoritative price. Provide the aggregate total via one rail: --payment-token-id (轨A: network-token minted for the aggregate total, external_transaction_id bound to this payment_group — one UnionPay/Visa passkey) OR --payment-method-id (轨B: EVO bound card — one 3DS challenge); both may be omitted (monthly_settlement / platform default card). On EVO cardholder authentication the response is AUTHENTICATION_REQUIRED with a three_ds_url + merchant_trans_id; finish it out-of-band, then an idempotent replay settles. On success the batch becomes settled / partially_settled (upstream-confirmation-failed orders are refunded). Supports --watch to poll until a terminal batch status.',\r\n flags: {\r\n 'order-ids': {\r\n type: 'string',\r\n required: true,\r\n description:\r\n 'Ordered order ids to settle together — comma-separated (hho_1,ffo_2,rio_3) or a JSON array ([\"hho_1\",\"ffo_2\"]). May mix hho_/ffo_/rio_ domains. Amounts come from each order\\'s locked authoritative price (NOT passed here).',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n '[轨A] Network-token id (UnionPay/Visa) minted for the aggregate total with external_transaction_id bound to this payment_group (direct-charge main path). Mutually exclusive with --payment-method-id; both may be omitted for monthly_settlement / platform default.',\r\n },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n '[轨B] EVO bound-card id to settle the aggregate total via one 3DS challenge (explicit/fallback rail). Mutually exclusive with --payment-token-id.',\r\n },\r\n 'evo-explicit': {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description:\r\n '[轨B 硬门槛] Explicit opt-in to settle via the EVO bound-card rail. Set true ONLY when the user explicitly chose EVO; forwarded to the body as evo_explicit=true. Omit on the payment-token-id direct-charge path.',\r\n },\r\n 'payment-group-id': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Optional caller-pre-generated payment group id; omit to let the platform generate one. The whole batch is associated with this group for cross-provider reconciliation.',\r\n },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description:\r\n 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. The SAME key + the SAME ordered order_ids replays as the same batch (dedup re-check, no double charge); any change to order_ids yields a new batch.',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n watch: {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description:\r\n 'Poll until a terminal batch status (settled / partially_settled / failed) or timeout, emitting one NDJSON line per poll. Non-terminal states (authorizing/capturing, AUTHENTICATION_REQUIRED) keep polling — after the user finishes 3DS out-of-band, the next idempotent replay settles.',\r\n },\r\n // watch 默认值与 pay-batch.ts 的 DEFAULT_PAY_BATCH_WATCH_* 常量一致;此处内联字面量\r\n // 以避免 verb-schema.ts ↔ pay-batch.ts 循环依赖(pay-batch.ts 反向依赖本模块的 schema)。\r\n 'watch-interval': {\r\n type: 'int',\r\n required: false,\r\n default: 5,\r\n description: 'Seconds between polls when --watch is set',\r\n },\r\n 'watch-timeout': {\r\n type: 'int',\r\n required: false,\r\n default: 300,\r\n description: 'Max seconds to poll before giving up',\r\n },\r\n },\r\n response: {\r\n payment_group_id: { type: 'string', description: 'The payment group this batch settled under (echoes --payment-group-id when supplied, else server-generated).' },\r\n status: { type: 'string', description: 'settled | partially_settled | failed | AUTHENTICATION_REQUIRED (3DS challenge body).' },\r\n currency: { type: 'string', description: 'ISO 4217 currency of the aggregate settlement (all orders share one currency).' },\r\n total_amount: { type: 'float', description: \"Aggregate total in DECIMAL units = sum of each order's authoritative price (computed by the platform, NOT sent by the caller).\" },\r\n orders: {\r\n type: 'array',\r\n description: 'Per-order final result after upstream confirmation.',\r\n items: {\r\n order_id: { type: 'string', description: 'hho_/ffo_/rio_ order id.' },\r\n status: { type: 'string', description: 'confirmed | refunded | failed.' },\r\n amount: { type: 'float', description: \"That order's authoritative amount.\" },\r\n refunded_amount: { type: 'float', description: 'Amount refunded when upstream confirmation failed for this order.' },\r\n },\r\n },\r\n three_ds_url: { type: 'string', description: '[AUTHENTICATION_REQUIRED only] EVO 3DS challenge URL — complete out-of-band, then replay to settle.' },\r\n merchant_trans_id: { type: 'string', description: '[AUTHENTICATION_REQUIRED only] merchant trans id of the batch preauth.' },\r\n amount: { type: 'float', description: '[AUTHENTICATION_REQUIRED only] challenge amount = aggregate total.' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli orders pay-batch --order-ids hho_01K...,ffo_01K...,rio_01K... --payment-token-id ntk_01J2ABC --idempotency-key trip-pay-1',\r\n output_summary:\r\n 'Settles all listed orders in one charge (banks/EVO see one transaction). Returns {payment_group_id, status, total_amount, currency, orders[]}. Use --watch to poll until settled / partially_settled / failed; upstream-confirmation-failed orders are refunded.',\r\n },\r\n error_recovery: {\r\n PARAM_INVALID: 'Fix --order-ids (a non-empty comma-separated list or JSON array of order ids) and ensure --idempotency-key is present, then retry.',\r\n ORDER_NOT_PAYABLE: 'One of the order_ids is not in AWAITING_PAYMENT (the error names the specific order_id). Remove/replace it and retry with a NEW idempotency-key.',\r\n CURRENCY_MISMATCH: 'The batch mixes currencies — orders in one pay-batch must share a single currency. Split by currency and settle each group separately.',\r\n TOKEN_ORDER_MISMATCH: 'The token external_transaction_id is not bound to this payment_group. Mint a token for the aggregate total bound to THIS payment_group_id and retry; no funds moved.',\r\n AUTHENTICATION_REQUIRED: 'EVO requires cardholder 3DS: open three_ds_url, finish authentication, then replay pay-batch with the SAME idempotency-key (or use --watch to poll automatically).',\r\n },\r\n};\r\n\r\n/** `orders get-payment-group` schema. Read-only status of one pay-batch settlement. */\r\nexport const ordersGetPaymentGroupSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: ORDERS_NOUN,\r\n verb: 'get-payment-group',\r\n description: 'Get the status of an aggregate settlement created by `orders pay-batch` (read-only; never re-sends the payment)',\r\n flags: {\r\n 'payment-group-id': { type: 'string', required: true, description: 'payment_group_id returned by `orders pay-batch` (1-64 chars)' },\r\n },\r\n response: {\r\n payment_group_id: { type: 'string', description: 'The payment group' },\r\n status: { type: 'string', description: 'settled | partially_settled | failed | uncertain' },\r\n currency: { type: 'string', description: 'ISO 4217 currency of the aggregate settlement' },\r\n total_amount: { type: 'float', description: 'Aggregate total in DECIMAL units' },\r\n per_order: {\r\n type: 'array',\r\n description: 'Per-order outcome, same shape as pay-batch',\r\n items: {\r\n order_id: { type: 'string', description: 'Order id' },\r\n domain: { type: 'string', description: 'hotel | flight | ride' },\r\n status: { type: 'string', description: 'confirmed | refunded | failed' },\r\n amount: { type: 'float', description: 'Authoritative order amount (decimal)' },\r\n refunded_amount: { type: 'float', description: 'Amount refunded when upstream confirmation failed' },\r\n },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli orders get-payment-group --payment-group-id pg_...',\r\n output_summary: 'Returns the batch status and per-order results; use it instead of replaying pay-batch to check progress.',\r\n },\r\n error_recovery: {\r\n PARAM_INVALID: 'Pass the payment_group_id exactly as pay-batch returned it (1-64 chars).',\r\n },\r\n};\r\n\r\n// ============================================================\r\n// flight-flink verb schemas (§4.4.1.3) — one per verb.\r\n// Amounts are integers (upstream convention). gender/id_type are STRINGS.\r\n// ============================================================\r\n\r\n/** Build a compact flight VerbSchema (keeps the 18 entries readable). */\r\nfunction flightSchema(\r\n verb: string,\r\n description: string,\r\n flags: Record<string, FlagSchema>,\r\n response: Record<string, unknown>,\r\n example: ExampleSchema,\r\n extra: Partial<Pick<VerbSchema, 'error_recovery' | 'polling'>> = {},\r\n): VerbSchema {\r\n return { cli: CLI_NAME, noun: FLIGHT_NOUN, verb, description, flags, response, example, ...extra };\r\n}\r\n\r\nexport const flightFindAirportSchema = flightSchema(\r\n 'find-airport',\r\n 'Resolve free-text into city/airport candidates (city hits carry children airports).',\r\n { keyword: { type: 'string', required: true, description: 'Free-text place/airport/city name.' } },\r\n { airports: { type: 'array', description: 'City/airport candidates with IATA codes.' } },\r\n { command: 'agenzo-merchant-cli flight-flink find-airport --keyword beijing', output_summary: 'Returns candidate city/airport IATA codes.' },\r\n);\r\n\r\nexport const flightListAirportsSchema = flightSchema(\r\n 'list-airports',\r\n 'Paged airport dictionary (requires page + page-size).',\r\n {\r\n page: { type: 'int', required: false, default: 1, description: '1-based page.' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page (1-100).' },\r\n keyword: { type: 'string', required: false, description: 'Optional name filter.' },\r\n },\r\n { airports: { type: 'array', description: 'Airport records.' } },\r\n { command: 'agenzo-merchant-cli flight-flink list-airports --page 1 --page-size 20', output_summary: 'Paged airport dictionary.' },\r\n);\r\n\r\nexport const flightListAirlinesSchema = flightSchema(\r\n 'list-airlines',\r\n 'Paged airline dictionary (requires page + page-size).',\r\n {\r\n page: { type: 'int', required: false, default: 1, description: '1-based page.' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page (1-100).' },\r\n keyword: { type: 'string', required: false, description: 'Optional name filter.' },\r\n },\r\n { airlines: { type: 'array', description: 'Airline records.' } },\r\n { command: 'agenzo-merchant-cli flight-flink list-airlines --page 1 --page-size 20', output_summary: 'Paged airline dictionary.' },\r\n);\r\n\r\nexport const flightListNationalitiesSchema = flightSchema(\r\n 'list-nationalities',\r\n 'Nationality list (no params).',\r\n {},\r\n { nationalities: { type: 'array', description: 'Nationality codes/names.' } },\r\n { command: 'agenzo-merchant-cli flight-flink list-nationalities', output_summary: 'Nationality list.' },\r\n);\r\n\r\nexport const flightSearchSchema = flightSchema(\r\n 'search',\r\n 'Search flights (one-way/round-trip/multi-city). journeys always carries all legs; for round-trip/multi-city relay the CHOSEN candidate\\'s next_journey_ids into --journey-id until is_final_leg is true — only then do offers carry a real priceKey (product_token).',\r\n {\r\n 'trip-type': { type: 'int', required: true, description: '1=one-way, 2=round-trip, 3=multi-city.' },\r\n journeys: { type: 'json', required: true, description: 'JSON array of {date, origin, destination, origin_type?, destination_type?}. origin/destination are IATA 3-letter codes; *_type 1=city, 2=airport. Carries ALL legs on every call, including relay calls.' },\r\n 'cabin-class': { type: 'string', required: false, default: 'economy', description: 'economy | premium_economy | business | first.' },\r\n 'adult-num': { type: 'int', required: false, default: 1, description: 'Adults (1-9).' },\r\n 'child-num': { type: 'int', required: false, default: 0, description: 'Children (0-9).' },\r\n 'infant-num': { type: 'int', required: false, default: 0, description: 'Infants (0-9).' },\r\n airline: { type: 'string', required: false, description: 'Airline 2-letter code filter.' },\r\n 'transfer-number': { type: 'int', required: false, default: 0, description: '0=any,1=direct,2=1 stop,3=2 stops.' },\r\n 'journey-id': { type: 'json', required: false, description: 'Relay key: copy offers[].next_journey_ids VERBATIM from the candidate the user chose in the previous search. Omit on the first search. Do not build it from the top-level journey_ids, and never send more ids than there are legs (rejected).' },\r\n },\r\n {\r\n offers: { type: 'array', description: 'Candidates for the current leg. Each has next_journey_ids (relay key), journey_id, segment_ids, paired_segment_ids, total_sale_price (WHOLE-TRIP total), currency, cabin_class, baggage/refund/change_rules, and product_token when price_key_ready.' },\r\n price_key_ready: { type: 'bool', description: 'True only when all legs are selected (final search).' },\r\n current_leg: { type: 'int', description: 'Which leg this result is choosing (1-based).' },\r\n total_legs: { type: 'int', description: 'Total legs in the trip.' },\r\n is_final_leg: { type: 'bool', description: 'True when these offers can be bookable. False means relay another round with the chosen candidate\\'s next_journey_ids.' },\r\n journey_ids: { type: 'array', description: 'DEPRECATED for relay: flattened across all candidates, so it cannot tell you which id belongs to which. Relay offers[].next_journey_ids instead.' },\r\n },\r\n { command: \"agenzo-merchant-cli flight-flink search --trip-type 1 --journeys '[{\\\"date\\\":\\\"2026-08-01\\\",\\\"origin\\\":\\\"PEK\\\",\\\"destination\\\":\\\"SHA\\\"}]'\", output_summary: 'Returns offers[]; use a product_token where price_key_ready is true, then verify. Round-trip: the first search has is_final_leg=false and no product_token — relay the chosen candidate\\'s next_journey_ids to get bookable offers.' },\r\n);\r\n\r\nexport const flightMoreOffersSchema = flightSchema(\r\n 'more-offers',\r\n 'More fare offers for a priceKey (carried by product_token).',\r\n { 'product-token': { type: 'string', required: true, description: 'Opaque token from search.' } },\r\n {\r\n offers: { type: 'array', description: 'Additional fare candidates for the same flight (same shape as search offers[]); all are bookable.' },\r\n current_leg: { type: 'int', description: 'Always 1 — alternative fares for one chosen flight, not a relay round.' },\r\n total_legs: { type: 'int', description: 'Always 1.' },\r\n is_final_leg: { type: 'bool', description: 'Always true.' },\r\n },\r\n { command: 'agenzo-merchant-cli flight-flink more-offers --product-token pt_...', output_summary: 'Additional fare offers.' },\r\n);\r\n\r\nexport const flightVerifySchema = flightSchema(\r\n 'verify',\r\n 'Pre-booking price verification. Returns the authoritative product_token and a price_changed flag; pass the returned token to create-order. With --previous-total-price set, supplier 1002/1950 no longer dead-ends: the platform re-searches the SAME flight from the token and returns the refreshed fare; if that flight can no longer be found it fails with OFFER_UNAVAILABLE (pick another flight).',\r\n {\r\n 'product-token': { type: 'string', required: true, description: 'Opaque token from search.' },\r\n 'previous-total-price': { type: 'int', required: false, description: 'Total price of the selected offer; enables the one-shot re-search refresh on supplier 1002/1950. Omit to keep the legacy behavior (error surfaces as-is).' },\r\n 'cabin-class': { type: 'string', required: false, description: 'Cabin class to re-search with when refreshing (economy | premium_economy | business | first). Omitted falls back to economy.' },\r\n 'adult-num': { type: 'int', required: false, description: 'Adults to re-search with when refreshing (1-9).' },\r\n 'child-num': { type: 'int', required: false, description: 'Children to re-search with when refreshing (0-9).' },\r\n 'infant-num': { type: 'int', required: false, description: 'Infants to re-search with when refreshing (0-9).' },\r\n },\r\n {\r\n product_token: { type: 'string', description: 'Authoritative token to pass to create-order.' },\r\n total_price: { type: 'int', description: 'Verified total price (integer).' },\r\n currency: { type: 'string', description: 'Currency code.' },\r\n price_changed: { type: 'bool', description: 'True if the price changed since search; re-confirm with the user.' },\r\n previous_total_price: { type: 'int', description: 'The selected offer’s price at pick time; present when the request carried previous-total-price. If it differs from total_price the fare was refreshed by a re-search (show the user the old → new price).' },\r\n journeys: { type: 'array', description: 'The COMPLETE itinerary being priced — every leg, not just the last one relayed. Use it to show the full trip on a confirmation screen.' },\r\n },\r\n { command: 'agenzo-merchant-cli flight-flink verify --product-token pt_...', output_summary: 'Returns the authoritative product_token + price_changed.' },\r\n);\r\n\r\nexport const flightCreateOrderSchema = flightSchema(\r\n 'create-order',\r\n 'Create a flight order without charging (locks the fare, status AWAITING_PAYMENT). Forward the verify product_token and its total/currency verbatim.',\r\n {\r\n 'product-token': { type: 'string', required: true, description: 'Authoritative token from verify.' },\r\n 'total-amount': { type: 'string', required: true, description: 'Verified total price (decimal units).' },\r\n currency: { type: 'string', required: true, description: 'ISO 4217 currency code.' },\r\n 'trip-type': { type: 'int', required: false, default: 1, description: '1/2/3.' },\r\n 'contact-name': { type: 'string', required: true, description: 'Contact name.' },\r\n 'contact-region': { type: 'string', required: true, description: 'Contact phone country code (no +).' },\r\n 'contact-phone': { type: 'string', required: true, description: 'Contact phone.' },\r\n 'contact-email': { type: 'string', required: true, description: 'Contact email.' },\r\n passengers: { type: 'json', required: true, description: 'JSON array of passengers. gender/id_type are STRINGS (\"1\"/\"2\"). child/infant require adult_passenger_name. A saved traveller can be passed as just {\"traveller_token\":\"tvp_...\",\"type\":\"adult\"} (from token-cli travellers list); the server fills in the ID details.' },\r\n 'save-travellers': { type: 'bool', required: false, description: 'Save the fully filled passengers of this order as frequent travellers. Set only when the user explicitly asked to save them.' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'idempotency-key': { type: 'string', required: true, description: 'Forwarded verbatim as the Idempotency-Key header.' },\r\n },\r\n {\r\n order_no: { type: 'string', description: 'Our order reference (ffo_...).' },\r\n upstream_order_no: { type: 'string', description: 'Supplier order number.' },\r\n status: { type: 'string', description: 'AWAITING_PAYMENT after a successful create.' },\r\n total_amount: { type: 'float', description: 'Total amount.' },\r\n currency: { type: 'string', description: 'Currency code.' },\r\n },\r\n { command: \"agenzo-merchant-cli flight-flink create-order --product-token pt_... --total-amount 1200 --currency CNY --contact-name 'ZHANG SAN' --contact-region 86 --contact-phone 138... --contact-email a@b.com --passengers '[...]' --idempotency-key k1\", output_summary: 'Returns order_no; then pay-order to ticket.' },\r\n {\r\n error_recovery: {\r\n PRICE_CHANGED: 'Price changed since verify. Re-run verify and confirm the new price with the user before retrying.',\r\n ORDER_CREATE_FAILED: 'Upstream create failed; funds released. Safe to retry with the same idempotency-key.',\r\n IDEMPOTENCY_CONFLICT: 'Same key reused with different params. Use a fresh idempotency-key.',\r\n },\r\n },\r\n);\r\n\r\nexport const flightPayOrderSchema = flightSchema(\r\n 'pay-order',\r\n 'Charge the order and trigger upstream ticketing. AWAITING_PAYMENT → PAID. Funds move HERE, not in create-order.',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference from create-order.' },\r\n 'payment-method-id': { type: 'string', required: false, description: 'Optional bound-card id to charge (pay_per_call only; omit to use the default card).' },\r\n 'payment-token-id': { type: 'string', required: false, description: 'Optional network-token id; settles via direct charge instead of EVO preauth.' },\r\n 'authorized-merchant-trans-id': { type: 'string', required: false, description: 'Resume an EVO-card 3DS challenge with an already-authorised preauth trans id.' },\r\n authenticate: { type: 'bool', required: false, default: false, description: 'Opt-in to require cardholder 3DS on the network-token direct charge (payment-token-id, EVO/Mastercard). On step-up the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume via authorized-charge-no. Default off = frictionless.' },\r\n 'return-url': { type: 'string', required: false, description: 'Optional 3DS/passkey return URL for the network-token authenticate path; falls back to the platform EVO_3DS_RETURN_URL.' },\r\n 'authorized-charge-no': { type: 'string', required: false, description: 'Resume a network-token 3DS challenge: charge_no from a prior AUTHENTICATION_REQUIRED response (settled via resume_token), then triggers ticketing on success.' },\r\n 'evo-explicit': { type: 'bool', required: false, default: false, description: '[方案 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set true ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Forwarded verbatim as the Idempotency-Key header.' },\r\n ...PRICE_ANNOTATION_FLAGS,\r\n },\r\n { order_no: { type: 'string', description: 'Our order reference.' }, status: { type: 'string', description: 'PAID on success; AUTHENTICATION_REQUIRED when the card needs 3DS.' } },\r\n { command: 'agenzo-merchant-cli flight-flink pay-order --order-no ffo_... --idempotency-key k2', output_summary: 'Order becomes PAID; poll get-order until TICKETED.' },\r\n);\r\n\r\nexport const flightGetOrderSchema = flightSchema(\r\n 'get-order',\r\n 'Query flight order status by --order-no. Ticketing is asynchronous — poll until TICKETED.',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll until terminal, one NDJSON line per update.' },\r\n 'watch-interval': { type: 'int', required: false, default: 5, description: 'Seconds between polls.' },\r\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll.' },\r\n },\r\n {\r\n order_no: { type: 'string', description: 'Our order reference.' },\r\n status: { type: 'string', description: 'AWAITING_PAYMENT | PAID | TICKETING | TICKETED | CANCELLED | FAILED.' },\r\n ticket_infos: { type: 'array', description: 'Ticket numbers once TICKETED.' },\r\n },\r\n { command: 'agenzo-merchant-cli flight-flink get-order --order-no ffo_...', output_summary: 'Returns status; poll until TICKETED.' },\r\n {\r\n polling: {\r\n recommended_interval_seconds: 5,\r\n terminal_statuses: ['TICKETED', 'CANCELLED', 'FAILED'],\r\n in_progress_statuses: ['AWAITING_PAYMENT', 'PAID', 'TICKETING'],\r\n },\r\n },\r\n);\r\n\r\nexport const flightCancelOrderSchema = flightSchema(\r\n 'cancel-order',\r\n 'Cancel an un-ticketed order by --order-no (with refund). A ticketed order is rejected upstream.',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n reason: { type: 'string', required: false, description: 'Optional cancellation reason.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Forwarded verbatim as the Idempotency-Key header.' },\r\n },\r\n { order_no: { type: 'string', description: 'Our order reference.' }, status: { type: 'string', description: 'CANCELLED on success.' }, refund_amount: { type: 'float|null', description: 'Refunded amount.' } },\r\n { command: 'agenzo-merchant-cli flight-flink cancel-order --order-no ffo_... --idempotency-key k3', output_summary: 'Order becomes CANCELLED; refund issued.' },\r\n);\r\n\r\nexport const flightListOrdersSchema = flightSchema(\r\n 'list-orders',\r\n \"List the developer's flight orders (local read, no upstream call).\",\r\n {\r\n status: { type: 'string', required: false, description: 'Optional status filter.' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n page: { type: 'int', required: false, default: 1, description: '1-based page.' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page (1-100).' },\r\n },\r\n { orders: { type: 'array', description: 'Flight order summaries; each item carries member_id (null when unattributed).' }, total: { type: 'int', description: 'Total count.' } },\r\n { command: 'agenzo-merchant-cli flight-flink list-orders', output_summary: 'Paged flight orders.' },\r\n);\r\n\r\nexport const flightChangeSearchSchema = flightSchema(\r\n 'change-search',\r\n 'Search rebook-eligible flights for an order.',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n date: { type: 'string', required: true, description: 'Target change date YYYY-MM-DD.' },\r\n passenger: { type: 'string', required: true, description: 'passengerCode.' },\r\n 'segment-id': { type: 'string', required: true, description: 'Comma-separated segment ids.' },\r\n 'cabin-class': { type: 'string', required: false, default: 'economy', description: 'Cabin class.' },\r\n },\r\n { flights: { type: 'array', description: 'Rebook-eligible flights.' } },\r\n { command: 'agenzo-merchant-cli flight-flink change-search --order-no ffo_... --date 2026-08-05 --passenger P1 --segment-id S1', output_summary: 'Rebook options.' },\r\n);\r\n\r\nexport const flightChangeApplySchema = flightSchema(\r\n 'change-apply',\r\n 'Submit a change request. Returns change_order_no, status 0 (pending review).',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n passenger: { type: 'string', required: true, description: 'passengerCode.' },\r\n 'segment-id': { type: 'string', required: true, description: 'Comma-separated segment ids.' },\r\n 'product-token': { type: 'string', required: true, description: 'Change priceKey token.' },\r\n 'contact-name': { type: 'string', required: true, description: 'Contact name.' },\r\n 'contact-region': { type: 'string', required: true, description: 'Contact region.' },\r\n 'contact-phone': { type: 'string', required: true, description: 'Contact phone.' },\r\n 'contact-email': { type: 'string', required: true, description: 'Contact email.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n },\r\n { change_order_no: { type: 'string', description: 'Change order number.' }, status: { type: 'int', description: '0 = pending review.' } },\r\n { command: 'agenzo-merchant-cli flight-flink change-apply --order-no ffo_... --passenger P1 --segment-id S1 --product-token pt_... --contact-name X --contact-region 86 --contact-phone 138 --contact-email a@b.com --idempotency-key k4', output_summary: 'Returns change_order_no; pay-order type=1 to confirm.' },\r\n);\r\n\r\nexport const flightChangeDetailSchema = flightSchema(\r\n 'change-detail',\r\n 'Change request detail by --change-order-no.',\r\n { 'change-order-no': { type: 'string', required: true, description: 'Change order number.' } },\r\n { status: { type: 'int', description: 'Change status.' } },\r\n { command: 'agenzo-merchant-cli flight-flink change-detail --change-order-no C1', output_summary: 'Change request detail.' },\r\n);\r\n\r\nexport const flightChangeCancelSchema = flightSchema(\r\n 'change-cancel',\r\n 'Cancel a change request (immediate terminal).',\r\n {\r\n 'change-order-no': { type: 'string', required: true, description: 'Change order number.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n },\r\n { status: { type: 'int', description: 'Terminal 5 (cancelled).' } },\r\n { command: 'agenzo-merchant-cli flight-flink change-cancel --change-order-no C1 --idempotency-key k5', output_summary: 'Change request cancelled.' },\r\n);\r\n\r\nexport const flightChangePaySchema = flightSchema(\r\n 'change-pay',\r\n 'Pay a change request fee (charges like a normal order) and trigger change ticketing. flink pay type=1.',\r\n {\r\n 'change-order-no': { type: 'string', required: true, description: 'Change order number.' },\r\n 'order-no': { type: 'string', required: true, description: 'Original order reference (ownership check).' },\r\n amount: { type: 'float', required: true, description: 'Change fee total (change-detail price_total, decimal units).' },\r\n currency: { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code.' },\r\n 'payment-method-id': { type: 'string', required: false, description: 'Optional bound-card id (EVO path).' },\r\n 'payment-token-id': { type: 'string', required: false, description: 'Optional UPI network-token id (unionpay charge path).' },\r\n 'authorized-merchant-trans-id': { type: 'string', required: false, description: 'Resume a 3DS challenge with the merchant trans id of the already-authorised preauth; the platform reuses and captures it instead of authorizing again.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n ...PRICE_ANNOTATION_FLAGS,\r\n },\r\n {\r\n change_order_no: { type: 'string', description: 'Change order number.' },\r\n status: { type: 'string', description: 'PROCESSING after payment.' },\r\n payment_status: { type: 'string', description: 'SETTLED on success. Absent when the card needs 3DS — the response then carries a challenge object instead (status AUTHENTICATION_REQUIRED, three_ds_url, merchant_trans_id) and nothing has been charged yet.' },\r\n },\r\n { command: 'agenzo-merchant-cli flight-flink change-pay --change-order-no C1 --order-no ffo_... --amount 120 --currency USD --idempotency-key k6', output_summary: 'Change fee charged; change ticketing triggered.' },\r\n);\r\n\r\nexport const flightRefundApplySchema = flightSchema(\r\n 'refund-apply',\r\n 'Submit a refund request. Returns refund_order_no, status 0 (pending review).',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n passenger: { type: 'string', required: true, description: 'passengerCode.' },\r\n 'segment-id': { type: 'string', required: true, description: 'Comma-separated segment ids.' },\r\n 'reason-type': { type: 'int', required: true, description: 'Refund reason type code.' },\r\n reason: { type: 'string', required: false, description: 'Free-text reason.' },\r\n 'contact-name': { type: 'string', required: true, description: 'Contact name.' },\r\n 'contact-region': { type: 'string', required: true, description: 'Contact region.' },\r\n 'contact-phone': { type: 'string', required: true, description: 'Contact phone.' },\r\n 'contact-email': { type: 'string', required: true, description: 'Contact email.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n },\r\n { refund_order_no: { type: 'string', description: 'Refund order number.' }, status: { type: 'int', description: '0 = pending review.' } },\r\n { command: 'agenzo-merchant-cli flight-flink refund-apply --order-no ffo_... --passenger P1 --segment-id S1 --reason-type 1 --contact-name X --contact-region 86 --contact-phone 138 --contact-email a@b.com --idempotency-key k6', output_summary: 'Returns refund_order_no; refund-confirm 1 to confirm.' },\r\n);\r\n\r\nexport const flightRefundDetailSchema = flightSchema(\r\n 'refund-detail',\r\n 'Refund request detail by --refund-order-no.',\r\n { 'refund-order-no': { type: 'string', required: true, description: 'Refund order number.' } },\r\n { status: { type: 'int', description: 'Refund status.' } },\r\n { command: 'agenzo-merchant-cli flight-flink refund-detail --refund-order-no R1', output_summary: 'Refund request detail.' },\r\n);\r\n\r\nexport const flightRefundConfirmSchema = flightSchema(\r\n 'refund-confirm',\r\n 'Confirm (\"1\") or cancel (\"2\") a refund. Cancel takes effect immediately to terminal 5.',\r\n {\r\n 'refund-order-no': { type: 'string', required: true, description: 'Refund order number.' },\r\n confirm: { type: 'string', required: true, description: '\"1\" confirm / \"2\" cancel.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n },\r\n { status: { type: 'int', description: 'Refund status after the action.' } },\r\n { command: 'agenzo-merchant-cli flight-flink refund-confirm --refund-order-no R1 --confirm 1 --idempotency-key k7', output_summary: 'Refund confirmed or cancelled.' },\r\n);\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { QuoteResponse, VehicleClass } from '../types/api.js';\r\nimport { attachSchemaHelp, quoteSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 2.1 / design §4.4.1.3) — a catalog code (exit 1), never\r\n * `PARAM_REQUIRED` (not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Number-ify a coordinate / numeric flag. Non-finite input maps to\r\n * `PARAM_INVALID`. Coordinates are sent as numbers, never strings (§4.4.1.3).\r\n */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the quote as a table for `--format table`. Each vehicle class is one\r\n * row; amounts are decimal currency units (NOT cents) — printed verbatim.\r\n */\r\nfunction formatQuote(data: QuoteResponse): string {\r\n const classes: VehicleClass[] = data.vehicle_classes ?? [];\r\n if (classes.length === 0) {\r\n return Formatter.status('info', 'No vehicle classes available for this route');\r\n }\r\n\r\n const headers = ['Vehicle Class', 'Price', 'Currency', 'Quote ID', 'Pax', 'Luggage'];\r\n const rows = classes.map((vc) => [\r\n String(vc.vehicle_class ?? '-'),\r\n String(vc.price?.amount ?? '-'),\r\n String(vc.price?.currency ?? '-'),\r\n String(vc.price?.quote_id ?? '-'),\r\n String(vc.passenger_capacity ?? '-'),\r\n String(vc.luggage_capacity ?? '-'),\r\n ]);\r\n\r\n const lines: [string, string][] = [\r\n ['Airport transfer', String(data.is_airport_transfer ?? false)],\r\n ];\r\n if (data.airport_direction) {\r\n lines.push(['Airport direction', String(data.airport_direction)]);\r\n }\r\n if (data.meet_and_greet) {\r\n const mg = data.meet_and_greet;\r\n const mgPrice = mg.price ? ` (${mg.price.amount} ${mg.price.currency})` : '';\r\n lines.push(['Meet & greet', `${mg.available ? 'available' : 'unavailable'}${mgPrice}`]);\r\n }\r\n\r\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(lines)}`;\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife quote` — request fare quotes between two points (§4.4.1.3).\r\n *\r\n * Read-only (no idempotency key). Builds the `/ride/quote` body from flags\r\n * (coordinates number-ified, missing required → `PARAM_INVALID`), POSTs with\r\n * the `X-Api-Key` auth, and renders `QuoteResponse` via `renderWithContext`\r\n * (json carries the profile/endpoint envelope). The progress line is emitted\r\n * through `notify` so it goes to stderr and stays silent in json mode.\r\n */\r\nexport function registerQuoteCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('quote')\r\n .description('Request fare quotes for a ride between two points')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--pickup-lat <lat>', 'Pickup latitude')\r\n .option('--pickup-lng <lng>', 'Pickup longitude')\r\n .option('--pickup-name <name>', 'Pickup location name')\r\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\r\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\r\n .option('--dropoff-name <name>', 'Dropoff location name')\r\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\r\n .option('--passenger-name <name>', 'Lead passenger full name')\r\n .option('--passenger-phone <phone>', 'Passenger phone (E.164)')\r\n .option('--passenger-count <n>', 'Passenger count')\r\n .option('--luggage-count <n>', 'Luggage count')\r\n .option('--passenger-email <email>', 'Passenger email')\r\n .option('--children-count <n>', 'Children count')\r\n .option('--infant-count <n>', 'Infant count (passenger breakdown)')\r\n .option('--toddler-count <n>', 'Toddler count (passenger breakdown)');\r\n\r\n attachSchemaHelp(cmd, quoteSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. Coordinates are number-ified; pickup_time accepts the\r\n // literal \"now\" or epoch seconds. Missing required fields throw\r\n // PARAM_INVALID before any request is sent.\r\n const body: Record<string, unknown> = {\r\n pickup: {\r\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\r\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\r\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\r\n },\r\n dropoff: {\r\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\r\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\r\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\r\n },\r\n pickup_time:\r\n opts.pickupTime === 'now'\r\n ? 'now'\r\n : num(opts.pickupTime as string | undefined, 'pickup-time'),\r\n };\r\n\r\n // Optional passenger / luggage / children fields — included only when set.\r\n if (opts.passengerName) body.passenger_name = opts.passengerName as string;\r\n if (opts.passengerPhone) body.passenger_phone = opts.passengerPhone as string;\r\n if (opts.passengerCount !== undefined) {\r\n body.passenger_count = num(opts.passengerCount as string, 'passenger-count');\r\n }\r\n if (opts.luggageCount !== undefined) {\r\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\r\n }\r\n if (opts.childrenCount !== undefined) {\r\n body.children_count = num(opts.childrenCount as string, 'children-count');\r\n }\r\n if (opts.infantCount !== undefined) {\r\n body.infant_count = num(opts.infantCount as string, 'infant-count');\r\n }\r\n if (opts.toddlerCount !== undefined) {\r\n body.toddler_count = num(opts.toddlerCount as string, 'toddler-count');\r\n }\r\n if (opts.passengerEmail !== undefined) {\r\n body.passenger_email = opts.passengerEmail as string;\r\n }\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching quotes...');\r\n\r\n const result = await deps.apiClient.post<QuoteResponse>(\r\n '/ride/quote',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<QuoteResponse> = {\r\n data,\r\n text: () => formatQuote(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { BookResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, bookSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 2.2 / design §4.4.1.3) — a catalog code (exit 1), mirroring the\r\n * sibling `quote` command's convention.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Validate a passenger phone as E.164 shape (edge fail-fast). The authoritative\r\n * region-aware validity check (libphonenumber) runs server-side; this catches\r\n * obviously malformed input before a request is sent. Accepts spaces/dashes,\r\n * normalizes them away, and requires a leading \"+\" country code.\r\n */\r\nfunction phone(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n const cleaned = raw.replace(/[\\s-]/g, '');\r\n if (!/^\\+[1-9]\\d{7,14}$/.test(cleaned)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `--${flag} must be a valid international phone number, e.g. +14155552671.`,\r\n );\r\n }\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Number-ify a seat count and enforce the 0–5 range (design §4.4.1.3 book\r\n * schema). Out-of-range values map to `PARAM_INVALID`.\r\n */\r\nfunction seatCount(value: string, flag: string): number {\r\n const n = num(value, flag);\r\n if (!Number.isInteger(n) || n < 0 || n > 5) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer between 0 and 5.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render a booked ride as a key/value block for `--format table`. Amounts are\r\n * decimal currency units (NOT cents) — printed verbatim.\r\n */\r\nfunction formatBook(data: BookResponse): string {\r\n const lines: [string, string][] = [\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ['Scheduled', String(data.is_scheduled ?? false)],\r\n ['Order type', String(data.order_type ?? '-')],\r\n ];\r\n if (data.price) {\r\n lines.push(['Price', `${data.price.amount} ${data.price.currency}`]);\r\n if (data.price.quote_id) lines.push(['Quote ID', String(data.price.quote_id)]);\r\n }\r\n lines.push(['Payment status', String(data.payment_status ?? '-')]);\r\n // Mode-dependent: monthly_settlement returns billing_entry_id, pay_per_call\r\n // echoes back payment_order_id.\r\n if (data.billing_entry_id) lines.push(['Billing entry', String(data.billing_entry_id)]);\r\n if (data.payment_order_id) lines.push(['Payment order', String(data.payment_order_id)]);\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife book` — book a ride against a previously returned quote\r\n * (§4.4.1.3 book schema + §4.4.2.1). Write op (W/Y).\r\n *\r\n * Funding is decided server-side by the developer's `billing_mode`:\r\n * - monthly_settlement: no payment handle; fare is deducted from the\r\n * settlement account (payment_status=ON_ACCOUNT).\r\n * - pay_per_call: pass `--payment-order-id` (a PAID order from payment-cli),\r\n * and/or `--payment-method-id` to charge a specific already-bound card.\r\n * `--payment-method-id` is an opaque bound-card id (the same handle\r\n * `hotel-redaug create-order` / `flight-flink create-order` accept) — the CLI\r\n * still never accepts raw card data (PAN/CVV) in any form.\r\n *\r\n * `POST /ride/book` with `X-Api-Key` auth + the `Idempotency-Key` header (key\r\n * forwarded verbatim, never in the body). `--yes` skips the confirm; a missing\r\n * `--idempotency-key` under `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED`\r\n * before any request is sent. Renders `BookResponse` via `renderWithContext`\r\n * (json carries the profile/endpoint envelope); the progress line goes to\r\n * stderr via `notify` and stays silent in json mode.\r\n */\r\nexport function registerBookCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('book')\r\n .description('Book a ride using a quote_id returned by quote')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--quote-id <id>', 'Quote id from `ride-elife quote`')\r\n .option('--vehicle-class <class>', 'Chosen vehicle class')\r\n .option('--price-amount <amount>', 'Fare in decimal currency units (not cents)')\r\n .option('--price-currency <currency>', 'Currency code (default USD)')\r\n .option('--payment-order-id <id>', 'Paid payment order id (pay_per_call mode only)')\r\n .option(\r\n '--payment-method-id <id>',\r\n 'Bound payment method id to charge (pay_per_call mode only)',\r\n )\r\n .option(\r\n '--payment-token-id <id>',\r\n 'DEPRECATED — use `ride-elife create-order` + `pay-order` for network-token direct charge. ' +\r\n 'A single-step book carrying a network token hits Charge_Service strict order↔token ' +\r\n 'binding and is rejected server-side with a retriable=false guidance error. Kept only for ' +\r\n 'backward compatibility; monthly_settlement / EVO / no-credential booking still work via book.',\r\n )\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'EVO merchant transaction id of an already-authorised preauth (3DS challenge resume). ' +\r\n 'When set, the server reuses that authorization instead of creating a new one, ' +\r\n 'avoiding a second hold on the card (pay_per_call mode only).',\r\n )\r\n .option('--passenger-name <name>', 'Passenger full name')\r\n .option('--passenger-phone <phone>', 'Passenger phone')\r\n .option('--passenger-email <email>', 'Passenger email')\r\n .option('--luggage-count <n>', 'Luggage count')\r\n .option('--special-requests <text>', 'Free-text special requests')\r\n .option('--pickup-lat <lat>', 'Pickup latitude')\r\n .option('--pickup-lng <lng>', 'Pickup longitude')\r\n .option('--pickup-name <name>', 'Pickup location name')\r\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\r\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\r\n .option('--dropoff-name <name>', 'Dropoff location name')\r\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\r\n .option('--meet-and-greet', 'Enable meet & greet service')\r\n .option('--meet-and-greet-price <amount>', 'Meet & greet surcharge')\r\n .option('--welcome-sign <text>', 'Welcome sign text')\r\n .option('--child-seat-count <n>', 'Number of child seats needed (0-5)')\r\n .option('--infant-seat-count <n>', 'Number of infant seats needed (0-5)')\r\n .option('--toddler-seat-count <n>', 'Number of toddler seats needed (0-5)')\r\n .option('--arrival-flight-no <no>', 'Arrival flight number')\r\n .option('--arrival-airline <airline>', 'Arrival airline')\r\n .option('--departure-flight-no <no>', 'Departure flight number')\r\n .option('--departure-airline <airline>', 'Departure airline')\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, bookSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. Required fields throw PARAM_INVALID before any\r\n // request is sent (mirrors the sibling `quote` command). The body carries NO\r\n // raw card data; payment handles are limited to the opaque\r\n // payment_order_id / payment_method_id ids below.\r\n const quoteId = need(opts.quoteId as string | undefined, 'quote-id');\r\n const body: Record<string, unknown> = {\r\n quote_id: quoteId,\r\n vehicle_class: need(opts.vehicleClass as string | undefined, 'vehicle-class'),\r\n price_amount: num(opts.priceAmount as string | undefined, 'price-amount'),\r\n price_currency: (opts.priceCurrency as string | undefined) ?? 'USD',\r\n passenger_name: need(opts.passengerName as string | undefined, 'passenger-name'),\r\n passenger_phone: phone(opts.passengerPhone as string | undefined, 'passenger-phone'),\r\n };\r\n\r\n // Optional payment handles for pay_per_call. `payment_method_id` is an opaque\r\n // bound-card id; raw card data is never accepted nor forwarded.\r\n // monthly_settlement omits both entirely.\r\n if (opts.paymentOrderId) body.payment_order_id = opts.paymentOrderId as string;\r\n if (opts.paymentMethodId) body.payment_method_id = opts.paymentMethodId as string;\r\n // 【已废弃】network-token 直扣请改走两步主路径:create-order 锁单取 order_ref → pay-order 直扣。\r\n // 这里仍原样透传 payment_token_id 以保持向后兼容;服务端会对单步 book 携带令牌的请求返回\r\n // retriable=false 的引导错误(指向 create-order + pay-order),不扣款、不建行程、不落单。\r\n if (opts.paymentTokenId) body.payment_token_id = opts.paymentTokenId as string;\r\n // 3DS 挑战续单凭证:持卡人完成认证后带回该交易号,服务端复用那笔已授权的预授权,\r\n // 不再新发起一次(否则又拿到新挑战页且重复冻结资金)。\r\n if (opts.authorizedMerchantTransId) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 归因标签(可选):非空才写入,缺省保持无归属。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n if (opts.passengerEmail) body.passenger_email = opts.passengerEmail as string;\r\n if (opts.luggageCount !== undefined) {\r\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\r\n }\r\n if (opts.specialRequests) body.special_requests = opts.specialRequests as string;\r\n\r\n // Pickup / dropoff / pickup_time are included only when supplied (they must\r\n // match the originating quote). Coordinates are number-ified.\r\n if (opts.pickupLat || opts.pickupLng || opts.pickupName) {\r\n body.pickup = {\r\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\r\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\r\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\r\n };\r\n }\r\n if (opts.dropoffLat || opts.dropoffLng || opts.dropoffName) {\r\n body.dropoff = {\r\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\r\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\r\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\r\n };\r\n }\r\n if (opts.pickupTime) {\r\n body.pickup_time =\r\n opts.pickupTime === 'now' ? 'now' : num(opts.pickupTime as string, 'pickup-time');\r\n }\r\n\r\n if (opts.meetAndGreet) body.meet_and_greet = true;\r\n if (opts.meetAndGreetPrice !== undefined) {\r\n body.meet_and_greet_price = num(opts.meetAndGreetPrice as string, 'meet-and-greet-price');\r\n }\r\n if (opts.welcomeSign) body.welcome_sign = opts.welcomeSign as string;\r\n if (opts.childSeatCount !== undefined) {\r\n body.child_seat_count = seatCount(opts.childSeatCount as string, 'child-seat-count');\r\n }\r\n if (opts.infantSeatCount !== undefined) {\r\n body.infant_seat_count = seatCount(opts.infantSeatCount as string, 'infant-seat-count');\r\n }\r\n if (opts.toddlerSeatCount !== undefined) {\r\n body.toddler_seat_count = seatCount(opts.toddlerSeatCount as string, 'toddler-seat-count');\r\n }\r\n if (opts.arrivalFlightNo || opts.arrivalAirline) {\r\n body.arrival_flight = {\r\n flight_no: opts.arrivalFlightNo as string | undefined,\r\n airline: opts.arrivalAirline as string | undefined,\r\n };\r\n }\r\n if (opts.departureFlightNo || opts.departureAirline) {\r\n body.departure_flight = {\r\n flight_no: opts.departureFlightNo as string | undefined,\r\n airline: opts.departureAirline as string | undefined,\r\n };\r\n }\r\n\r\n // Confirm before the write unless --yes. The warning/prompt go to stderr;\r\n // declining maps to CLIENT_ABORTED (exit 5) via the top-level envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Book ride with quote ${quoteId}?`,\r\n default: true,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Booking cancelled by user.');\r\n }\r\n }\r\n\r\n // Idempotency key (requirement 5.3): resolved before the request. Under\r\n // --yes a missing key is a hard error and no request is sent. The key is\r\n // sent as a header, never in the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife book',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Booking ride...');\r\n\r\n const result = await deps.apiClient.post<BookResponse>(\r\n '/ride/book',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<BookResponse> = {\r\n data,\r\n text: () => formatBook(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","/**\r\n * Idempotency key resolution for write commands (`ride-elife book` / `cancel`)\r\n * — requirement 5.3 / §6.1, design Property 3.\r\n *\r\n * The error type is reused from `@agenzo/cli-core` (`IdempotencyKeyRequiredError`\r\n * → `PARAM_IDEMPOTENCY_KEY_REQUIRED`) so the merchant CLI does not re-define it.\r\n * The resolve/normalize logic stays in the app because it is merchant-domain\r\n * policy (per requirement 4.4): the §6.1 key format `[A-Za-z0-9_-]{1,128}`, the\r\n * `--yes`-missing hard error vs. interactive prompt branch, and the rule that\r\n * the key is forwarded verbatim as the `Idempotency-Key` HTTP header and is\r\n * never placed in the request body.\r\n *\r\n * The CLI NEVER auto-generates a key: under `--yes` a missing key is a hard\r\n * error thrown before any request is sent; otherwise the caller is prompted.\r\n */\r\nimport {\r\n CliError,\r\n IdempotencyKeyRequiredError,\r\n PromptEngine,\r\n} from '@agenzo/cli-core';\r\n\r\n/**\r\n * §6.1 idempotency key format: 1–128 characters drawn from `[A-Za-z0-9_-]`.\r\n */\r\nexport const IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;\r\n\r\n/** Human-readable rule reused in validation messages and prompt feedback. */\r\nexport const IDEMPOTENCY_KEY_RULE = 'Use 1-128 characters from [A-Za-z0-9_-].';\r\n\r\n/**\r\n * Validate + normalize a caller-supplied idempotency key. A malformed key maps\r\n * to `PARAM_INVALID` (catalog code, exit 1) — never silently corrected and\r\n * never auto-generated.\r\n */\r\nexport function normalizeIdempotencyKey(key: string): string {\r\n const trimmed = key.trim();\r\n if (!IDEMPOTENCY_KEY_PATTERN.test(trimmed)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `Invalid idempotency key: \"${key}\". ${IDEMPOTENCY_KEY_RULE}`,\r\n );\r\n }\r\n return trimmed;\r\n}\r\n\r\n/**\r\n * Resolve the idempotency key for a write operation (requirement 5.3). The CLI\r\n * never generates one:\r\n * - supplied via `--idempotency-key` → validated + normalized;\r\n * - absent under `--yes` → hard error (`PARAM_IDEMPOTENCY_KEY_REQUIRED`,\r\n * reused from cli-core) thrown before any request is sent;\r\n * - absent otherwise → collected interactively, then validated.\r\n *\r\n * The returned key is forwarded verbatim as the `Idempotency-Key` header by the\r\n * caller — it never enters the request body.\r\n */\r\nexport async function resolveIdempotencyKey(\r\n flagValue: string | undefined,\r\n opts: { yes: boolean; commandPath: string },\r\n): Promise<string> {\r\n if (flagValue !== undefined) {\r\n return normalizeIdempotencyKey(flagValue);\r\n }\r\n if (opts.yes) {\r\n throw new IdempotencyKeyRequiredError(opts.commandPath);\r\n }\r\n const entered = await PromptEngine.resolveInput(undefined, {\r\n message: 'Idempotency key (unique per write, for safe retry):',\r\n validate: (v) => IDEMPOTENCY_KEY_PATTERN.test(v.trim()) || IDEMPOTENCY_KEY_RULE,\r\n });\r\n return normalizeIdempotencyKey(entered);\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { CreateRideOrderResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, rideCreateOrderSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (a catalog code, exit 1), mirroring the sibling `book` / `quote` commands.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Validate a passenger phone as E.164 shape (edge fail-fast). The authoritative\r\n * region-aware validity check runs server-side; this catches obviously\r\n * malformed input before a request is sent. Accepts spaces/dashes, normalizes\r\n * them away, and requires a leading \"+\" country code.\r\n */\r\nfunction phone(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n const cleaned = raw.replace(/[\\s-]/g, '');\r\n if (!/^\\+[1-9]\\d{7,14}$/.test(cleaned)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `--${flag} must be a valid international phone number, e.g. +14155552671.`,\r\n );\r\n }\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Number-ify a seat count and enforce the 0–5 range (mirrors `book`).\r\n * Out-of-range values map to `PARAM_INVALID`.\r\n */\r\nfunction seatCount(value: string, flag: string): number {\r\n const n = num(value, flag);\r\n if (!Number.isInteger(n) || n < 0 || n > 5) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer between 0 and 5.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the locked order as a key/value block for `--format table`. Amounts\r\n * are decimal currency units (NOT cents) — printed verbatim. The order\r\n * reference is resolved from `order_ref` when present, else `order_id` (both\r\n * carry the authoritative rio_… value).\r\n */\r\nfunction formatCreateOrder(data: CreateRideOrderResponse): string {\r\n const orderRef = String(data.order_ref ?? data.order_id ?? '-');\r\n const lines: [string, string][] = [\r\n ['Order ref', orderRef],\r\n ['Status', String(data.status ?? '-')],\r\n ['Payment status', String(data.payment_status ?? '-')],\r\n ];\r\n if (data.price) {\r\n lines.push(['Amount', `${data.price.amount} ${data.price.currency}`]);\r\n if (data.price.quote_id) lines.push(['Quote ID', String(data.price.quote_id)]);\r\n }\r\n if (data.is_scheduled !== undefined) lines.push(['Scheduled', String(data.is_scheduled)]);\r\n if (data.order_type) lines.push(['Order type', String(data.order_type)]);\r\n\r\n return [\r\n Formatter.keyValue(lines),\r\n Formatter.status(\r\n 'info',\r\n `Fare locked (AWAITING_PAYMENT) — bind ${orderRef} as the network token external_transaction_id, ` +\r\n `then settle with 'ride-elife pay-order --order-id ${orderRef}'. No funds moved yet.`,\r\n ),\r\n ].join('\\n\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife create-order` — lock a ride fare WITHOUT charging (the first step\r\n * of the two-step network-token direct-charge flow;\r\n * ride-network-token-direct-charge R11.1). Mirrors\r\n * `flight-flink create-order` / `hotel-redaug create-order`: the order enters\r\n * AWAITING_PAYMENT / payment_status=PENDING, NO funds move, and eLife is NOT\r\n * called. It returns the authoritative `order_ref` (rio_…) so the caller can\r\n * mint a network token bound to it (external_transaction_id = order_ref) and\r\n * then settle via `ride-elife pay-order`.\r\n *\r\n * Deliberately carries the SAME trip/quote/passenger/surcharge context as\r\n * `book` MINUS every payment credential (payment_order_id / payment_method_id /\r\n * payment_token_id / authorized_merchant_trans_id) — funding is deferred to\r\n * `pay-order`, so no payment handle is accepted here.\r\n *\r\n * `POST /ride/create-order` with `X-Api-Key` auth + the `Idempotency-Key`\r\n * header (key forwarded verbatim, never in the body). Locking a fare is a real\r\n * commitment (though not a charge), so the non-`--yes` path confirms (restating\r\n * amount/currency) before the write; `--yes` skips it and a missing\r\n * `--idempotency-key` under `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED`\r\n * before any request is sent. A declined confirm maps to `CLIENT_ABORTED`.\r\n */\r\nexport function registerRideCreateOrderCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('create-order')\r\n .description('Lock a ride fare without charging (await payment); returns the order_ref to pay')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--quote-id <id>', 'Quote id from `ride-elife quote`')\r\n .option('--vehicle-class <class>', 'Chosen vehicle class')\r\n .option('--price-amount <amount>', 'Fare in decimal currency units (not cents)')\r\n .option('--price-currency <currency>', 'Currency code (default USD)')\r\n .option('--passenger-name <name>', 'Passenger full name')\r\n .option('--passenger-phone <phone>', 'Passenger phone')\r\n .option('--passenger-email <email>', 'Passenger email')\r\n .option('--luggage-count <n>', 'Luggage count')\r\n .option('--special-requests <text>', 'Free-text special requests')\r\n .option('--pickup-lat <lat>', 'Pickup latitude')\r\n .option('--pickup-lng <lng>', 'Pickup longitude')\r\n .option('--pickup-name <name>', 'Pickup location name')\r\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\r\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\r\n .option('--dropoff-name <name>', 'Dropoff location name')\r\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\r\n .option('--meet-and-greet', 'Enable meet & greet service')\r\n .option('--meet-and-greet-price <amount>', 'Meet & greet surcharge')\r\n .option('--welcome-sign <text>', 'Welcome sign text')\r\n .option('--child-seat-count <n>', 'Number of child seats needed (0-5)')\r\n .option('--infant-seat-count <n>', 'Number of infant seats needed (0-5)')\r\n .option('--toddler-seat-count <n>', 'Number of toddler seats needed (0-5)')\r\n .option('--arrival-flight-no <no>', 'Arrival flight number')\r\n .option('--arrival-airline <airline>', 'Arrival airline')\r\n .option('--departure-flight-no <no>', 'Departure flight number')\r\n .option('--departure-airline <airline>', 'Departure airline')\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, rideCreateOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. Required fields throw PARAM_INVALID before any request\r\n // is sent (mirrors the sibling `book` command). The body carries NO payment\r\n // credential of any kind — create-order only locks the fare; funding is\r\n // deferred to `pay-order`.\r\n const quoteId = need(opts.quoteId as string | undefined, 'quote-id');\r\n const priceAmount = num(opts.priceAmount as string | undefined, 'price-amount');\r\n const priceCurrency = (opts.priceCurrency as string | undefined) ?? 'USD';\r\n const body: Record<string, unknown> = {\r\n quote_id: quoteId,\r\n vehicle_class: need(opts.vehicleClass as string | undefined, 'vehicle-class'),\r\n price_amount: priceAmount,\r\n price_currency: priceCurrency,\r\n passenger_name: need(opts.passengerName as string | undefined, 'passenger-name'),\r\n passenger_phone: phone(opts.passengerPhone as string | undefined, 'passenger-phone'),\r\n passenger_email: need(opts.passengerEmail as string | undefined, 'passenger-email'),\r\n };\r\n\r\n // 归因标签(可选):非空才写入,缺省保持无归属。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n if (opts.luggageCount !== undefined) {\r\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\r\n }\r\n if (opts.specialRequests) body.special_requests = opts.specialRequests as string;\r\n\r\n // Pickup / dropoff / pickup_time are included only when supplied (they must\r\n // match the originating quote). Coordinates are number-ified.\r\n if (opts.pickupLat || opts.pickupLng || opts.pickupName) {\r\n body.pickup = {\r\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\r\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\r\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\r\n };\r\n }\r\n if (opts.dropoffLat || opts.dropoffLng || opts.dropoffName) {\r\n body.dropoff = {\r\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\r\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\r\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\r\n };\r\n }\r\n if (opts.pickupTime) {\r\n body.pickup_time =\r\n opts.pickupTime === 'now' ? 'now' : num(opts.pickupTime as string, 'pickup-time');\r\n }\r\n\r\n if (opts.meetAndGreet) body.meet_and_greet = true;\r\n if (opts.meetAndGreetPrice !== undefined) {\r\n body.meet_and_greet_price = num(opts.meetAndGreetPrice as string, 'meet-and-greet-price');\r\n }\r\n if (opts.welcomeSign) body.welcome_sign = opts.welcomeSign as string;\r\n if (opts.childSeatCount !== undefined) {\r\n body.child_seat_count = seatCount(opts.childSeatCount as string, 'child-seat-count');\r\n }\r\n if (opts.infantSeatCount !== undefined) {\r\n body.infant_seat_count = seatCount(opts.infantSeatCount as string, 'infant-seat-count');\r\n }\r\n if (opts.toddlerSeatCount !== undefined) {\r\n body.toddler_seat_count = seatCount(opts.toddlerSeatCount as string, 'toddler-seat-count');\r\n }\r\n if (opts.arrivalFlightNo || opts.arrivalAirline) {\r\n body.arrival_flight = {\r\n flight_no: opts.arrivalFlightNo as string | undefined,\r\n airline: opts.arrivalAirline as string | undefined,\r\n };\r\n }\r\n if (opts.departureFlightNo || opts.departureAirline) {\r\n body.departure_flight = {\r\n flight_no: opts.departureFlightNo as string | undefined,\r\n airline: opts.departureAirline as string | undefined,\r\n };\r\n }\r\n\r\n // Confirm before the write unless --yes. Locking a fare is a commitment but\r\n // NOT a charge — the prompt restates the amount and says so. The prompt goes\r\n // to stderr; declining maps to CLIENT_ABORTED (exit 5) via the top-level\r\n // envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Lock this ride fare for ${priceAmount} ${priceCurrency}? This reserves the order (AWAITING_PAYMENT) but does NOT charge yet.`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Order creation aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key: resolved before the request. Under --yes a missing key is\r\n // a hard error and no request is sent. The key is sent as a header, never in\r\n // the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife create-order',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Locking ride fare...');\r\n\r\n const result = await deps.apiClient.post<CreateRideOrderResponse>(\r\n '/ride/create-order',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CreateRideOrderResponse> = {\r\n data,\r\n text: () => formatCreateOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { PayRideOrderResponse } from '../types/api.js';\r\nimport { PRICE_ANNOTATION_FLAGS, applyPriceAnnotation } from '../price-annotation.js';\r\nimport { attachSchemaHelp, ridePayOrderSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (a catalog code, exit 1), mirroring the sibling `create-order` / `book`\r\n * commands.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Enforce the exactly-one payment-credential rule (requirement 11.5). The two-step\r\n * pay MUST carry exactly one of `--payment-token-id` (network-token direct charge,\r\n * the main path) or `--payment-method-id` (EVO bound-card fallback). Both missing\r\n * and both present are rejected LOCALLY with a distinguishable `PARAM_INVALID`\r\n * error BEFORE any request is sent, so `Ride_Service.pay` is never called with an\r\n * ambiguous credential set. The two branches carry distinct messages so the\r\n * offending condition (neither vs. both) is itself distinguishable.\r\n */\r\nfunction assertExactlyOneCredential(\r\n paymentTokenId: string | undefined,\r\n paymentMethodId: string | undefined,\r\n): void {\r\n const hasToken = paymentTokenId !== undefined;\r\n const hasMethod = paymentMethodId !== undefined;\r\n if (!hasToken && !hasMethod) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Invalid payment credential options: provide exactly one of --payment-token-id ' +\r\n '(network-token direct charge) or --payment-method-id (EVO bound card). Neither was given.',\r\n );\r\n }\r\n if (hasToken && hasMethod) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Invalid payment credential options: --payment-token-id and --payment-method-id are ' +\r\n 'mutually exclusive — provide exactly one, not both.',\r\n );\r\n }\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the settled order as a key/value block for `--format table`. Amounts\r\n * are decimal currency units (NOT cents) — printed verbatim. The order reference\r\n * is resolved from `order_ref` when present, else `order_id` (both carry the\r\n * authoritative rio_… value). Status / payment status are echoed from the\r\n * response (a successful settlement returns PAID / SETTLED — requirement 11.4).\r\n */\r\nfunction formatPayOrder(data: PayRideOrderResponse): string {\r\n const orderRef = String(data.order_ref ?? data.order_id ?? '-');\r\n const lines: [string, string][] = [\r\n ['Order ref', orderRef],\r\n ['Status', String(data.status ?? '-')],\r\n ['Payment status', String(data.payment_status ?? '-')],\r\n ];\r\n if (data.ride_id !== undefined) lines.push(['Ride ID', String(data.ride_id)]);\r\n if (data.payment_channel) lines.push(['Payment channel', String(data.payment_channel)]);\r\n if (data.price) {\r\n lines.push(['Amount', `${data.price.amount} ${data.price.currency}`]);\r\n if (data.price.quote_id) lines.push(['Quote ID', String(data.price.quote_id)]);\r\n }\r\n // 网络令牌 3DS 挑战(status=AUTHENTICATION_REQUIRED):透出续付句柄与挑战地址。\r\n if (data.charge_no) lines.push(['Charge no', String(data.charge_no)]);\r\n if (data.three_ds_url) lines.push(['3DS URL', String(data.three_ds_url)]);\r\n\r\n // 挑战态不是终态成功:状态行按 AUTHENTICATION_REQUIRED 提示需完成认证,否则报结算成功。\r\n if (String(data.status) === 'AUTHENTICATION_REQUIRED') {\r\n return [\r\n Formatter.keyValue(lines),\r\n Formatter.status(\r\n 'warning',\r\n `Order ${orderRef} needs cardholder 3DS — open the 3DS URL, then resume pay-order with `\r\n + `--authorized-charge-no ${data.charge_no ?? ''}.`,\r\n ),\r\n ].join('\\n\\n');\r\n }\r\n\r\n return [\r\n Formatter.keyValue(lines),\r\n Formatter.status(\r\n 'success',\r\n `Order ${orderRef} settled — ${data.status ?? 'PAID'} / ${data.payment_status ?? 'SETTLED'}.`,\r\n ),\r\n ].join('\\n\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife pay-order` — settle a locked ride order by `--order-id` (the\r\n * second step of the two-step network-token direct-charge flow;\r\n * ride-network-token-direct-charge R11.2/R11.4/R11.5). Mirrors\r\n * `flight-flink pay-order` / `hotel-redaug pay-order`: funds move HERE (not in\r\n * create-order), and on success the order is pushed AWAITING_PAYMENT → PAID /\r\n * payment_status=SETTLED.\r\n *\r\n * Exactly one payment credential is required (requirement 11.5, mutual\r\n * exclusion): `--payment-token-id` (network-token direct charge — the main\r\n * path, `charge(order_id=order_ref)` triggers strict order↔token binding) OR\r\n * `--payment-method-id` (EVO bound-card fallback). Both missing and both present\r\n * are rejected LOCALLY with a distinguishable `PARAM_INVALID` error before any\r\n * request is sent — `Ride_Service.pay` is never called with an ambiguous\r\n * credential set. `--authorized-merchant-trans-id` resumes an EVO 3DS challenge.\r\n *\r\n * `POST /ride/pay` with `X-Api-Key` auth + the `Idempotency-Key` header (key\r\n * forwarded verbatim, never in the body). The order reference and payment\r\n * credentials travel in the body. Since this step actually charges the card,\r\n * the non-`--yes` path confirms before the write; `--yes` skips it and a missing\r\n * `--idempotency-key` under `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED`\r\n * before any request is sent. A declined confirm maps to `CLIENT_ABORTED`.\r\n */\r\nexport function registerRidePayOrderCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('pay-order')\r\n .description('Settle a locked ride order by --order-id (charges the card, creates the ride)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The order_ref (rio_…) from create-order to settle')\r\n .option(\r\n '--payment-token-id <id>',\r\n 'Network-token id (unionpay/visa direct-charge path). Exactly one of ' +\r\n '--payment-token-id / --payment-method-id is required.',\r\n )\r\n .option(\r\n '--payment-method-id <id>',\r\n 'Bound-card id to charge via EVO preauth+capture (fallback path). Exactly one of ' +\r\n '--payment-token-id / --payment-method-id is required.',\r\n )\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'Resume an EVO-card 3DS challenge: merchant trans id of an already-authorised preauth',\r\n )\r\n .option(\r\n '--authenticate',\r\n 'Opt-in to require cardholder 3DS on the network-token direct charge (--payment-token-id, EVO/Mastercard). When a step-up is needed the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume with --authorized-charge-no. Default off = frictionless.',\r\n )\r\n .option(\r\n '--return-url <url>',\r\n 'Optional 3DS/passkey return URL for the network-token authenticate path (falls back to the platform EVO_3DS_RETURN_URL)',\r\n )\r\n .option(\r\n '--authorized-charge-no <no>',\r\n 'Resume a network-token 3DS challenge: charge_no returned by a prior AUTHENTICATION_REQUIRED response (settled via ChargeService.resume_token). When set, the exactly-one-credential rule is relaxed (this is a continuation, not a fresh charge).',\r\n )\r\n .option(\r\n '--evo-explicit',\r\n '[方案 B/R16] Explicit opt-in to settle this pay_per_call ride via the EVO bound-card fallback rail. Set ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side.',\r\n )\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n )\r\n .option(\r\n '--original-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['original-amount-cents'].description,\r\n )\r\n .option(\r\n '--discount-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['discount-amount-cents'].description,\r\n );\r\n\r\n attachSchemaHelp(cmd, ridePayOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n // Validate the target order + payment credentials FIRST — before resolving\r\n // the API key or prompting — so an invalid credential set fails fast and\r\n // never triggers a request to Ride_Service.pay (requirement 11.5).\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n const paymentTokenId = opts.paymentTokenId as string | undefined;\r\n const paymentMethodId = opts.paymentMethodId as string | undefined;\r\n const authorizedChargeNo = opts.authorizedChargeNo as string | undefined;\r\n // 3DS 续付(--authorized-charge-no)是已放行网络令牌扣款的收尾,本身即凭证,不再要求\r\n // token/method 二选一(首扣时已校验过);仅首扣路径强制 exactly-one。\r\n if (authorizedChargeNo === undefined) {\r\n assertExactlyOneCredential(paymentTokenId, paymentMethodId);\r\n }\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. The order reference and the (validated) exactly-one\r\n // payment credential travel in the body; the amount/currency are NOT sent —\r\n // the platform settles at the order's locked authoritative amount and the\r\n // token's minted amount, never a caller-supplied value (requirement 2.6).\r\n const body: Record<string, unknown> = { order_id: orderId };\r\n if (paymentTokenId !== undefined) body.payment_token_id = paymentTokenId;\r\n if (paymentMethodId !== undefined) body.payment_method_id = paymentMethodId;\r\n if (opts.authorizedMerchantTransId !== undefined) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 网络令牌支付时 3DS(opt-in):仅置位时透传 authenticate=true;return_url 可选(缺省平台\r\n // 回落 EVO_3DS_RETURN_URL);authorized_charge_no 是续付句柄。\r\n if (opts.authenticate) body.authenticate = true;\r\n if (opts.returnUrl !== undefined) body.return_url = opts.returnUrl as string;\r\n if (authorizedChargeNo !== undefined) body.authorized_charge_no = authorizedChargeNo;\r\n // 方案 B/R16 显式 EVO 选择信号:仅在置位时透传 evo_explicit=true;缺省则不发(平台默认 false)。\r\n if (opts.evoExplicit) body.evo_explicit = true;\r\n // 价格批注(原价 / 优惠,纯记录):落订单 auth_snapshot + 统一流水并在订单详情回显,\r\n // 不进网关报文、不参与「实扣额 == 锁单权威价」那道核验(金额仍不由调用方决定,R2.6)。\r\n applyPriceAnnotation(body, opts);\r\n\r\n // Confirm before the write unless --yes. This step actually moves money\r\n // (network-token direct charge or EVO preauth+capture) and creates the ride\r\n // upstream. The prompt goes to stderr; declining maps to CLIENT_ABORTED\r\n // (exit 5) via the top-level envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Settle ride order ${orderId}? This charges the card and creates the ride (AWAITING_PAYMENT → PAID).`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Payment aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key: resolved before the request. Under --yes a missing key is\r\n // a hard error and no request is sent. The key is sent as a header, never in\r\n // the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife pay-order',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Settling ride order...');\r\n\r\n const result = await deps.apiClient.post<PayRideOrderResponse>(\r\n '/ride/pay',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<PayRideOrderResponse> = {\r\n data,\r\n text: () => formatPayOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { GetOrderResponse } from '../types/api.js';\r\nimport {\r\n DEFAULT_WATCH_INTERVAL_SECONDS,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n resolveSeconds,\r\n watchRideStatus,\r\n} from './watch.js';\r\nimport { attachSchemaHelp, rideGetSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 3.1 / §4.4.1.3) — a catalog code (exit 1), mirroring the\r\n * sibling quote/book commands' convention.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary, non-watch path only)\r\n// ============================================================\r\n\r\n/**\r\n * Render a single ride order as a key/value block for `--format table`.\r\n * Pickup/dropoff are `from_location`/`to_location` (v3 snake_case, NOT the\r\n * elife `from`/`to` aliases). Amounts are decimal currency units (NOT cents).\r\n */\r\nfunction formatGetOrder(data: GetOrderResponse): string {\r\n const lines: [string, string][] = [\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ];\r\n if (data.source) lines.push(['Source', String(data.source)]);\r\n if (data.is_scheduled !== undefined) lines.push(['Scheduled', String(data.is_scheduled)]);\r\n if (data.from_location) {\r\n lines.push(['From', String(data.from_location.name ?? '-')]);\r\n }\r\n if (data.to_location) {\r\n lines.push(['To', String(data.to_location.name ?? '-')]);\r\n }\r\n if (data.pickup_time !== undefined) lines.push(['Pickup time', String(data.pickup_time)]);\r\n if (data.vehicle_class) lines.push(['Vehicle class', String(data.vehicle_class)]);\r\n if (data.price) {\r\n lines.push(['Price', `${data.price.amount} ${data.price.currency}`]);\r\n }\r\n if (data.final_amount !== undefined && data.final_amount !== null) {\r\n lines.push(['Final amount', String(data.final_amount)]);\r\n }\r\n if (data.final_settlement_status) {\r\n lines.push(['Settlement', String(data.final_settlement_status)]);\r\n }\r\n if (data.driver) {\r\n const driver = data.driver;\r\n const phone = driver.phone_number ? ` (${driver.phone_number})` : '';\r\n lines.push(['Driver', `${driver.name ?? '-'}${phone}`]);\r\n }\r\n if (data.vehicle) {\r\n const v = data.vehicle;\r\n const desc = [v.color, v.make, v.model].filter(Boolean).join(' ') || '-';\r\n const plate = v.license_plate ? ` [${v.license_plate}]` : '';\r\n lines.push(['Vehicle', `${desc}${plate}`]);\r\n }\r\n if (data.created_at) lines.push(['Created at', String(data.created_at)]);\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife get` — fetch a ride order status by id (§4.4.1.3 get schema).\r\n * Read-only (no idempotency key).\r\n *\r\n * Two modes:\r\n * - Non-`--watch`: a single `GET /ride/<id>/status` → `CommandResult` +\r\n * `renderWithContext` (json carries the profile/endpoint envelope).\r\n * - `--watch`: hands off to `watch.ts`, which polls until a terminal status\r\n * or timeout, writing each result as ONE NDJSON line on stdout. The watch\r\n * stream is NOT wrapped in the profile/endpoint envelope (it is a line\r\n * stream); on timeout the final line is `{ watch_status:'timeout', ... }`\r\n * (design Property 2).\r\n *\r\n * Named `registerRideGetCommand` to avoid clashing with the `services get`\r\n * registration.\r\n */\r\nexport function registerRideGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('get')\r\n .description('Retrieve a ride order status by id (repeatable for polling)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Ride order id (the ride_id returned by `ride-elife book`)')\r\n .option('--watch', 'Poll until a terminal status, emitting one NDJSON line per update')\r\n .option(\r\n '--watch-interval <seconds>',\r\n `Seconds between polls when --watch is set (default ${DEFAULT_WATCH_INTERVAL_SECONDS})`,\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n `Max seconds to poll before giving up (default ${DEFAULT_WATCH_TIMEOUT_SECONDS})`,\r\n );\r\n\r\n attachSchemaHelp(cmd, rideGetSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n\r\n // --watch: NDJSON line stream (no profile/endpoint envelope). The stream\r\n // itself is the progress, so no spinner/notify is emitted.\r\n if (opts.watch) {\r\n await watchRideStatus(deps.apiClient, apiKey, orderId, {\r\n intervalSeconds: resolveSeconds(\r\n opts.watchInterval as string | undefined,\r\n DEFAULT_WATCH_INTERVAL_SECONDS,\r\n ),\r\n timeoutSeconds: resolveSeconds(\r\n opts.watchTimeout as string | undefined,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n ),\r\n });\r\n return;\r\n }\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching ride status...');\r\n\r\n const result = await deps.apiClient.get<GetOrderResponse>(\r\n `/ride/${encodeURIComponent(orderId)}/status`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<GetOrderResponse> = {\r\n data,\r\n text: () => formatGetOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { CancelResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, cancelSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 3.3 / §4.4.1.3 cancel schema) — a catalog code (exit 1),\r\n * mirroring the sibling quote/book/get commands' convention.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render a cancelled ride as a key/value block for `--format table`. Amounts\r\n * are decimal currency units (NOT cents) — printed verbatim. `cancellation`\r\n * may be null when the backend reports no fee/reversal breakdown.\r\n */\r\nfunction formatCancel(data: CancelResponse): string {\r\n const lines: [string, string][] = [\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Status', String(data.ride_stat ?? '-')],\r\n ];\r\n if (data.cancellation) {\r\n const c = data.cancellation;\r\n lines.push(['Cancellation fee', `${c.cancellation_fee} ${c.currency}`]);\r\n lines.push(['Reversal amount', `${c.reversal_amount} ${c.currency}`]);\r\n }\r\n if (data.refund_amount !== undefined && data.refund_amount !== null) {\r\n lines.push(['Refund amount', String(data.refund_amount)]);\r\n }\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife cancel` — cancel a ride order by id (§4.4.1.3 cancel schema).\r\n * Write op (W/Y).\r\n *\r\n * `POST /ride/<order-id>/cancel` with NO request body, `X-Api-Key` auth, and\r\n * the `Idempotency-Key` header (key forwarded verbatim, never in the body).\r\n * Cancelling may incur a fee, so the non-`--yes` path MUST confirm before the\r\n * write; `--yes` skips the confirmation. A missing `--idempotency-key` under\r\n * `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED` before any request is sent;\r\n * non-`--yes` prompts for it. Declining the confirmation maps to\r\n * `CLIENT_ABORTED` (exit 5) via the top-level envelope. Renders\r\n * `CancelResponse` via `renderWithContext` (json carries the profile/endpoint\r\n * envelope); the progress line goes to stderr via `notify` and stays silent in\r\n * json mode.\r\n */\r\nexport function registerCancelCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('cancel')\r\n .description('Cancel a ride order by id (may incur a cancellation fee)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Ride order id to cancel (the ride_id returned by book)')\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, cancelSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required input throws PARAM_INVALID before any request is sent (mirrors\r\n // the sibling get/book commands).\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n\r\n // Confirm before the write unless --yes. Cancelling may incur a fee, so the\r\n // prompt warns explicitly (requirement 3.3). The warning/prompt go to\r\n // stderr; declining maps to CLIENT_ABORTED (exit 5) via the top-level\r\n // envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Cancel ride ${orderId}? This may incur a fee.`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Cancellation aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key (requirement 5.3): resolved before the request. Under\r\n // --yes a missing key is a hard error and no request is sent. The key is\r\n // sent as a header, never in the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife cancel',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Cancelling ride...');\r\n\r\n // POST /ride/<id>/cancel carries NO body — only the Idempotency-Key header.\r\n const result = await deps.apiClient.post<CancelResponse>(\r\n `/ride/${encodeURIComponent(orderId)}/cancel`,\r\n { type: 'api-key', key: apiKey },\r\n undefined,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CancelResponse> = {\r\n data,\r\n text: () => formatCancel(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { UpdateResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, rideUpdateSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (a catalog code, exit 1), mirroring the sibling get/cancel commands.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Parse a numeric flag, rejecting non-numbers as `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number | undefined {\r\n if (value === undefined) return undefined;\r\n const parsed = Number(value);\r\n if (!Number.isFinite(parsed)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return parsed;\r\n}\r\n\r\n/** Parse an integer flag, rejecting non-integers as `PARAM_INVALID`. */\r\nfunction int(value: string | undefined, flag: string): number | undefined {\r\n const parsed = num(value, flag);\r\n if (parsed === undefined) return undefined;\r\n if (!Number.isInteger(parsed)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer.`);\r\n }\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Epoch seconds or the literal `now` (same convention as book/quote). Anything\r\n * else is `PARAM_INVALID` — the CLI does not guess at date strings.\r\n */\r\nfunction pickupTime(value: string | undefined): number | string | undefined {\r\n if (value === undefined) return undefined;\r\n if (value === 'now') return 'now';\r\n const parsed = Number(value);\r\n if (!Number.isInteger(parsed)) {\r\n throw new CliError('PARAM_INVALID', \"--pickup-time must be epoch seconds or 'now'.\");\r\n }\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Build a location object only when at least one of its parts was passed, and\r\n * require all three parts together — a half-specified point would silently\r\n * change the route to something the user never asked for.\r\n */\r\nfunction location(\r\n lat: string | undefined,\r\n lng: string | undefined,\r\n name: string | undefined,\r\n side: 'pickup' | 'dropoff',\r\n): { lat: number; lng: number; name: string } | undefined {\r\n if (lat === undefined && lng === undefined && name === undefined) return undefined;\r\n if (lat === undefined || lng === undefined || name === undefined) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `--${side}-lat, --${side}-lng and --${side}-name must be passed together.`,\r\n );\r\n }\r\n return {\r\n lat: num(lat, `${side}-lat`) as number,\r\n lng: num(lng, `${side}-lng`) as number,\r\n name,\r\n };\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/** Render the modification outcome, making the per-side result explicit. */\r\nfunction formatUpdate(data: UpdateResponse): string {\r\n return Formatter.keyValue([\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ['Trip details updated', data.ride_updated ? 'yes' : 'no'],\r\n ['Passenger updated', data.passenger_updated ? 'yes' : 'no'],\r\n ]);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife update` — modify an existing ride order. Write op (W/Y).\r\n *\r\n * `POST /ride/<order-id>/update` with only the fields the caller passed, plus\r\n * the `Idempotency-Key` header (never in the body). Trip-side and passenger-side\r\n * changes are two separate upstream calls with NO transaction, so the response\r\n * reports each side; a partial application surfaces as `UPSTREAM_ERROR` carrying\r\n * `data.partial_update`.\r\n *\r\n * At least one modifiable field is required — an empty update is rejected\r\n * client-side as `PARAM_INVALID` before any request is sent, so we never spend\r\n * an idempotency key on a no-op.\r\n */\r\nexport function registerRideUpdateCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('update')\r\n .description('Modify an existing ride order (trip details and/or passenger)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Ride order id to modify (the ride_id returned by book)')\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n )\r\n .option('--quote-id <id>', 'New quote id when the fare changes')\r\n .option('--vehicle-class <class>', 'New vehicle class')\r\n .option('--price-amount <amount>', 'New fare in decimal currency units (NOT cents)')\r\n .option('--price-currency <code>', 'ISO 4217 currency code for the new fare')\r\n .option('--pickup-lat <lat>', 'New pickup latitude')\r\n .option('--pickup-lng <lng>', 'New pickup longitude')\r\n .option('--pickup-name <name>', 'New pickup location name')\r\n .option('--dropoff-lat <lat>', 'New dropoff latitude')\r\n .option('--dropoff-lng <lng>', 'New dropoff longitude')\r\n .option('--dropoff-name <name>', 'New dropoff location name')\r\n .option('--pickup-time <time>', \"New pickup time: epoch seconds or 'now'\")\r\n .option('--meet-and-greet', 'Enable meet & greet service')\r\n .option('--no-meet-and-greet', 'Disable meet & greet service')\r\n .option('--welcome-sign <text>', 'New welcome sign text (meet & greet)')\r\n .option('--arrival-flight-no <no>', 'New arrival flight number')\r\n .option('--arrival-airline <name>', 'New arrival airline name')\r\n .option('--departure-flight-no <no>', 'New departure flight number')\r\n .option('--departure-airline <name>', 'New departure airline name')\r\n .option('--service-area-id <id>', 'Service area id, when the upstream requires re-scoping')\r\n .option('--passenger-name <name>', 'New passenger full name')\r\n .option('--passenger-phone <phone>', 'New passenger phone (E.164)')\r\n .option('--passenger-email <email>', 'New passenger email')\r\n .option('--luggage-count <count>', 'New luggage count');\r\n\r\n attachSchemaHelp(cmd, rideUpdateSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n\r\n // `--meet-and-greet` / `--no-meet-and-greet` are only meaningful when the\r\n // user actually passed one: commander materialises `meetAndGreet: true` by\r\n // default for `--no-` pairs, so an untouched flag must stay out of the body.\r\n const mgTouched = process.argv.some(\r\n (a) => a === '--meet-and-greet' || a === '--no-meet-and-greet',\r\n );\r\n\r\n const body: Record<string, unknown> = {};\r\n const set = (key: string, value: unknown): void => {\r\n if (value !== undefined) body[key] = value;\r\n };\r\n set('quote_id', opts.quoteId as string | undefined);\r\n set('vehicle_class', opts.vehicleClass as string | undefined);\r\n set('price_amount', num(opts.priceAmount as string | undefined, 'price-amount'));\r\n set('price_currency', opts.priceCurrency as string | undefined);\r\n set(\r\n 'pickup',\r\n location(\r\n opts.pickupLat as string | undefined,\r\n opts.pickupLng as string | undefined,\r\n opts.pickupName as string | undefined,\r\n 'pickup',\r\n ),\r\n );\r\n set(\r\n 'dropoff',\r\n location(\r\n opts.dropoffLat as string | undefined,\r\n opts.dropoffLng as string | undefined,\r\n opts.dropoffName as string | undefined,\r\n 'dropoff',\r\n ),\r\n );\r\n set('pickup_time', pickupTime(opts.pickupTime as string | undefined));\r\n if (mgTouched) set('meet_and_greet', Boolean(opts.meetAndGreet));\r\n set('welcome_sign', opts.welcomeSign as string | undefined);\r\n if (opts.arrivalFlightNo !== undefined || opts.arrivalAirline !== undefined) {\r\n set('arrival_flight', {\r\n flight_no: opts.arrivalFlightNo as string | undefined,\r\n airline: opts.arrivalAirline as string | undefined,\r\n });\r\n }\r\n if (opts.departureFlightNo !== undefined || opts.departureAirline !== undefined) {\r\n set('departure_flight', {\r\n flight_no: opts.departureFlightNo as string | undefined,\r\n airline: opts.departureAirline as string | undefined,\r\n });\r\n }\r\n set('service_area_id', opts.serviceAreaId as string | undefined);\r\n set('passenger_name', opts.passengerName as string | undefined);\r\n set('passenger_phone', opts.passengerPhone as string | undefined);\r\n set('passenger_email', opts.passengerEmail as string | undefined);\r\n set('luggage_count', int(opts.luggageCount as string | undefined, 'luggage-count'));\r\n\r\n // Reject an empty update before spending an idempotency key on a no-op.\r\n if (Object.keys(body).length === 0) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Nothing to update. Pass at least one trip field or one passenger-* flag.',\r\n );\r\n }\r\n\r\n // Confirm before the write unless --yes: a modification can re-price the\r\n // ride upstream. Declining maps to CLIENT_ABORTED (exit 5).\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Apply ${Object.keys(body).length} change(s) to ride ${orderId}? The fare may change.`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Update aborted by user.');\r\n }\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife update',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Updating ride...');\r\n\r\n const result = await deps.apiClient.post<UpdateResponse>(\r\n `/ride/${encodeURIComponent(orderId)}/update`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<UpdateResponse> = {\r\n data,\r\n text: () => formatUpdate(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { TripStatusResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, rideTripStatusSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/** Missing required input maps to `PARAM_INVALID` (catalog code, exit 1). */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Leg index is 1-based; 0 or negative is a client-side `PARAM_INVALID`. */\r\nfunction tripNo(value: string | undefined): number {\r\n if (value === undefined) return 1;\r\n const parsed = Number(value);\r\n if (!Number.isInteger(parsed) || parsed < 1) {\r\n throw new CliError('PARAM_INVALID', '--trip-no must be an integer >= 1.');\r\n }\r\n return parsed;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render one leg's status. Location points are summarised (count + latest\r\n * sample) rather than dumped — a long ride can carry hundreds of points, and\r\n * `--format json` is the right channel for the full array.\r\n */\r\nfunction formatTripStatus(data: TripStatusResponse): string {\r\n const lines: [string, string][] = [\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Trip no', String(data.trip_no ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ];\r\n const points = data.points ?? [];\r\n lines.push(['Location points', String(points.length)]);\r\n const latest = points[points.length - 1];\r\n if (latest) {\r\n lines.push(['Latest position', `${latest.lat}, ${latest.lng} @ ${latest.utc_timestamp}`]);\r\n }\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife trip-status` — status of ONE leg of a multi-leg ride. Read-only\r\n * (no idempotency key).\r\n *\r\n * `GET /ride/<order-id>/trips/<trip-no>`. Single-shot only: whole-ride polling\r\n * belongs to `ride-elife get --watch`, and duplicating a watch loop here would\r\n * give two competing pollers for the same ride.\r\n */\r\nexport function registerRideTripStatusCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('trip-status')\r\n .description('Retrieve the status and driver location points of one leg of a ride')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Ride order id (the ride_id returned by `ride-elife book`)')\r\n .option('--trip-no <no>', '1-based leg index (default 1)');\r\n\r\n attachSchemaHelp(cmd, rideTripStatusSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n const leg = tripNo(opts.tripNo as string | undefined);\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching trip status...');\r\n\r\n const result = await deps.apiClient.get<TripStatusResponse>(\r\n `/ride/${encodeURIComponent(orderId)}/trips/${leg}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<TripStatusResponse> = {\r\n data,\r\n text: () => formatTripStatus(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { ListOrdersResponse, RideOrderListItem } from '../types/api.js';\r\nimport { attachSchemaHelp, listOrdersSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\nconst DEFAULT_PAGE = '1';\r\nconst DEFAULT_PAGE_SIZE = '20';\r\n\r\n/**\r\n * Number-ify a pagination flag. Non-finite / non-integer / non-positive input\r\n * maps to `PARAM_INVALID` (catalog code, exit 1) — mirroring the sibling\r\n * quote/get/cancel commands' convention. Returns the canonical string form to\r\n * be passed through as a query parameter.\r\n */\r\nfunction positiveInt(value: string, flag: string): string {\r\n const n = Number(value);\r\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\r\n }\r\n return String(n);\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the order list as a table for `--format table`. Each order is one\r\n * row; amounts are decimal currency units (NOT cents) — printed verbatim.\r\n */\r\nfunction formatOrders(data: ListOrdersResponse): string {\r\n const orders: RideOrderListItem[] = data.orders ?? [];\r\n if (orders.length === 0) {\r\n return Formatter.status('info', 'No ride orders found');\r\n }\r\n\r\n const headers = ['Order ID', 'Ride ID', 'Status', 'Vehicle Class', 'Price', 'Currency', 'Payment'];\r\n const rows = orders.map((o) => [\r\n String(o.order_id ?? '-'),\r\n String(o.ride_id ?? '-'),\r\n String(o.status ?? '-'),\r\n String(o.vehicle_class ?? '-'),\r\n String(o.price_amount ?? '-'),\r\n String(o.price_currency ?? '-'),\r\n String(o.payment_status ?? '-'),\r\n ]);\r\n\r\n const summary: [string, string][] = [\r\n ['Total', String(data.total ?? '-')],\r\n ['Page', String(data.page ?? '-')],\r\n ['Page size', String(data.page_size ?? '-')],\r\n ];\r\n\r\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(summary)}`;\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife list-orders` — list previously placed ride orders (§4.4.1.3\r\n * list-orders schema). Read-only (no idempotency key).\r\n *\r\n * Passes `--page`(default 1) / `--page-size`(default 20) / `--status` /\r\n * `--order-type` through as query parameters to `GET /ride/orders` with the\r\n * `X-Api-Key` auth, and renders `ListOrdersResponse` via `renderWithContext`\r\n * (json carries the profile/endpoint envelope). `page`/`page-size` are\r\n * validated as positive integers (invalid → `PARAM_INVALID`); `status` /\r\n * `order-type` are forwarded verbatim only when set. The progress line is\r\n * emitted through `notify` so it goes to stderr and stays silent in json mode.\r\n */\r\nexport function registerListOrdersCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('list-orders')\r\n .description('List previously placed ride orders')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--page <page>', 'Page number', DEFAULT_PAGE)\r\n .option('--page-size <size>', 'Page size', DEFAULT_PAGE_SIZE)\r\n .option('--status <status>', 'Filter by order status')\r\n .option('--order-type <type>', 'Filter by order type')\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n\r\n attachSchemaHelp(cmd, listOrdersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build query params. page/page-size are validated as positive integers\r\n // (invalid → PARAM_INVALID before any request); status/order-type are\r\n // forwarded verbatim only when set. Sent as a query string, never a body.\r\n const params: Record<string, string> = {\r\n page: positiveInt((opts.page as string | undefined) ?? DEFAULT_PAGE, 'page'),\r\n page_size: positiveInt((opts.pageSize as string | undefined) ?? DEFAULT_PAGE_SIZE, 'page-size'),\r\n };\r\n if (opts.status !== undefined) params.status = opts.status as string;\r\n if (opts.orderType !== undefined) params.order_type = opts.orderType as string;\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) params.member_id = member;\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching orders...');\r\n\r\n const result = await deps.apiClient.get<ListOrdersResponse>(\r\n '/ride/orders',\r\n { type: 'api-key', key: apiKey },\r\n params,\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<ListOrdersResponse> = {\r\n data,\r\n text: () => formatOrders(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n notify,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport {\r\n attachSchemaHelp,\r\n rideCallbackSetSchema,\r\n rideCallbackGetSchema,\r\n rideCallbackDefaultSetSchema,\r\n rideCallbackDefaultGetSchema,\r\n rideCallbackDeliveriesSchema,\r\n rideCallbackReplaySchema,\r\n} from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n/**\r\n * Ride status-callback commands — thin wrappers over the platform's callback routes:\r\n *\r\n * callback-set POST /ride/<order-id>/callback (per-ride destination)\r\n * callback-get GET /ride/<order-id>/callback\r\n * callback-default-set POST /ride/callback/default (developer-wide fallback)\r\n * callback-default-get GET /ride/callback/default\r\n * callback-deliveries GET /ride/<order-id>/callback/deliveries\r\n * callback-replay POST /ride/<order-id>/callback/replay\r\n *\r\n * The platform enforces ownership (another developer's ride reads as not found) and the\r\n * https / non-internal URL rule (SSRF guard); the CLI only checks shape. The signing secret\r\n * comes back exactly once, in the set response that issued it — it is printed with a warning\r\n * and never retrievable again.\r\n */\r\n\r\nconst SIGNATURE_MODES = ['off', 'optional', 'required'] as const;\r\nconst DELIVERIES_LIMIT_MAX = 100;\r\n\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || String(value).trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return String(value);\r\n}\r\n\r\nfunction intFlag(value: string | undefined, flag: string, min: number, max?: number): number | undefined {\r\n if (value === undefined) return undefined;\r\n const parsed = Number(value);\r\n if (!Number.isInteger(parsed) || parsed < min || (max !== undefined && parsed > max)) {\r\n const range = max === undefined ? `>= ${min}` : `${min}-${max}`;\r\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer ${range}.`);\r\n }\r\n return parsed;\r\n}\r\n\r\nasync function apiKeyOf(opts: Record<string, unknown>): Promise<string> {\r\n return PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n}\r\n\r\n/** Body shared by per-ride and default registration. Omitted flags are not sent (server keeps the stored value). */\r\nfunction subscriptionBody(opts: Record<string, unknown>): Record<string, unknown> {\r\n const body: Record<string, unknown> = { callback_url: need(opts.callbackUrl as string | undefined, 'callback-url') };\r\n if (opts.adapter !== undefined) body.adapter = need(opts.adapter as string, 'adapter');\r\n if (opts.signatureMode !== undefined) {\r\n const mode = String(opts.signatureMode);\r\n if (!(SIGNATURE_MODES as readonly string[]).includes(mode)) {\r\n throw new CliError('PARAM_INVALID', `--signature-mode must be one of ${SIGNATURE_MODES.join(' / ')}.`);\r\n }\r\n body.signature_mode = mode;\r\n }\r\n if (opts.callbackApiKey !== undefined) body.callback_api_key = String(opts.callbackApiKey);\r\n if (opts.rotateSecret) body.rotate_secret = true;\r\n return body;\r\n}\r\n\r\nfunction formatSubscription(data: Record<string, unknown>): string {\r\n const lines: [string, string][] = [];\r\n for (const key of ['ride_id', 'order_id', 'developer_id', 'callback_url', 'adapter', 'signature_mode', 'status']) {\r\n if (data[key] !== undefined && data[key] !== null) lines.push([key, String(data[key])]);\r\n }\r\n const out = [Formatter.keyValue(lines)];\r\n if (typeof data.callback_secret === 'string' && data.callback_secret) {\r\n out.push('', Formatter.keyValue([['callback_secret', data.callback_secret]]));\r\n out.push('Save this signing secret now — it is shown only once and cannot be read back.');\r\n }\r\n return out.join('\\n');\r\n}\r\n\r\ntype Format = ReturnType<typeof resolveFormat>;\r\n\r\nasync function render<T>(data: T, text: () => string, format: Format): Promise<void> {\r\n const commandResult: CommandResult<T> = { data, text };\r\n await renderWithContext(commandResult, { format }, new ConfigManager());\r\n}\r\n\r\nfunction withSubscriptionFlags(cmd: Command): Command {\r\n return cmd\r\n .option('--callback-url <url>', 'https URL that receives ride status events (must not be an internal address)')\r\n .option('--adapter <name>', 'Outbound event shape (default techtanium_v1)')\r\n .option('--signature-mode <mode>', 'off / optional / required (default off)')\r\n .option('--callback-api-key <key>', 'API key the platform sends to your endpoint; omit to keep the stored one')\r\n .option('--rotate-secret', 'Issue a new HMAC signing secret (breaks verification with the old one)')\r\n .option('--idempotency-key <key>', 'Idempotency key forwarded verbatim as the Idempotency-Key header');\r\n}\r\n\r\nasync function postSubscription(\r\n deps: { apiClient: ApiClient },\r\n cmd: Command,\r\n path: (opts: Record<string, unknown>) => string,\r\n commandPath: string,\r\n doneMessage: string,\r\n): Promise<void> {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const target = path(opts);\r\n const body = subscriptionBody(opts);\r\n const apiKey = await apiKeyOf(opts);\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: Boolean(opts.yes),\r\n commandPath,\r\n });\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n target,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n notify(format, 'success', doneMessage);\r\n await render(result.data, () => formatSubscription(result.data), format);\r\n}\r\n\r\nasync function getJson(\r\n deps: { apiClient: ApiClient },\r\n cmd: Command,\r\n path: (opts: Record<string, unknown>) => string,\r\n text: (data: Record<string, unknown>) => string,\r\n params?: (opts: Record<string, unknown>) => Record<string, string> | undefined,\r\n): Promise<void> {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const target = path(opts);\r\n const query = params?.(opts);\r\n const apiKey = await apiKeyOf(opts);\r\n const result = await deps.apiClient.get<Record<string, unknown>>(target, { type: 'api-key', key: apiKey }, query);\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, () => text(result.data), format);\r\n}\r\n\r\nconst ridePath = (opts: Record<string, unknown>, suffix: string): string =>\r\n `/ride/${encodeURIComponent(need(opts.orderId as string | undefined, 'order-id'))}/callback${suffix}`;\r\n\r\nexport function registerRideCallbackCommands(parent: Command, deps: { apiClient: ApiClient }): void {\r\n // callback-set\r\n const set = withSubscriptionFlags(\r\n parent\r\n .command('callback-set')\r\n .description('Register (or update) where one ride\\'s status events are forwarded')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The numeric ride_id returned by book'),\r\n );\r\n attachSchemaHelp(set, rideCallbackSetSchema);\r\n set.action(() =>\r\n postSubscription(deps, set, (o) => ridePath(o, ''), 'ride-elife callback-set', 'Ride callback registered'),\r\n );\r\n\r\n // callback-get\r\n const get = parent\r\n .command('callback-get')\r\n .description('Show one ride\\'s callback registration (the signing secret is never returned)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The numeric ride_id returned by book');\r\n attachSchemaHelp(get, rideCallbackGetSchema);\r\n get.action(() => getJson(deps, get, (o) => ridePath(o, ''), formatSubscription));\r\n\r\n // callback-default-set\r\n const defSet = withSubscriptionFlags(\r\n parent\r\n .command('callback-default-set')\r\n .description('Register (or update) the developer-wide fallback for rides without their own callback')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)'),\r\n );\r\n attachSchemaHelp(defSet, rideCallbackDefaultSetSchema);\r\n defSet.action(() =>\r\n postSubscription(\r\n deps,\r\n defSet,\r\n () => '/ride/callback/default',\r\n 'ride-elife callback-default-set',\r\n 'Default ride callback registered',\r\n ),\r\n );\r\n\r\n // callback-default-get\r\n const defGet = parent\r\n .command('callback-default-get')\r\n .description('Show the developer-wide fallback callback (the signing secret is never returned)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n attachSchemaHelp(defGet, rideCallbackDefaultGetSchema);\r\n defGet.action(() => getJson(deps, defGet, () => '/ride/callback/default', formatSubscription));\r\n\r\n // callback-deliveries\r\n const deliveries = parent\r\n .command('callback-deliveries')\r\n .description('List one ride\\'s callback forwarding records (pending / delivered / dead)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The numeric ride_id returned by book')\r\n .option('--limit <n>', `Page size 1-${DELIVERIES_LIMIT_MAX} (default 50)`)\r\n .option('--offset <n>', 'Records to skip (default 0)');\r\n attachSchemaHelp(deliveries, rideCallbackDeliveriesSchema);\r\n deliveries.action(() =>\r\n getJson(\r\n deps,\r\n deliveries,\r\n (o) => ridePath(o, '/deliveries'),\r\n (data) => {\r\n const rows = (data.deliveries as Record<string, unknown>[] | undefined) ?? [];\r\n if (rows.length === 0) return Formatter.status('info', 'No callback deliveries');\r\n return Formatter.table(\r\n ['Event', 'Status', 'Attempts', 'Last error'],\r\n rows.map((r) => [\r\n String(r.event_id ?? '-'),\r\n String(r.status ?? '-'),\r\n String(r.attempts ?? '-'),\r\n String(r.last_error ?? '-'),\r\n ]),\r\n );\r\n },\r\n (o) => {\r\n const limit = intFlag(o.limit as string | undefined, 'limit', 1, DELIVERIES_LIMIT_MAX);\r\n const offset = intFlag(o.offset as string | undefined, 'offset', 0);\r\n const params: Record<string, string> = {};\r\n if (limit !== undefined) params.limit = String(limit);\r\n if (offset !== undefined) params.offset = String(offset);\r\n return Object.keys(params).length > 0 ? params : undefined;\r\n },\r\n ),\r\n );\r\n\r\n // callback-replay\r\n const replay = parent\r\n .command('callback-replay')\r\n .description('Requeue one ride\\'s dead (or failed) callback records; delivered records are never re-sent')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The numeric ride_id returned by book')\r\n .option('--event-id <id>', 'Requeue only this record (default: all dead records of the ride)')\r\n .option('--include-failed', 'Also requeue pending records that already failed at least once')\r\n .option('--reset-attempts', 'Reset the retry counter of requeued records')\r\n .option('--idempotency-key <key>', 'Idempotency key forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(replay, rideCallbackReplaySchema);\r\n replay.action(async () => {\r\n const opts = replay.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const target = ridePath(opts, '/replay');\r\n const body: Record<string, unknown> = {};\r\n if (opts.eventId !== undefined) body.event_id = need(opts.eventId as string, 'event-id');\r\n if (opts.includeFailed) body.include_failed = true;\r\n if (opts.resetAttempts) body.reset_attempts = true;\r\n const apiKey = await apiKeyOf(opts);\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: Boolean(opts.yes),\r\n commandPath: 'ride-elife callback-replay',\r\n });\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n target,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n notify(format, 'success', `Requeued ${String(result.data.requeued ?? 0)} callback record(s)`);\r\n await render(\r\n result.data,\r\n () => Formatter.keyValue([\r\n ['Ride ID', String(result.data.ride_id ?? '-')],\r\n ['Requeued', String(result.data.requeued ?? 0)],\r\n ]),\r\n format,\r\n );\r\n });\r\n}\r\n","/**\r\n * Built-in static capability registry (D4, merchant-domain only).\r\n *\r\n * NOTE: this is a CLI-bundled, single-merchant catalog — NOT a live backend\r\n * discovery feed. It does not reflect which services are enabled for the\r\n * current API key, nor the developer's billing mode (that is a per-developer\r\n * property decided by the backend, surfaced via the `book` response /\r\n * error codes, not advertised here). The §4.4.1 backend `/services` discovery\r\n * endpoint (BACK-063) + top-level `billing` block + `page` cursor are pending\r\n * impl; until they land, `services list/get` read this table.\r\n *\r\n * Each entry describes a CLI-exposed service: which `cli_noun` group hosts it,\r\n * the verbs it offers (with one-line descriptions), the recommended call\r\n * `workflow`, and discovery hints. `services list` renders a summary of these\r\n * entries and `services get <service-id>` returns one in full.\r\n *\r\n * `ServiceCapability` / the registry are merchant-domain specific (only\r\n * merchant-cli uses them) and stay in the app — they are NOT lifted to\r\n * `@agenzo/cli-core`.\r\n */\r\n\r\n/** Discovery hints for a capability (§4.4.1 schema). */\r\nexport interface ServiceDiscovery {\r\n /** Command an agent can run to discover the verbs in detail. */\r\n help_command: string;\r\n /**\r\n * Capability-layer schema download URL (the provider's aggregate\r\n * `schema/<cli_noun>.json`, mirrored by its `schema_ref.schema_url`). The\r\n * aggregate HTTP endpoint is reserved/pending; until it lands, agents use\r\n * `help_command` (`<noun> <verb> --help --format json`) for the live schema.\r\n */\r\n schema_url?: string;\r\n}\r\n\r\nexport interface ServiceCapability {\r\n service_id: string;\r\n name: string;\r\n description: string;\r\n /** Service category (e.g. `ride`); part of the §4.4.1 schema form. */\r\n category: string;\r\n version: string;\r\n /** Upstream capability provider. */\r\n provider: string;\r\n /** Top-level CLI noun (command group) that hosts this service's verbs (`<category>-<provider>`). */\r\n cli_noun: string;\r\n /** Verb names exposed under `cli_noun`. */\r\n verbs: string[];\r\n /** One-line description per verb, keyed by verb name. */\r\n verb_descriptions: Record<string, string>;\r\n /** Ordered call sequence; `[cancel]` is optional. */\r\n workflow: string[];\r\n /** ISO date the capability became available. */\r\n since: string;\r\n discovery: ServiceDiscovery;\r\n}\r\n\r\n/** Static registry. This iteration ships ride-elife and hotel-redaug capabilities. */\r\nexport const SERVICE_REGISTRY: ServiceCapability[] = [\r\n {\r\n // Agent-facing service_id = cli_noun(Agent 拼命令用这个标识)。\r\n // 平台级不透明内部 ULID: svc_01KWTPBWDH5YZ52H717BFVWZA8(与后端\r\n // services/merchant_service/discovery/catalog.py 的 RIDE_ELIFE_SERVICE_ID 对应)。\r\n service_id: 'ride-elife',\r\n name: 'Ride hailing (eLife)',\r\n description: 'On-demand ride ordering: quote a fare, book it, poll status, and cancel.',\r\n category: 'ride',\r\n version: '1.0.0',\r\n provider: 'elife',\r\n cli_noun: 'ride-elife',\r\n verbs: ['quote', 'book', 'get', 'cancel', 'update', 'trip-status', 'list-orders'],\r\n verb_descriptions: {\r\n quote: 'Request fare quotes for a ride between two points.',\r\n book: 'Book a ride using a quote_id returned by quote.',\r\n get: 'Retrieve a ride order by id (poll for status changes with --watch).',\r\n cancel: 'Cancel a ride order by id (may incur a fee).',\r\n update: 'Modify a booked ride: trip details and/or passenger info.',\r\n 'trip-status': 'Retrieve status and driver location points for one leg of a multi-leg ride.',\r\n 'list-orders': 'List previously placed ride orders.',\r\n },\r\n workflow: [\r\n 'quote',\r\n 'book',\r\n 'get (poll for status)',\r\n 'update (optional)',\r\n 'trip-status (optional, multi-leg rides)',\r\n 'cancel (optional)',\r\n ],\r\n since: '2026-06-01',\r\n discovery: {\r\n help_command: 'agenzo-merchant-cli ride-elife --help',\r\n },\r\n },\r\n {\r\n service_id: 'hotel-redaug',\r\n name: 'Hotel booking (Redaug)',\r\n description:\r\n 'International hotel booking via Redaug: search by location, real-time room/rate availability, two-step create-then-pay flow supporting monthly_settlement and pay_per_call (EVO) billing modes, cancel and partial check-out.',\r\n category: 'hotel',\r\n version: 'v1',\r\n provider: 'redaug',\r\n cli_noun: 'hotel-redaug',\r\n verbs: [\r\n 'find-destination',\r\n 'hotel-filters',\r\n 'list-cities',\r\n 'search',\r\n 'hotel-detail',\r\n 'quote',\r\n 'create-order',\r\n 'pay-order',\r\n 'get',\r\n 'cancel',\r\n 'checkout',\r\n 'get-checkout',\r\n 'list-orders',\r\n ],\r\n verb_descriptions: {\r\n 'find-destination': 'Resolve a free-text place into destinations.',\r\n 'hotel-filters': 'Get available filter options for a location.',\r\n 'list-cities': 'List the cities of a country.',\r\n search: 'Search hotels by destination or coordinates.',\r\n 'hotel-detail': 'Get hotel detail (name/star/address/facilities/photos).',\r\n quote: 'Get real-time room types and bookable rates for a hotel.',\r\n 'create-order': 'Create a hotel order without charging (locks the rate, no payment).',\r\n 'pay-order': 'Settle a created order by --order-id (path chosen server-side by billing_mode: monthly_settlement or pay_per_call).',\r\n get: 'Query order status (poll for async confirmation).',\r\n cancel: 'Cancel an order (whole-order, in-policy).',\r\n checkout: 'Apply for partial check-out / out-of-policy cancellation.',\r\n 'get-checkout': 'Poll a check-out application status.',\r\n 'list-orders': 'List hotel orders (local store, no upstream call).',\r\n },\r\n workflow: [\r\n 'find-destination / list-cities (optional)',\r\n 'hotel-filters (optional)',\r\n 'search',\r\n 'hotel-detail (optional)',\r\n 'quote',\r\n 'create-order (locks the rate, no charge)',\r\n 'pay-order (settles: monthly_settlement or pay_per_call)',\r\n 'get (poll until CONFIRMED)',\r\n 'cancel / checkout (optional)',\r\n ],\r\n since: '2026-06-25',\r\n discovery: {\r\n help_command: 'agenzo-merchant-cli hotel-redaug --help',\r\n },\r\n },\r\n {\r\n // 与后端 services/merchant_service/discovery/catalog.py 的 flight-flink 条目 + provider\r\n // schema flight-flink.json 的 service_id 保持一致。Agent 拼命令用 cli_noun=\"flight-flink\"。\r\n service_id: 'svc_01J0HT5FLINK0001',\r\n name: 'Flight booking (Flink)',\r\n description:\r\n 'International flight booking: airport/city resolution, one-way/round-trip/multi-city search with journeyId relay, price verification, two-step create-then-pay ticketing, order polling, plus change (rebooking) and refund flows.',\r\n category: 'flight',\r\n version: '1.0.0',\r\n provider: 'flink',\r\n cli_noun: 'flight-flink',\r\n verbs: [\r\n 'find-airport',\r\n 'list-airports',\r\n 'list-airlines',\r\n 'list-nationalities',\r\n 'search',\r\n 'more-offers',\r\n 'verify',\r\n 'create-order',\r\n 'pay-order',\r\n 'get-order',\r\n 'cancel-order',\r\n 'list-orders',\r\n 'change-search',\r\n 'change-apply',\r\n 'change-detail',\r\n 'change-pay',\r\n 'change-cancel',\r\n 'refund-apply',\r\n 'refund-detail',\r\n 'refund-confirm',\r\n ],\r\n verb_descriptions: {\r\n 'find-airport': 'Resolve free-text into city/airport candidates.',\r\n 'list-airports': 'Paged airport dictionary.',\r\n 'list-airlines': 'Paged airline dictionary.',\r\n 'list-nationalities': 'Nationality list.',\r\n search: 'Search flights (one-way/round-trip/multi-city) with journeyId relay.',\r\n 'more-offers': 'More fare offers for a priceKey.',\r\n verify: 'Verify the latest price before booking; returns the authoritative product_token.',\r\n 'create-order': 'Create a flight order without charging (locks the fare).',\r\n 'pay-order': 'Settle a created order by --order-no (triggers ticketing).',\r\n 'get-order': 'Query order status (poll ticketing 5→8).',\r\n 'cancel-order': 'Cancel an un-ticketed order (with refund).',\r\n 'list-orders': 'List flight orders (local store, no upstream call).',\r\n 'change-search': 'Search rebook-eligible flights.',\r\n 'change-apply': 'Submit a change request (pending review).',\r\n 'change-detail': 'Change request detail.',\r\n 'change-pay': 'Pay the change fee and trigger change ticketing.',\r\n 'change-cancel': 'Cancel a change request (immediate terminal).',\r\n 'refund-apply': 'Submit a refund request (pending review).',\r\n 'refund-detail': 'Refund request detail.',\r\n 'refund-confirm': 'Confirm (\"1\") or cancel (\"2\") a refund.',\r\n },\r\n workflow: [\r\n 'find-airport',\r\n 'search (relay journey-id for round-trip/multi-city)',\r\n 'verify',\r\n 'create-order (locks the fare, no charge)',\r\n 'pay-order (settles + ticketing)',\r\n 'get-order (poll until TICKETED)',\r\n 'change-* / refund-* / cancel-order (optional)',\r\n ],\r\n since: '2026-07-09',\r\n discovery: {\r\n help_command: 'agenzo-merchant-cli flight-flink --help',\r\n },\r\n },\r\n];\r\n\r\n/** Look up a capability by its service_id or cli_noun. Returns undefined when not found. */\r\nexport function findService(serviceId: string): ServiceCapability | undefined {\r\n return SERVICE_REGISTRY.find((s) => s.service_id === serviceId || s.cli_noun === serviceId);\r\n}\r\n","import { Command } from 'commander';\r\n\r\n/**\r\n * Map of `cli_noun` → the verb names this CLI binary actually registers.\r\n *\r\n * This is the CLI's local source of truth for \"what can I execute\". It is built\r\n * by introspecting the commander program's command tree — NOT from any bundled\r\n * schema. The discovery gate intersects backend capabilities against this map so\r\n * the Agent never sees a service/verb the local CLI cannot run.\r\n */\r\nexport type LocalCapabilityMap = Record<string, string[]>;\r\n\r\n/** Command groups that are NOT discoverable services (utility groups). */\r\nconst NON_SERVICE_NOUNS = new Set(['services', 'help', 'config']);\r\n\r\n/**\r\n * Build the local capability map from the commander program: each top-level\r\n * command group (noun) → its registered subcommand (verb) names.\r\n *\r\n * Excludes utility groups (e.g. `services` itself) and any command with no\r\n * subcommands (those are not service nouns).\r\n */\r\nexport function buildLocalCapabilityMap(program: Command): LocalCapabilityMap {\r\n const map: LocalCapabilityMap = {};\r\n for (const noun of program.commands) {\r\n const name = noun.name();\r\n if (NON_SERVICE_NOUNS.has(name)) continue;\r\n const verbs = noun.commands.map((v) => v.name()).filter((n) => n !== 'help');\r\n if (verbs.length === 0) continue;\r\n map[name] = verbs;\r\n }\r\n return map;\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n Formatter,\r\n PromptEngine,\r\n CliError,\r\n resolveFormat,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { SERVICE_REGISTRY } from './registry.js';\r\nimport { buildLocalCapabilityMap, type LocalCapabilityMap } from './local-caps.js';\r\n\r\n/**\r\n * Summary view of a capability for `services list` output. Lightweight on\r\n * purpose — the full schema (incl. per-verb detail) is fetched via `services\r\n * get`. Heavy fields (verb_descriptions / workflow / description / schema_content)\r\n * are deliberately omitted here.\r\n */\r\ninterface ServiceListItem {\r\n service_id: string;\r\n name: string;\r\n category: string;\r\n provider: string;\r\n cli_noun: string;\r\n version: string;\r\n verbs: string[];\r\n since: string;\r\n discovery?: unknown;\r\n}\r\n\r\n/**\r\n * Normalize any capability-like record — a backend discovery item OR a local\r\n * registry entry — down to the lightweight list summary. Both sources share\r\n * field names, so one normalizer keeps `list` output identical regardless of\r\n * where it came from and prevents heavy fields from leaking in.\r\n */\r\nfunction toListItem(s: Record<string, unknown>): ServiceListItem {\r\n return {\r\n service_id: String(s.service_id ?? ''),\r\n name: String(s.name ?? ''),\r\n category: String(s.category ?? ''),\r\n provider: String(s.provider ?? ''),\r\n cli_noun: String(s.cli_noun ?? ''),\r\n version: String(s.version ?? ''),\r\n verbs: Array.isArray(s.verbs) ? (s.verbs as string[]) : [],\r\n since: String(s.since ?? ''),\r\n discovery: s.discovery,\r\n };\r\n}\r\n\r\n/**\r\n * Gate backend capabilities against what this CLI binary can actually execute.\r\n *\r\n * The schema lives on the backend (dynamic); the CLI does NOT bundle it. The\r\n * gate uses the CLI's own command tree (`localCaps`): a capability is kept only\r\n * if this CLI registers its `cli_noun`, and its `verbs` are intersected with the\r\n * locally-registered verbs (so a verb the CLI doesn't implement is never shown).\r\n * Capabilities with no executable verb are dropped entirely — the Agent never\r\n * sees a service/verb it cannot run.\r\n */\r\nfunction gateByLocalCommands(\r\n capabilities: ServiceListItem[],\r\n localCaps: LocalCapabilityMap,\r\n): ServiceListItem[] {\r\n const gated: ServiceListItem[] = [];\r\n for (const cap of capabilities) {\r\n const localVerbs = localCaps[cap.cli_noun];\r\n if (!localVerbs) continue; // CLI doesn't have this noun at all → hide\r\n const usableVerbs = (cap.verbs || []).filter((v) => localVerbs.includes(v));\r\n if (usableVerbs.length === 0) continue; // nothing executable → hide\r\n gated.push({ ...cap, verbs: usableVerbs });\r\n }\r\n return gated;\r\n}\r\n\r\n/**\r\n * `services list` — discover available merchant capabilities.\r\n *\r\n * Primary path: call the platform discovery API (`GET /api/discovery/v1/catalog`),\r\n * then gate the result against this CLI's command tree (see gateByLocalCommands)\r\n * so only services/verbs this binary can run are shown.\r\n *\r\n * Fallback: if the platform is unreachable, fall back to the CLI-bundled local\r\n * registry (offline usability), gated the same way.\r\n */\r\nexport function registerServicesListCommand(\r\n parent: Command,\r\n deps: { discoveryClient: ApiClient; program: Command },\r\n): void {\r\n const cmd = parent\r\n .command('list')\r\n .description('List available merchant services (from platform discovery)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const localCaps = buildLocalCapabilityMap(deps.program);\r\n\r\n let services: ServiceListItem[];\r\n\r\n try {\r\n // Resolve API key (required for the discovery endpoint).\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Discovery lives at /api/discovery/v1/catalog (host root, not the merchant\r\n // prefix); deps.discoveryClient is built from the raw host in index.ts.\r\n const result = await deps.discoveryClient.get<{\r\n capabilities: Array<Record<string, unknown>>;\r\n }>('/api/discovery/v1/catalog', { type: 'api-key', key: apiKey });\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n services = gateByLocalCommands(\r\n (result.data.capabilities || []).map(toListItem),\r\n localCaps,\r\n );\r\n } catch {\r\n // Fallback to local registry when the backend is unreachable.\r\n services = gateByLocalCommands(\r\n SERVICE_REGISTRY.map((s) => toListItem(s as unknown as Record<string, unknown>)),\r\n localCaps,\r\n );\r\n }\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<{ services: ServiceListItem[] }> = {\r\n data: { services },\r\n text: () => {\r\n if (services.length === 0) {\r\n return Formatter.status('info', 'No services found');\r\n }\r\n const headers = ['Service ID', 'Name', 'Category', 'Provider', 'Version', 'Verbs'];\r\n const rows = services.map((s) => [\r\n s.service_id,\r\n s.name,\r\n s.category,\r\n s.provider,\r\n s.version,\r\n s.verbs.join(', '),\r\n ]);\r\n return Formatter.table(headers, rows);\r\n },\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n Formatter,\r\n PromptEngine,\r\n CliError,\r\n resolveFormat,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { findService } from './registry.js';\r\nimport { buildLocalCapabilityMap, type LocalCapabilityMap } from './local-caps.js';\r\n\r\n/**\r\n * Render the full capability as a key/value block for table output. Heavy\r\n * detail (workflow, per-verb descriptions) is appended when present so the\r\n * human-facing table stays as informative as the JSON payload.\r\n */\r\nfunction formatServiceGet(s: Record<string, unknown>): string {\r\n const lines: [string, string][] = [\r\n ['Service ID', String(s.service_id ?? '')],\r\n ['Name', String(s.name ?? '')],\r\n ['Description', String(s.description ?? s.summary ?? '')],\r\n ['Category', String(s.category ?? '')],\r\n ['Version', String(s.version ?? '')],\r\n ['Provider', String(s.provider ?? '')],\r\n ['CLI Noun', String(s.cli_noun ?? '')],\r\n ['Verbs', Array.isArray(s.verbs) ? (s.verbs as string[]).join(', ') : ''],\r\n ];\r\n if (Array.isArray(s.workflow) && s.workflow.length > 0) {\r\n lines.push(['Workflow', (s.workflow as string[]).join(' → ')]);\r\n }\r\n\r\n const block = Formatter.keyValue(lines);\r\n\r\n const verbDescriptions = s.verb_descriptions as Record<string, string> | undefined;\r\n if (verbDescriptions && Object.keys(verbDescriptions).length > 0) {\r\n const detail = Object.entries(verbDescriptions)\r\n .map(([verb, desc]) => ` ${verb}: ${desc}`)\r\n .join('\\n');\r\n return `${block}\\n\\nVerb descriptions:\\n${detail}`;\r\n }\r\n return block;\r\n}\r\n\r\n/**\r\n * Gate a single backend capability against the CLI's command tree: the\r\n * `cli_noun` must be registered locally, otherwise the service is treated as\r\n * not found (the CLI can't execute it, so it must not surface its schema).\r\n * Verb lists inside the returned payload are intersected with local verbs so a\r\n * verb the CLI lacks is never advertised to the Agent.\r\n */\r\nfunction gateCapability(\r\n data: Record<string, unknown>,\r\n localCaps: LocalCapabilityMap,\r\n): Record<string, unknown> | null {\r\n const noun = String(data.cli_noun ?? '');\r\n const localVerbs = localCaps[noun];\r\n if (!localVerbs) return null;\r\n\r\n const out = { ...data };\r\n // Intersect the top-level verbs[] summary.\r\n if (Array.isArray(out.verbs)) {\r\n out.verbs = (out.verbs as string[]).filter((v) => localVerbs.includes(v));\r\n }\r\n // Intersect the full schema_content.verbs map when present.\r\n const schema = out.schema_content as Record<string, unknown> | undefined;\r\n if (schema && schema.verbs && typeof schema.verbs === 'object') {\r\n const filtered: Record<string, unknown> = {};\r\n for (const [verb, def] of Object.entries(schema.verbs as Record<string, unknown>)) {\r\n if (localVerbs.includes(verb)) filtered[verb] = def;\r\n }\r\n out.schema_content = { ...schema, verbs: filtered };\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * `services get <service-id>` — retrieve a single capability's full metadata\r\n * including the complete schema_content (the Agent reads this to learn how to\r\n * use the service).\r\n *\r\n * Primary path: `GET /api/discovery/v1/catalog/<service-id>` → full schema, then\r\n * gated against the CLI command tree (noun must exist; verbs intersected).\r\n * Fallback: local registry (basic metadata, no schema_content).\r\n */\r\nexport function registerServiceGetCommand(\r\n parent: Command,\r\n deps: { discoveryClient: ApiClient; program: Command },\r\n): void {\r\n const cmd = parent\r\n .command('get <service-id>')\r\n .description('Retrieve a single merchant service by id (includes full schema)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n\r\n cmd.action(async (serviceId: string) => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const localCaps = buildLocalCapabilityMap(deps.program);\r\n\r\n let data: Record<string, unknown> | null = null;\r\n\r\n try {\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const result = await deps.discoveryClient.get<Record<string, unknown>>(\r\n `/api/discovery/v1/catalog/${encodeURIComponent(serviceId)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n data = gateCapability(result.data, localCaps);\r\n } catch {\r\n // Fallback to local registry.\r\n const local = findService(serviceId);\r\n data = local ? gateCapability(local as unknown as Record<string, unknown>, localCaps) : null;\r\n }\r\n\r\n if (data === null) {\r\n throw new CliError(\r\n 'SERVICE_NOT_FOUND',\r\n `Service '${serviceId}' is not available in this CLI. Run \"services list\" to see available services.`,\r\n );\r\n }\r\n\r\n const resolved = data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<Record<string, unknown>> = {\r\n data: resolved,\r\n text: () => formatServiceGet(resolved),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { UnifiedListOrdersResponse, UnifiedOrderListItem } from '../types/api.js';\r\nimport { attachSchemaHelp, unifiedOrdersListSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\n\r\nconst DEFAULT_PAGE = '1';\r\nconst DEFAULT_PAGE_SIZE = '20';\r\n\r\nfunction positiveInt(value: string, flag: string): string {\r\n const n = Number(value);\r\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\r\n }\r\n return String(n);\r\n}\r\n\r\nfunction assertCompatibleOptions(opts: Record<string, unknown>): void {\r\n if (opts.orderType !== undefined && opts.orderTypes !== undefined) {\r\n throw new CliError('PARAM_INVALID', '--order-type and --order-types cannot be used together.');\r\n }\r\n if (opts.status !== undefined && opts.statuses !== undefined) {\r\n throw new CliError('PARAM_INVALID', '--status and --statuses cannot be used together.');\r\n }\r\n if (opts.cursor !== undefined && Number(opts.page ?? DEFAULT_PAGE) !== 1) {\r\n throw new CliError('PARAM_INVALID', '--cursor cannot be combined with --page greater than 1.');\r\n }\r\n}\r\n\r\n/** Render a compact cross-provider list summary for table output. */\r\nfunction formatOrders(data: UnifiedListOrdersResponse): string {\r\n const orders: UnifiedOrderListItem[] = data.orders ?? [];\r\n if (orders.length === 0) {\r\n return Formatter.status('info', 'No orders found');\r\n }\r\n\r\n const headers = ['Order ID', 'Type', 'Status', 'Amount', 'Currency'];\r\n const rows = orders.map((o) => [\r\n String(o.order_id ?? '-'),\r\n String(o.order_type ?? '-'),\r\n String(o.status ?? '-'),\r\n String(o.amount ?? '-'),\r\n String(o.currency ?? '-'),\r\n ]);\r\n\r\n const summary: [string, string][] = [\r\n ['Total', String(data.total ?? '-')],\r\n ['Page', String(data.page ?? '-')],\r\n ['Page size', String(data.page_size ?? '-')],\r\n ];\r\n if (data.has_more !== undefined) summary.push(['Has more', String(data.has_more)]);\r\n if (data.next_cursor) summary.push(['Next cursor', data.next_cursor]);\r\n\r\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(summary)}`;\r\n}\r\n\r\n/**\r\n * `orders list` — cross-provider order list (`GET /orders`). This is the\r\n * only list spanning ride, hotel, and flight in one call. Domain-specific\r\n * list commands remain available when provider-specific columns are needed.\r\n */\r\nexport function registerOrdersListCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('list')\r\n .description('List orders across ALL providers (ride + hotel + flight), with filters and pagination')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-type <type>', 'Legacy single order type filter: ride | hotel | flight')\r\n .option('--order-types <types>', 'Comma-separated order types: ride,hotel,flight')\r\n .option('--status <status>', 'Legacy single normalized status filter')\r\n .option('--statuses <statuses>', 'Comma-separated statuses: PENDING,CONFIRMED,COMPLETED,CANCELLED,FAILED')\r\n .option('--created-from <datetime>', 'Created at or after this ISO 8601 datetime (inclusive)')\r\n .option('--created-to <datetime>', 'Created before this ISO 8601 datetime (exclusive)')\r\n .option('--cursor <cursor>', 'Opaque cursor returned by the previous page')\r\n .option('--page <page>', 'Legacy 1-based page number', DEFAULT_PAGE)\r\n .option('--page-size <size>', 'Page size', DEFAULT_PAGE_SIZE)\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n\r\n attachSchemaHelp(cmd, unifiedOrdersListSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n assertCompatibleOptions(opts);\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const params: Record<string, string> = {\r\n page: positiveInt((opts.page as string | undefined) ?? DEFAULT_PAGE, 'page'),\r\n page_size: positiveInt((opts.pageSize as string | undefined) ?? DEFAULT_PAGE_SIZE, 'page-size'),\r\n };\r\n if (opts.orderType !== undefined) params.order_type = opts.orderType as string;\r\n if (opts.orderTypes !== undefined) params.order_types = opts.orderTypes as string;\r\n if (opts.status !== undefined) params.status = opts.status as string;\r\n if (opts.statuses !== undefined) params.statuses = opts.statuses as string;\r\n if (opts.createdFrom !== undefined) params.created_from = opts.createdFrom as string;\r\n if (opts.createdTo !== undefined) params.created_to = opts.createdTo as string;\r\n if (opts.cursor !== undefined) params.cursor = opts.cursor as string;\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) params.member_id = member;\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching orders...');\r\n const result = await deps.apiClient.get<UnifiedListOrdersResponse>(\r\n '/orders',\r\n { type: 'api-key', key: apiKey },\r\n params,\r\n );\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<UnifiedListOrdersResponse> = {\r\n data,\r\n text: () => formatOrders(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { UnifiedOrderDetailResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, unifiedOrdersGetSchema } from '../verb-schema.js';\r\n\r\n/**\r\n * `orders get` — cross-provider order detail (`GET /orders/{id}`). The\r\n * platform resolves order_id -> order_type and delegates to the owning ride,\r\n * hotel, or flight domain. Treat the domain detail as an opaque object.\r\n */\r\nexport function registerOrdersGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('get')\r\n .description('Get a single order detail by id, regardless of provider (ride/hotel/flight)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .requiredOption('--order-id <id>', 'Order id (e.g. rio_..., hho_..., or ffo_...)');\r\n\r\n attachSchemaHelp(cmd, unifiedOrdersGetSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching order...');\r\n\r\n const result = await deps.apiClient.get<UnifiedOrderDetailResponse>(\r\n `/orders/${encodeURIComponent(opts.orderId as string)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<UnifiedOrderDetailResponse> = {\r\n data,\r\n text: () =>\r\n Formatter.keyValue(\r\n Object.entries(data).map(([k, v]) => [k, typeof v === 'object' ? JSON.stringify(v) : String(v)]),\r\n ),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { attachSchemaHelp, ordersPayBatchSchema } from '../verb-schema.js';\r\n// 复用打车 watch 模块导出的 NDJSON 写行 / 真实定时器 / 秒数解析(与 pay-order.ts 同源)。\r\nimport { ndjsonWriteLine, realSleep, resolveSeconds } from '../ride-elife/watch.js';\r\n\r\n// ============================================================\r\n// Response types(后端 pay-batch 契约:成功体 / 3DS 挑战体)\r\n// ============================================================\r\n\r\n/** 聚合结算里单笔订单的最终结果(逐单确认后:成功 / 退款 / 失败)。 */\r\nexport interface PayBatchOrderResult {\r\n order_id: string;\r\n /** 该订单所属领域(hotel / flight / ride),逐单上游确认按此分派。 */\r\n domain?: string;\r\n /** confirmed(上游确认成功)| refunded(确认失败已退款)| failed。 */\r\n status: string;\r\n /** 该订单的权威金额(十进制币种单位,非最小单位)。 */\r\n amount?: number;\r\n /** 确认失败时按该订单金额退款的金额。 */\r\n refunded_amount?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * `POST /orders/pay-batch` 的返回体。同一形状承载三种结果:\r\n * - 成功体:`status ∈ {settled, partially_settled}`,携 `total_amount`/`currency`/`per_order[]`\r\n * (逐单项 `{order_id, domain, status, amount, refunded_amount}`);\r\n * - 3DS 挑战体(轨 B EVO 强制认证):`status == \"AUTHENTICATION_REQUIRED\"`,携 `three_ds_url`/`merchant_trans_id`/`amount`;\r\n * - 失败终态:`status == \"failed\"`。\r\n * CLI 是薄透传层,原样透出后端字段,不做业务判定。逐单列表键名 `per_order`(含 `domain`)与\r\n * 后端 `_build_result_body` / 编排层 `trip-aggregate.json`(`$.per_order`)跨仓契约一致。\r\n */\r\nexport interface PayBatchResponse {\r\n payment_group_id: string;\r\n /** settled | partially_settled | failed | AUTHENTICATION_REQUIRED。 */\r\n status: string;\r\n currency?: string;\r\n /** 合计总额 = 各订单权威价之和(后端计算,调用方不传各订单金额)。 */\r\n total_amount?: number;\r\n per_order?: PayBatchOrderResult[];\r\n // ---- 3DS 挑战体专有字段 ----\r\n three_ds_url?: string;\r\n merchant_trans_id?: string;\r\n /** 挑战金额(= 合计总额)。 */\r\n amount?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n// ============================================================\r\n// Constants\r\n// ============================================================\r\n\r\n/** `--watch` 轮询间隔默认值(秒)。 */\r\nexport const DEFAULT_PAY_BATCH_WATCH_INTERVAL_SECONDS = 5;\r\n/** `--watch` 轮询超时默认值(秒)。 */\r\nexport const DEFAULT_PAY_BATCH_WATCH_TIMEOUT_SECONDS = 300;\r\n\r\n/**\r\n * 聚合支付的终态集合(对齐 checkout-cart plan 的 `poll` 步\r\n * `until: batch.status in [settled, partially_settled, failed]`)。大小写敏感,\r\n * 必须与后端返回的 `status` 字面量一致。`AUTHENTICATION_REQUIRED` 与授权/捕获中\r\n * 等状态均非终态,`--watch` 会继续轮询(幂等重放复查)。\r\n */\r\nexport const PAY_BATCH_TERMINAL_STATUSES: ReadonlySet<string> = new Set([\r\n 'settled',\r\n 'partially_settled',\r\n 'failed',\r\n]);\r\n\r\n// ============================================================\r\n// Input helper:解析 --order-ids(有序,可混合 hho_/ffo_/rio_ 三域)\r\n// ============================================================\r\n\r\n/**\r\n * 解析并 shape 校验 `--order-ids`。接受两种写法(都保持顺序):\r\n * - 逗号分隔:`hho_1,ffo_2,rio_3`;\r\n * - JSON 数组字符串:`[\"hho_1\",\"ffo_2\",\"rio_3\"]`。\r\n *\r\n * 产出一个非空、去除首尾空白后的字符串列表;空值/非字符串元素/空列表 → `PARAM_INVALID`\r\n * (在发起任何请求前抛出)。CLI 只做\"是一批非空 order_id\"的最小结构校验,**不校验前缀域**\r\n * ——具体不可支付单 / 币种不一致 / 令牌绑定不符由后端在 4xx 里标明 order_id 与原因。\r\n *\r\n * 导出以便注册命令与后续测试直接调用。\r\n */\r\nexport function parseOrderIds(raw: string): string[] {\r\n const INVALID =\r\n '--order-ids must be a comma-separated list OR a JSON array of order ids '\r\n + '(e.g. \"hho_1,ffo_2,rio_3\" or [\"hho_1\",\"ffo_2\"]).';\r\n\r\n const trimmed = raw.trim();\r\n let ids: string[];\r\n\r\n if (trimmed.startsWith('[')) {\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(trimmed);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n if (!parsed.every((el) => typeof el === 'string')) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n ids = (parsed as string[]).map((s) => s.trim());\r\n } else {\r\n ids = trimmed.split(',').map((s) => s.trim());\r\n }\r\n\r\n // 去除空片段(如尾随逗号),并要求至少一个有效 order_id。\r\n ids = ids.filter((s) => s.length > 0);\r\n if (ids.length === 0) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n return ids;\r\n}\r\n\r\n// ============================================================\r\n// Output helper\r\n// ============================================================\r\n\r\n/** 导出供 `orders get-payment-group` 复用:查进度和付款返回同形,展示也一致。 */\r\nexport function formatPayBatch(data: PayBatchResponse): string {\r\n const lines: [string, string][] = [\r\n ['Payment group', String(data.payment_group_id ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ];\r\n if (data.total_amount != null && data.currency) {\r\n lines.push(['Total', `${data.total_amount} ${data.currency}`]);\r\n }\r\n // 3DS 挑战体:透出续付所需的 URL / merchantTransID / 挑战金额。\r\n if (data.status === 'AUTHENTICATION_REQUIRED') {\r\n if (data.three_ds_url) lines.push(['3DS URL', String(data.three_ds_url)]);\r\n if (data.merchant_trans_id) lines.push(['Merchant trans ID', String(data.merchant_trans_id)]);\r\n if (data.amount != null && data.currency) {\r\n lines.push(['Challenge amount', `${data.amount} ${data.currency}`]);\r\n }\r\n }\r\n\r\n const out: string[] = [Formatter.keyValue(lines)];\r\n\r\n const perOrder = data.per_order ?? [];\r\n if (perOrder.length > 0) {\r\n const headers = ['Order ID', 'Domain', 'Status', 'Amount', 'Refunded'];\r\n const rows = perOrder.map((o) => [\r\n String(o.order_id ?? '-'),\r\n String(o.domain ?? '-'),\r\n String(o.status ?? '-'),\r\n String(o.amount ?? '-'),\r\n String(o.refunded_amount ?? '-'),\r\n ]);\r\n out.push('', Formatter.table(headers, rows));\r\n }\r\n\r\n return out.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Watch (polling) terminal predicate\r\n// ============================================================\r\n\r\n/**\r\n * 纯终态判定(导出以便单元/属性测试直接调用):`status ∈ {settled,\r\n * partially_settled, failed}` 即终态。缺失/未知状态永不终态,轮询继续直到终态或超时。\r\n */\r\nexport function isBatchTerminal(record: unknown): boolean {\r\n const status = (record as { status?: unknown }).status;\r\n return typeof status === 'string' && PAY_BATCH_TERMINAL_STATUSES.has(status);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `orders pay-batch` —— 行程聚合支付:以**一份支付凭证**对一批订单(`order_ids[]`,\r\n * 可混合 `hho_`/`ffo_`/`rio_` 三域)一次结算合计总额。调用 `POST /orders/pay-batch`,\r\n * `Idempotency-Key` 走 header,body 为\r\n * `{order_ids[], payment_token_id?, payment_method_id?, evo_explicit?, payment_group_id?, member_id?}`。\r\n *\r\n * - `--order-ids`(必填):有序订单列表(逗号分隔或 JSON 数组)。金额取各订单锁单落库的\r\n * 权威价、由后端求和,**调用方不传各订单金额**。\r\n * - `--payment-token-id`(可选,轨 A):以合计总额created、`external_transaction_id` 绑定到\r\n * 本次 payment_group 的网络令牌(银联/Visa 一次 passkey)。\r\n * - `--payment-method-id`(可选,轨 B):EVO 绑卡(一次 3DS)。\r\n * - `--evo-explicit`(可选,轨 B 硬门槛):仅在用户显式选择 EVO 时置位,透传 `evo_explicit=true`。\r\n * - `--payment-group-id`(可选):调用方预生成的组号;缺省由后端生成。\r\n * - `--member`(可选):归因的终端用户 member id。\r\n * - `--idempotency-key`(必填):原样作为 `Idempotency-Key` header 转发;相同键 + 有序\r\n * `order_ids` 重放为同一批次去重复查,不重复扣款。\r\n * - `--watch` / `--watch-interval` / `--watch-timeout`:NDJSON 轮询到终态\r\n * (`settled` / `partially_settled` / `failed`)。\r\n *\r\n * 这是真正动钱的一步(一次卡交互覆盖整趟总额),故非 `--yes` 路径在写之前必须二次确认;\r\n * `--yes` 跳过。确认被拒绝映射为 `CLIENT_ABORTED`(exit 5)。单发与 `--watch` 两条路径都\r\n * 适用(确认只在轮询开始前发生一次)。\r\n *\r\n * 成功:exit 0,打印聚合结算结果(含逐单成功/退款金额)。\r\n * 业务错误:exit 1,错误码写 stderr(后端在 4xx 里标明具体 order_id 与原因)。\r\n * Watch 模式:每次轮询输出一行 NDJSON。\r\n */\r\nexport function registerOrdersPayBatchCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('pay-batch')\r\n .description(\r\n 'Settle a batch of orders (may mix ride/hotel/flight) in one aggregate payment via a single payment credential',\r\n )\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option(\r\n '--order-ids <ids>',\r\n 'Ordered order ids to settle together — comma-separated (hho_1,ffo_2,rio_3) or a JSON array. '\r\n + 'May mix hho_/ffo_/rio_ domains. Amounts come from each order\\'s locked authoritative price (not passed here).',\r\n )\r\n .option(\r\n '--payment-token-id <id>',\r\n '[轨 A] Network-token id minted for the aggregate total and bound to this payment_group (unionpay/visa charge path)',\r\n )\r\n .option(\r\n '--payment-method-id <id>',\r\n '[轨 B] EVO bound-card id to settle the aggregate total (one 3DS challenge)',\r\n )\r\n .option(\r\n '--evo-explicit',\r\n '[轨 B 硬门槛] Explicit opt-in to settle via the EVO bound-card rail. Set ONLY when the user explicitly chose EVO; forwarded to the body as evo_explicit=true.',\r\n )\r\n .option(\r\n '--payment-group-id <id>',\r\n 'Optional caller-pre-generated payment group id; omit to let the platform generate one',\r\n )\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n )\r\n .option('--watch', 'Poll until a terminal batch status or timeout (NDJSON output)', false)\r\n .option(\r\n '--watch-interval <seconds>',\r\n 'Seconds between polls when --watch is set',\r\n String(DEFAULT_PAY_BATCH_WATCH_INTERVAL_SECONDS),\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n 'Max seconds to poll before giving up',\r\n String(DEFAULT_PAY_BATCH_WATCH_TIMEOUT_SECONDS),\r\n );\r\n\r\n // 挂 `--help --format json` verb schema(供工具发现 / Agent 本地读参,无需网络往返)。\r\n attachSchemaHelp(cmd, ordersPayBatchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // 必填 + shape 校验:在发起任何请求前完成 → PARAM_INVALID。\r\n const orderIds = parseOrderIds(need(opts.orderIds as string | undefined, 'order-ids'));\r\n\r\n // 幂等键解析:--yes 下缺失即硬错误(在任何请求前抛出)。\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'orders pay-batch',\r\n });\r\n\r\n // Watch 参数\r\n const watchEnabled = Boolean(opts.watch);\r\n const watchInterval = resolveSeconds(opts.watchInterval as string, DEFAULT_PAY_BATCH_WATCH_INTERVAL_SECONDS);\r\n const watchTimeout = resolveSeconds(opts.watchTimeout as string, DEFAULT_PAY_BATCH_WATCH_TIMEOUT_SECONDS);\r\n\r\n // Body 构造(薄透传):order_ids 必带;凭证 / evo_explicit / group / member 仅在提供时带上。\r\n const body: Record<string, unknown> = { order_ids: orderIds };\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n // 显式 EVO 选择信号:仅在置位时透传 evo_explicit=true;缺省不发(后端默认 false)。\r\n if (opts.evoExplicit) body.evo_explicit = true;\r\n if (opts.paymentGroupId !== undefined) body.payment_group_id = opts.paymentGroupId as string;\r\n // 归因标签:仅在显式传了非空 --member 时写入,缺省保持无归属。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n\r\n // 写前二次确认(除非 --yes)。这是真正动钱的一步:一次卡交互覆盖整趟合计总额\r\n // (银联/Visa 一次 passkey 或 EVO 一次 3DS)。合计总额由后端按权威价求和,CLI 端\r\n // 未知,故确认话术只声明订单笔数。提示走 stderr;拒绝映射 CLIENT_ABORTED(exit 5)。\r\n // 单发与 --watch 都适用(确认只在轮询开始前发生一次)。\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message:\r\n `Settle ${orderIds.length} order(s) in one aggregate payment? `\r\n + 'This moves money — a single charge covers the authoritative total of all listed orders '\r\n + '(banks/EVO see one transaction).',\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Aggregate payment aborted by user.');\r\n }\r\n }\r\n\r\n const path = '/orders/pay-batch';\r\n const headers = { 'Idempotency-Key': idempotencyKey };\r\n const auth = { type: 'api-key' as const, key: apiKey };\r\n\r\n if (!watchEnabled) {\r\n // 单发模式\r\n const spinner = format === 'json' ? null : createSpinner('Settling order batch...');\r\n\r\n const result = await deps.apiClient.post<PayBatchResponse>(path, auth, body, headers);\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<PayBatchResponse> = {\r\n data,\r\n text: () => formatPayBatch(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n } else {\r\n // Watch 模式:幂等重放复查同一批次,逐次输出 NDJSON,直到终态或超时。\r\n const deadline = Date.now() + watchTimeout * 1000;\r\n let lastRecord: unknown = null;\r\n\r\n for (;;) {\r\n const result = await deps.apiClient.post<PayBatchResponse>(path, auth, body, headers);\r\n\r\n if (result.success) {\r\n const data = result.data;\r\n lastRecord = data;\r\n ndjsonWriteLine(data);\r\n\r\n // 终态(settled / partially_settled / failed)→ 停止。非终态(授权/捕获中、\r\n // AUTHENTICATION_REQUIRED 等)→ 继续轮询:用户在 3DS 页外带完成认证后,\r\n // 后续一次幂等重放即结算。\r\n if (isBatchTerminal(data)) {\r\n return;\r\n }\r\n } else {\r\n // 业务错误(不可支付单 / 币种不一致 / 令牌绑定不符等)→ 直接 exit 1。\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n // 超时检查:下一次轮询将越过截止时间则收尾。\r\n if (Date.now() + watchInterval * 1000 >= deadline) {\r\n const timeoutLine = {\r\n watch_status: 'timeout',\r\n message: `Polling stopped after ${watchTimeout}s without reaching a terminal batch status.`,\r\n last_status: lastRecord,\r\n };\r\n ndjsonWriteLine(timeoutLine);\r\n return;\r\n }\r\n\r\n await realSleep(watchInterval * 1000);\r\n }\r\n }\r\n });\r\n}\r\n\r\n// ============================================================\r\n// Local input helper\r\n// ============================================================\r\n\r\n/** 必填标量取值:缺失即 PARAM_INVALID(在任何请求前抛出)。 */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, ordersGetPaymentGroupSchema } from '../verb-schema.js';\r\nimport { formatPayBatch, type PayBatchResponse } from './pay-batch.js';\r\n\r\n/** Platform caps the path segment at 64 chars; anything longer is rejected client-side. */\r\nconst PAYMENT_GROUP_ID_MAX = 64;\r\n\r\n/**\r\n * `orders get-payment-group` — read-only status of one aggregate settlement.\r\n *\r\n * `GET /orders/payment-groups/<payment_group_id>` with X-Api-Key. Returns the same\r\n * shape as `orders pay-batch` (settled / partially_settled / failed / uncertain, plus\r\n * per_order[]), so it is the way to check a batch after `pay-batch` without\r\n * re-sending the payment write. The platform scopes it to the caller's\r\n * organization; a group of another organization reads as not found.\r\n */\r\nexport function registerOrdersGetPaymentGroupCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('get-payment-group')\r\n .description('Get the status of an aggregate settlement created by `orders pay-batch` (read-only)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .requiredOption('--payment-group-id <id>', 'payment_group_id returned by `orders pay-batch`');\r\n\r\n attachSchemaHelp(cmd, ordersGetPaymentGroupSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const groupId = String(opts.paymentGroupId ?? '').trim();\r\n if (!groupId || groupId.length > PAYMENT_GROUP_ID_MAX) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `--payment-group-id must be 1-${PAYMENT_GROUP_ID_MAX} characters.`,\r\n );\r\n }\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching payment group...');\r\n const result = await deps.apiClient.get<PayBatchResponse>(\r\n `/orders/payment-groups/${encodeURIComponent(groupId)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const commandResult: CommandResult<PayBatchResponse> = {\r\n data,\r\n text: () => formatPayBatch(data),\r\n };\r\n await renderWithContext(commandResult, { format }, new ConfigManager());\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { SearchHotelResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelSearchSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/quote.ts and book.ts each define\r\n// their own need/num) rather than pulled from a shared helpers file.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 2.3 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Number-ify a coordinate flag and enforce its valid range. Missing,\r\n * non-finite, or out-of-range input maps to `PARAM_INVALID` (requirement 2.4)\r\n * before any request is sent. Coordinates are sent as numbers, never strings.\r\n */\r\nfunction coord(value: string | undefined, flag: string, min: number, max: number): number {\r\n const n = num(value, flag);\r\n if (n < min || n > max) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be between ${min} and ${max}.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Validate a supplied flag as a positive integer. `undefined` is allowed\r\n * (caller decides whether the flag is required). Non-finite or ≤ 0 → `PARAM_INVALID`.\r\n */\r\nfunction positiveInt(value: string | undefined, flag: string): number {\r\n const n = num(value, flag);\r\n if (!Number.isInteger(n) || n <= 0) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\r\n }\r\n return n;\r\n}\r\n\r\nconst YMD_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\r\n\r\n/**\r\n * Require and validate a stay date. The value must be a real `YYYY-MM-DD`\r\n * calendar date (e.g. `2026-02-30` is rejected); otherwise `PARAM_INVALID`\r\n * (requirement 2.5) before any request is sent. Returns the canonical string.\r\n */\r\nfunction stayDate(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n if (!YMD_RE.test(raw)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a YYYY-MM-DD date.`);\r\n }\r\n const [y, m, d] = raw.split('-').map(Number);\r\n const dt = new Date(Date.UTC(y, m - 1, d));\r\n if (dt.getUTCFullYear() !== y || dt.getUTCMonth() !== m - 1 || dt.getUTCDate() !== d) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a valid calendar date (YYYY-MM-DD).`);\r\n }\r\n return raw;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the search hits as a table for `--format table`. Each hotel is one\r\n * row; the indicative `lowest_price.amount` is a decimal currency unit (NOT\r\n * cents) — printed verbatim. An empty `hotels` list is a successful result, so\r\n * it renders an info line (never an error).\r\n *\r\n * Extended fields from enriched HotelSummary (city_name, score, main_image) are\r\n * included when present.\r\n */\r\nfunction formatSearch(data: SearchHotelResponse): string {\r\n const hotels = data.hotels ?? [];\r\n if (hotels.length === 0) {\r\n return Formatter.status('info', 'No hotels found for this area and dates');\r\n }\r\n\r\n const headers = ['Hotel ID', 'Name', 'Star', 'Distance (km)', 'From', 'Currency', 'City', 'Score', 'Image', 'Address'];\r\n const rows = hotels.map((h) => [\r\n String(h.hotel_id ?? '-'),\r\n String(h.hotel_name ?? '-'),\r\n String(h.star ?? '-'),\r\n String(h.distance_km ?? '-'),\r\n String(h.lowest_price?.amount ?? '-'),\r\n String(h.lowest_price?.currency ?? '-'),\r\n String(h.city_name ?? '-'),\r\n String(h.score ?? '-'),\r\n String(h.main_image ?? '-'),\r\n String(h.address ?? '-'),\r\n ]);\r\n\r\n return Formatter.table(headers, rows);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug search` — search hotels near a coordinate or within a\r\n * destination for a stay (§ search schema). Read-only (no idempotency key).\r\n *\r\n * Accepts exactly one location branch:\r\n * Branch A: --destination-id (alone, no lat/lng needed)\r\n * Branch B: --lat AND --lng (both required together)\r\n * Supplying both branches or neither → PARAM_INVALID before any request.\r\n *\r\n * Builds the `/hotel/search` body from flags (coordinates number-ified and\r\n * range-checked when coordinate branch, dates validated as `YYYY-MM-DD` with\r\n * `check-out` strictly after `check-in`, all before any request → `PARAM_INVALID`),\r\n * POSTs with the `X-Api-Key` auth, and renders `SearchHotelResponse` via\r\n * `renderWithContext` (json carries the profile/endpoint envelope). An empty\r\n * `hotels` list renders as a successful result (exit 0), not an error.\r\n */\r\nexport function registerHotelSearchCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('search')\r\n .description('Search hotels near a coordinate or within a destination for the given stay dates')\r\n // Location branch A: destination-id\r\n .option('--destination-id <id>', 'Destination ID (alternative to --lat/--lng)')\r\n // Location branch B: lat/lng\r\n .option('--lat <lat>', 'Latitude of the search center (-90 to 90)')\r\n .option('--lng <lng>', 'Longitude of the search center (-180 to 180)')\r\n // Common location/search params\r\n .option('--distance <km>', 'Search radius in kilometers', '20')\r\n .option('--check-in <date>', 'Check-in date (YYYY-MM-DD)')\r\n .option('--check-out <date>', 'Check-out date (YYYY-MM-DD, strictly after check-in)')\r\n .option('--adults <n>', 'Number of adults', '2')\r\n .option('--children <n>', 'Number of children', '0')\r\n .option('--room-num <n>', 'Number of rooms requested', '1')\r\n .option('--star <n>', 'Minimum hotel star rating filter (3/4/5)')\r\n .option('--keyword <text>', 'Optional hotel name keyword to narrow results')\r\n // Filter flags (each forwarded only when supplied)\r\n .option('--price-min <n>', 'Minimum price filter')\r\n .option('--price-max <n>', 'Maximum price filter')\r\n .option('--sort-by <field>', 'Sort field')\r\n .option('--page <n>', 'Page number (positive integer)', '1')\r\n .option('--page-size <n>', 'Results per page (positive integer)', '10')\r\n .option('--hotel-facility-codes <codes>', 'Hotel facility codes (comma-separated or JSON array)')\r\n .option('--room-facility-codes <codes>', 'Room facility codes (comma-separated or JSON array)')\r\n .option('--hotel-brand-codes <codes>', 'Hotel brand codes (comma-separated or JSON array)')\r\n .option('--plate-codes <codes>', 'Plate codes (comma-separated or JSON array)')\r\n .option('--hotel-label-ids <ids>', 'Hotel label IDs (comma-separated or JSON array)')\r\n .option('--hotel-sub-category-ids <ids>', 'Hotel sub-category IDs (comma-separated or JSON array)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n\r\n attachSchemaHelp(cmd, hotelSearchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // ---- Location branch validation (BEFORE any request) ----\r\n // Exactly one branch must be supplied:\r\n // Branch A: --destination-id (alone)\r\n // Branch B: --lat AND --lng (both required together)\r\n // Both branches OR neither → PARAM_INVALID.\r\n const hasDestination = opts.destinationId !== undefined;\r\n const hasLat = opts.lat !== undefined;\r\n const hasLng = opts.lng !== undefined;\r\n const hasCoordBranch = hasLat || hasLng;\r\n\r\n if (hasDestination && hasCoordBranch) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Supply either --destination-id OR --lat/--lng, not both.',\r\n );\r\n }\r\n\r\n if (!hasDestination && !hasCoordBranch) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Supply either --destination-id OR --lat/--lng (one location branch is required).',\r\n );\r\n }\r\n\r\n // Coordinate branch: both lat AND lng must be present, with valid ranges.\r\n if (hasCoordBranch && !(hasLat && hasLng)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n '--lat and --lng must both be provided together.',\r\n );\r\n }\r\n\r\n // ---- Date validation (common to both branches) ----\r\n const checkIn = stayDate(opts.checkIn as string | undefined, 'check-in');\r\n const checkOut = stayDate(opts.checkOut as string | undefined, 'check-out');\r\n // Both are validated YYYY-MM-DD, so a lexical compare is a correct date\r\n // order; check-out must be strictly after check-in.\r\n if (!(checkOut > checkIn)) {\r\n throw new CliError('PARAM_INVALID', '--check-out must be strictly after --check-in.');\r\n }\r\n\r\n // ---- Pagination validation (BEFORE any request) ----\r\n const page = positiveInt(opts.page as string | undefined, 'page');\r\n const pageSize = positiveInt(opts.pageSize as string | undefined, 'page-size');\r\n\r\n // ---- Build request body ----\r\n // Location branch: destination_id OR (lat, lng)\r\n const body: Record<string, unknown> = {};\r\n\r\n if (hasDestination) {\r\n body.destination_id = need(opts.destinationId as string | undefined, 'destination-id');\r\n } else {\r\n body.lat = coord(opts.lat as string | undefined, 'lat', -90, 90);\r\n body.lng = coord(opts.lng as string | undefined, 'lng', -180, 180);\r\n }\r\n\r\n // Common fields\r\n body.distance = num(opts.distance as string | undefined, 'distance');\r\n body.check_in = checkIn;\r\n body.check_out = checkOut;\r\n body.adults = num(opts.adults as string | undefined, 'adults');\r\n body.children = num(opts.children as string | undefined, 'children');\r\n body.room_num = num(opts.roomNum as string | undefined, 'room-num');\r\n\r\n // Optional filters — included only when supplied (omitted keys never enter\r\n // the body). --star is numeric when present; --keyword is free text.\r\n if (opts.star !== undefined) body.star = num(opts.star as string, 'star');\r\n if (opts.keyword !== undefined) body.keyword = opts.keyword as string;\r\n\r\n // Price filters (numeric when present)\r\n if (opts.priceMin !== undefined) body.price_min = num(opts.priceMin as string, 'price-min');\r\n if (opts.priceMax !== undefined) body.price_max = num(opts.priceMax as string, 'price-max');\r\n\r\n // Sort\r\n if (opts.sortBy !== undefined) body.sort_by = opts.sortBy as string;\r\n\r\n // Pagination (always included — has defaults)\r\n body.page = page;\r\n body.page_size = pageSize;\r\n\r\n // Opaque code array filters — forwarded as-is when supplied\r\n if (opts.hotelFacilityCodes !== undefined) body.hotel_facility_codes = opts.hotelFacilityCodes as string;\r\n if (opts.roomFacilityCodes !== undefined) body.room_facility_codes = opts.roomFacilityCodes as string;\r\n if (opts.hotelBrandCodes !== undefined) body.hotel_brand_codes = opts.hotelBrandCodes as string;\r\n if (opts.plateCodes !== undefined) body.plate_codes = opts.plateCodes as string;\r\n if (opts.hotelLabelIds !== undefined) body.hotel_label_ids = opts.hotelLabelIds as string;\r\n if (opts.hotelSubCategoryIds !== undefined) body.hotel_sub_category_ids = opts.hotelSubCategoryIds as string;\r\n\r\n const result = await deps.apiClient.post<SearchHotelResponse>(\r\n '/hotel/search',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<SearchHotelResponse> = {\r\n data,\r\n text: () => formatSearch(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { QuoteHotelResponse, HotelRate, PriceItem } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelQuoteSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/quote.ts and hotel-redaug/search.ts\r\n// each define their own need/num/stayDate) rather than pulled from a shared\r\n// helpers file. `quote` is read-only — no idempotency key.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 3.3 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\nconst YMD_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\r\n\r\n/**\r\n * Require and validate a stay date. The value must be a real `YYYY-MM-DD`\r\n * calendar date (e.g. `2026-02-30` is rejected); otherwise `PARAM_INVALID`\r\n * (requirement 3.4) before any request is sent. Returns the canonical string.\r\n */\r\nfunction stayDate(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n if (!YMD_RE.test(raw)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a YYYY-MM-DD date.`);\r\n }\r\n const [y, m, d] = raw.split('-').map(Number);\r\n const dt = new Date(Date.UTC(y, m - 1, d));\r\n if (dt.getUTCFullYear() !== y || dt.getUTCMonth() !== m - 1 || dt.getUTCDate() !== d) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a valid calendar date (YYYY-MM-DD).`);\r\n }\r\n return raw;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Compact per-night summary of a rate's `price_items`. Each night is\r\n * `<date>: <sale_price> (bf <n>)`; `sale_price` is a DECIMAL currency amount\r\n * (NOT cents) — printed verbatim. An empty breakdown renders as `-`.\r\n */\r\nfunction summarizePriceItems(items: PriceItem[] | undefined): string {\r\n if (!items || items.length === 0) return '-';\r\n return items\r\n .map((it) => `${it.sale_date}: ${it.sale_price} (bf ${it.breakfast_num})`)\r\n .join('; ');\r\n}\r\n\r\n/**\r\n * Render the bookable rates as a table for `--format table`. Each rate is one\r\n * row carrying the opaque `product_token` (printed verbatim — passed to `book`\r\n * unchanged), room name, the whole-stay `total_price.amount`+`currency` (DECIMAL\r\n * units, NOT cents — printed verbatim), and a per-night `price_items` summary.\r\n * An empty `rates` list is a successful result, so it renders an info line\r\n * (never an error).\r\n */\r\nfunction formatQuote(data: QuoteHotelResponse): string {\r\n const rates: HotelRate[] = data.rates ?? [];\r\n if (rates.length === 0) {\r\n return Formatter.status('info', 'No bookable rates for this hotel and dates');\r\n }\r\n\r\n const headers = ['Product Token', 'Room', 'Total', 'Currency', 'Per-night (price_items)'];\r\n const rows = rates.map((r) => [\r\n String(r.product_token ?? '-'),\r\n String(r.room_name ?? '-'),\r\n String(r.total_price?.amount ?? '-'),\r\n String(r.total_price?.currency ?? '-'),\r\n summarizePriceItems(r.price_items),\r\n ]);\r\n\r\n return Formatter.table(headers, rows);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug quote` — get real-time room types and bookable rates for one\r\n * hotel and stay (§ quote schema). Read-only (no idempotency key).\r\n *\r\n * Builds the `/hotel/quote` body from flags (`--hotel-id` required, dates\r\n * validated as `YYYY-MM-DD` with `check-out` strictly after `check-in`, numeric\r\n * guest/room flags finite — all before any request → `PARAM_INVALID`), POSTs\r\n * with the `X-Api-Key` auth, and renders `QuoteHotelResponse` via\r\n * `renderWithContext` (json carries the profile/endpoint envelope). Each rate's\r\n * `product_token`, `total_price.amount`/`currency` and `price_items` are decimal\r\n * units rendered verbatim. An empty `rates` list renders as a successful result\r\n * (exit 0), not an error.\r\n */\r\nexport function registerHotelQuoteCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('quote')\r\n .description('Get real-time room types and bookable rates for one hotel and stay')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--hotel-id <id>', 'Hotel chosen from search results (hotels[].hotel_id)')\r\n .option('--check-in <date>', 'Check-in date (YYYY-MM-DD, match search)')\r\n .option('--check-out <date>', 'Check-out date (YYYY-MM-DD, strictly after check-in)')\r\n .option('--adults <n>', 'Number of adults per room', '2')\r\n .option('--children <n>', 'Number of children per room', '0')\r\n .option('--room-num <n>', 'Number of rooms requested', '1')\r\n .option('--nationality <code>', 'Guest nationality (ISO country code)', 'CN');\r\n\r\n attachSchemaHelp(cmd, hotelQuoteSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. All validation throws PARAM_INVALID BEFORE any\r\n // request: --hotel-id required; dates real YYYY-MM-DD with check-out\r\n // strictly after check-in; the numeric guest/room flags finite. snake_case\r\n // keys match the platform contract.\r\n const hotelId = need(opts.hotelId as string | undefined, 'hotel-id');\r\n\r\n const checkIn = stayDate(opts.checkIn as string | undefined, 'check-in');\r\n const checkOut = stayDate(opts.checkOut as string | undefined, 'check-out');\r\n // Both are validated YYYY-MM-DD, so a lexical compare is a correct date\r\n // order; check-out must be strictly after check-in.\r\n if (!(checkOut > checkIn)) {\r\n throw new CliError('PARAM_INVALID', '--check-out must be strictly after --check-in.');\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n hotel_id: hotelId,\r\n check_in: checkIn,\r\n check_out: checkOut,\r\n adults: num(opts.adults as string | undefined, 'adults'),\r\n children: num(opts.children as string | undefined, 'children'),\r\n room_num: num(opts.roomNum as string | undefined, 'room-num'),\r\n nationality: opts.nationality as string,\r\n };\r\n\r\n const result = await deps.apiClient.post<QuoteHotelResponse>(\r\n '/hotel/quote',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<QuoteHotelResponse> = {\r\n data,\r\n text: () => formatQuote(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { PriceItem, RoomGuest } from '../types/hotel.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, hotelCreateOrderSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\n\r\n// ============================================================\r\n// Structured-flag parser (pure builder — directly property-testable)\r\n// ============================================================\r\n\r\n/**\r\n * Parse and shape-validate `--price-items`.\r\n *\r\n * The raw flag MUST be a JSON array in which every element carries `sale_date`\r\n * (string), `sale_price` (number), and `breakfast_num` (number). Any deviation\r\n * — non-JSON, a non-array, or any element missing/mistyping a required field —\r\n * raises `PARAM_INVALID` before any request is issued.\r\n *\r\n * The parsed array is returned VERBATIM (the actual parsed objects, extra keys\r\n * untouched) and forwarded as-is in the request body: `sale_price` is a DECIMAL\r\n * currency amount and is never converted to/from minor units.\r\n *\r\n * Exported so tests and other verbs can import and exercise it directly.\r\n */\r\nexport function parsePriceItems(raw: string): PriceItem[] {\r\n const INVALID =\r\n '--price-items must be a JSON array of {sale_date (string), sale_price (number), breakfast_num (number)}.';\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n for (const el of parsed) {\r\n if (typeof el !== 'object' || el === null || Array.isArray(el)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n const item = el as Record<string, unknown>;\r\n if (\r\n typeof item.sale_date !== 'string' ||\r\n typeof item.sale_price !== 'number' ||\r\n typeof item.breakfast_num !== 'number'\r\n ) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n }\r\n\r\n // Forwarded verbatim — the parsed objects are returned unchanged.\r\n return parsed as PriceItem[];\r\n}\r\n\r\n/**\r\n * Parse and shape-validate `--room-guests`.\r\n *\r\n * Optional per-room primary guests, so several rooms can be booked under\r\n * different names. The raw flag MUST be a non-empty JSON array in which every\r\n * element carries `guest_name` (non-empty string). `room_index` is OPTIONAL:\r\n * callers list the names in room order and the 1-based index is filled in from\r\n * the array position; supplying it explicitly is allowed and then wins. Any\r\n * other deviation raises `PARAM_INVALID` before any request is issued.\r\n *\r\n * Omitting the flag entirely is the backward-compatible path: the platform then\r\n * reuses `guest_name` for every room.\r\n *\r\n * Elements are forwarded as-is apart from the filled-in `room_index` (extra\r\n * keys untouched); the platform validates `room_index` against `room_num` and\r\n * sends the names upstream.\r\n *\r\n * Exported so tests and other verbs can import and exercise it directly.\r\n */\r\nexport function parseRoomGuests(raw: string): RoomGuest[] {\r\n const INVALID =\r\n '--room-guests must be a JSON array of {guest_name (non-empty string), room_index (optional 1-based integer)}.';\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n if (!Array.isArray(parsed) || parsed.length === 0) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n return parsed.map((el, i) => {\r\n if (typeof el !== 'object' || el === null || Array.isArray(el)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n const item = el as Record<string, unknown>;\r\n if (typeof item.guest_name !== 'string' || item.guest_name.trim() === '') {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n // room_index is OPTIONAL: callers just list the names in room order and the\r\n // 1-based index is filled in here. Supplying it is still allowed (and then\r\n // wins), but 0 / negatives / non-integers are the classic off-by-one and are\r\n // rejected locally rather than after a round trip. The upper bound is left\r\n // to the platform (it validates against room_num) so the two never disagree.\r\n if (item.room_index === undefined) {\r\n return { ...item, room_index: i + 1 } as unknown as RoomGuest;\r\n }\r\n if (!Number.isInteger(item.room_index) || (item.room_index as number) < 1) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n // Other keys are forwarded untouched.\r\n return item as unknown as RoomGuest;\r\n });\r\n}\r\n\r\n/**\r\n * Parse and shape-validate `--tips` (客户自测点5 提示信息).\r\n *\r\n * The raw flag MUST be a JSON array of objects, each optionally carrying\r\n * `title` and `text` (strings). Snapshot of the chosen rate's tips, persisted\r\n * on the order for the order-detail page; NOT forwarded upstream.\r\n */\r\nexport function parseTips(raw: string): Array<{ title?: string; text?: string }> {\r\n const INVALID = '--tips must be a JSON array of {title (string, optional), text (string, optional)}.';\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n for (const el of parsed) {\r\n if (typeof el !== 'object' || el === null || Array.isArray(el)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n const item = el as Record<string, unknown>;\r\n if (\r\n (item.title !== undefined && typeof item.title !== 'string') ||\r\n (item.text !== undefined && typeof item.text !== 'string')\r\n ) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n }\r\n\r\n return parsed as Array<{ title?: string; text?: string }>;\r\n}\r\n\r\n/** 解析并校验订单取消条款快照;该对象只在平台落库,不发送给供应商。 */\r\nexport function parseCancellation(raw: string): Record<string, unknown> {\r\n const invalid = '--cancellation must be a JSON object.';\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', invalid);\r\n }\r\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', invalid);\r\n }\r\n return parsed as Record<string, unknown>;\r\n}\r\n\r\n// ============================================================\r\n// Response type\r\n// ============================================================\r\n\r\nexport interface CreateHotelOrderResponse {\r\n order_id: string;\r\n fc_order_code: string;\r\n order_status: string;\r\n total_amount: number;\r\n currency: string;\r\n rooms?: Array<{ room_index: string; guest_name: string }>;\r\n}\r\n\r\n// ============================================================\r\n// Input helpers (reused from book.ts pattern)\r\n// ============================================================\r\n\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\nconst YMD_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\r\n\r\nfunction stayDate(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n if (!YMD_RE.test(raw)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a YYYY-MM-DD date.`);\r\n }\r\n const [y, m, d] = raw.split('-').map(Number);\r\n const dt = new Date(Date.UTC(y, m - 1, d));\r\n if (dt.getUTCFullYear() !== y || dt.getUTCMonth() !== m - 1 || dt.getUTCDate() !== d) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a valid calendar date (YYYY-MM-DD).`);\r\n }\r\n return raw;\r\n}\r\n\r\n// ============================================================\r\n// Output helper\r\n// ============================================================\r\n\r\nfunction formatCreateOrder(data: CreateHotelOrderResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['FC order code', String(data.fc_order_code ?? '-')],\r\n ['Order status', String(data.order_status ?? '-')],\r\n ['Total amount', `${data.total_amount} ${data.currency}`],\r\n ];\r\n\r\n const out: string[] = [Formatter.keyValue(lines)];\r\n\r\n const rooms = data.rooms ?? [];\r\n if (rooms.length > 0) {\r\n const headers = ['Room index', 'Guest name'];\r\n const rows = rooms.map((r) => [String(r.room_index ?? '-'), String(r.guest_name ?? '-')]);\r\n out.push('', Formatter.table(headers, rows));\r\n }\r\n\r\n out.push(\r\n '',\r\n Formatter.status(\r\n 'info',\r\n `Order created with status AWAITING_PAYMENT — proceed with 'hotel-redaug pay-order --order-id ${data.order_id ?? '<order_id>'}' to settle.`,\r\n ),\r\n );\r\n\r\n return out.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug create-order` — create a hotel order without charging any\r\n * account. Calls `POST /hotel/create-order` with `Idempotency-Key` header.\r\n * On success: exit 0, prints the created order_id to stdout.\r\n *\r\n * This is the first step of the create-then-pay flow; the order enters\r\n * AWAITING_PAYMENT status and must be settled via `pay-order`. Locking a rate\r\n * is a real commitment (though not a charge), so the non-`--yes` path MUST\r\n * confirm (restating amount/currency/dates) before the write; `--yes` skips\r\n * it. A declined confirm maps to `CLIENT_ABORTED` (exit 5).\r\n */\r\nexport function registerHotelCreateOrderCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('create-order')\r\n .description('Create a hotel order without charging (lock inventory, await payment)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--product-token <token>', 'Chosen rate token from quote (rates[].product_token)')\r\n .option('--total-amount <amount>', 'Total stay price in decimal currency units (not cents)')\r\n .option('--currency <currency>', 'ISO 4217 currency code from the chosen rate')\r\n .option('--price-items <json>', 'Per-night price breakdown JSON array (copied verbatim from quote)')\r\n .option('--check-in <date>', 'Check-in date (YYYY-MM-DD, match quote)')\r\n .option('--check-out <date>', 'Check-out date (YYYY-MM-DD, strictly after check-in)')\r\n .option('--room-num <n>', 'Number of rooms (match quote)', '1')\r\n .option('--adults <n>', 'Adults per room (match quote)', '2')\r\n .option('--children <n>', 'Children per room (match quote)', '0')\r\n .option('--nationality <code>', 'Guest nationality (ISO country code)', 'CN')\r\n .option('--guest-name <name>', 'Primary guest name')\r\n .option(\r\n '--room-guests <json>',\r\n 'Optional per-room primary guests as a JSON array [{guest_name}], listed in room ' +\r\n 'order, for booking several rooms under different names. room_index is filled in ' +\r\n 'from the array position (1-based); pass it explicitly to override. Omit the flag ' +\r\n 'and every room reuses --guest-name.',\r\n )\r\n .option('--contact-name <name>', 'Booking contact name (may equal guest-name)')\r\n .option('--contact-phone <phone>', 'Booking contact phone number (digits)')\r\n .option('--contact-country-code <code>', \"Phone country calling code without '+'\", '86')\r\n .option('--contact-email <email>', 'Booking contact email')\r\n .option('--arrive-time <time>', 'Expected arrival time (HH:mm, hotel local time)')\r\n .option('--special-requests <text>', 'Free-text special requests (non-binding)')\r\n .option(\r\n '--tips <json>',\r\n \"客户自测点5 提示信息: the chosen quote rate's tips as a JSON array [{title,text}]. Stored on the order for the order-detail page ONLY — platform-local, not sent upstream.\",\r\n )\r\n .option('--hotel-name <name>', 'Hotel name (display-only, stored for order summary)')\r\n .option(\r\n '--cancellation <json>',\r\n 'Cancellation policy JSON from the chosen rate; stored on the order for cancellation gating and deadline display.',\r\n )\r\n .option(\r\n '--hotel-timezone <tz>',\r\n \"Hotel timezone from quote (for example 'UTC+8'); stored to evaluate cancellation deadlines in hotel-local time.\",\r\n )\r\n .option(\r\n '--bed-type <code>',\r\n \"Product bed-type code from the chosen quote rate's beds[].code (e.g. 'L000000' King / '1000000' Queen); forwarded verbatim to upstream createOrder bedType.\",\r\n )\r\n .option(\r\n '--payment-method-id <id>',\r\n 'Optional bound-card id (pay_per_call / EVO path). When set, the platform settles this order by pre-authorizing + capturing on that specific bound card. Omit to let the platform pick by billing_mode.',\r\n )\r\n .option(\r\n '--payment-token-id <id>',\r\n 'UPI Agent Pay: payment token id from an already-completed UnionPay network-token capture. When set, the platform skips EVO preauth/capture and only locks the order + records this credential (funds already charged).',\r\n )\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'EVO merchant transaction id of an already-authorised preauth (3DS challenge resume). ' +\r\n 'When set, the server reuses that authorization instead of creating a new one, ' +\r\n 'avoiding a second hold on the card (pay_per_call mode only).',\r\n )\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelCreateOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required + typed validation — ALL before any request → PARAM_INVALID.\r\n const productToken = need(opts.productToken as string | undefined, 'product-token');\r\n const totalAmount = num(opts.totalAmount as string | undefined, 'total-amount');\r\n const currency = need(opts.currency as string | undefined, 'currency');\r\n const priceItems = parsePriceItems(need(opts.priceItems as string | undefined, 'price-items'));\r\n\r\n const checkIn = stayDate(opts.checkIn as string | undefined, 'check-in');\r\n const checkOut = stayDate(opts.checkOut as string | undefined, 'check-out');\r\n if (!(checkOut > checkIn)) {\r\n throw new CliError('PARAM_INVALID', '--check-out must be strictly after --check-in.');\r\n }\r\n\r\n const guestName = need(opts.guestName as string | undefined, 'guest-name');\r\n const contactName = need(opts.contactName as string | undefined, 'contact-name');\r\n const contactPhone = need(opts.contactPhone as string | undefined, 'contact-phone');\r\n\r\n const body: Record<string, unknown> = {\r\n product_token: productToken,\r\n total_amount: totalAmount,\r\n currency,\r\n price_items: priceItems,\r\n check_in: checkIn,\r\n check_out: checkOut,\r\n room_num: num(opts.roomNum as string | undefined, 'room-num'),\r\n adults: num(opts.adults as string | undefined, 'adults'),\r\n children: num(opts.children as string | undefined, 'children'),\r\n nationality: opts.nationality as string,\r\n guest_name: guestName,\r\n contact_name: contactName,\r\n contact_phone: contactPhone,\r\n contact_country_code: opts.contactCountryCode as string,\r\n };\r\n\r\n // Optional fields — included only when supplied.\r\n // 每间房各自的住客名:不传则平台让所有房间沿用 guest_name(向后兼容)。\r\n if (opts.roomGuests !== undefined) body.room_guests = parseRoomGuests(opts.roomGuests as string);\r\n if (opts.contactEmail !== undefined) body.contact_email = opts.contactEmail as string;\r\n if (opts.arriveTime !== undefined) body.arrive_time = opts.arriveTime as string;\r\n if (opts.specialRequests !== undefined) body.special_requests = opts.specialRequests as string;\r\n // 提示信息快照(客户自测点5):解析并校验 tips JSON,传给平台落库、订单详情页展示。\r\n if (opts.tips !== undefined) body.tips = parseTips(opts.tips as string);\r\n if (opts.cancellation !== undefined) body.cancellation = parseCancellation(opts.cancellation as string);\r\n if (opts.hotelTimezone !== undefined) body.hotel_timezone = opts.hotelTimezone as string;\r\n if (opts.hotelName !== undefined) body.hotel_name = opts.hotelName as string;\r\n if (opts.bedType !== undefined) body.bed_type = opts.bedType as string;\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n // 3DS 挑战续单凭证:持卡人完成认证后带回该交易号,服务端复用那笔已授权的预授权,\r\n // 不再新发起一次(否则又拿到新挑战页且重复冻结资金)。\r\n if (opts.authorizedMerchantTransId) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 归因标签:只在调用方显式传了非空 --member 时写入,缺省订单保持无归属(见\r\n // doc/member-id-attribution-design.md 不变量 3)。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n\r\n // Confirm before the write unless --yes. This locks inventory at the quoted\r\n // rate — the user must have already picked this hotel/rate (from search +\r\n // quote), so the prompt restates what is being locked in before the call is\r\n // made. The prompt goes to stderr; declining maps to CLIENT_ABORTED (exit 5)\r\n // via the top-level envelope.\r\n if (!isYes) {\r\n const chargeNote = opts.paymentTokenId !== undefined\r\n ? 'Payment has already been captured via UPI Agent Pay; this only locks the room.'\r\n : 'This locks the rate but does NOT charge anything yet.';\r\n const confirmed = await confirm({\r\n message: `Create this hotel order for ${totalAmount} ${currency} (check-in ${checkIn}, check-out ${checkOut})? ${chargeNote}`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Order creation aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key resolution — under --yes a missing key is a hard error.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'hotel-redaug create-order',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Creating hotel order...');\r\n\r\n const result = await deps.apiClient.post<CreateHotelOrderResponse>(\r\n '/hotel/create-order',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CreateHotelOrderResponse> = {\r\n data,\r\n text: () => formatCreateOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { PRICE_ANNOTATION_FLAGS, applyPriceAnnotation } from '../price-annotation.js';\r\nimport { attachSchemaHelp, hotelPayOrderSchema } from '../verb-schema.js';\r\nimport {\r\n ndjsonWriteLine,\r\n realSleep,\r\n resolveSeconds,\r\n} from './watch.js';\r\n\r\n// ============================================================\r\n// Response type\r\n// ============================================================\r\n\r\nexport interface PayHotelOrderResponse {\r\n order_id: string;\r\n order_status: string;\r\n settlement_path?: string;\r\n pay_status?: string;\r\n total_amount?: number;\r\n currency?: string;\r\n billing_entry_id?: string;\r\n /** For the pay_per_call settlement path, this echoes the order_id (the EVO merchantTransID). */\r\n merchant_trans_id?: string;\r\n /** AUTHENTICATION_REQUIRED when the network-token authenticate path needs a 3DS step-up. */\r\n status?: string;\r\n /** 3DS/passkey challenge URL (present with status=AUTHENTICATION_REQUIRED). */\r\n three_ds_url?: string;\r\n /** Resume handle for the network-token 3DS path (feed back as --authorized-charge-no). */\r\n charge_no?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\n// ============================================================\r\n// Constants\r\n// ============================================================\r\n\r\n/** Default polling interval for --watch mode (seconds). */\r\nexport const DEFAULT_PAY_WATCH_INTERVAL_SECONDS = 5;\r\n/** Default polling timeout for --watch mode (seconds). */\r\nexport const DEFAULT_PAY_WATCH_TIMEOUT_SECONDS = 300;\r\n\r\n// ============================================================\r\n// Output helper\r\n// ============================================================\r\n\r\nfunction formatPayOrder(data: PayHotelOrderResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['Order status', String(data.order_status ?? '-')],\r\n ];\r\n if (data.settlement_path) lines.push(['Settlement path', String(data.settlement_path)]);\r\n if (data.pay_status) lines.push(['Pay status', String(data.pay_status)]);\r\n if (data.status) lines.push(['Status', String(data.status)]);\r\n if (data.total_amount != null && data.currency) {\r\n lines.push(['Amount', `${data.total_amount} ${data.currency}`]);\r\n }\r\n if (data.billing_entry_id) lines.push(['Billing entry', String(data.billing_entry_id)]);\r\n if (data.merchant_trans_id) lines.push(['Merchant trans ID', String(data.merchant_trans_id)]);\r\n // 网络令牌 3DS 挑战:透出续付句柄与挑战地址,供调用方打开认证页并回带续付。\r\n if (data.charge_no) lines.push(['Charge no', String(data.charge_no)]);\r\n if (data.three_ds_url) lines.push(['3DS URL', String(data.three_ds_url)]);\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Watch (polling) logic for pay-order\r\n// ============================================================\r\n\r\n/**\r\n * Terminal predicate for pay-order watch: PAID means done.\r\n * Any error response triggers exit 1 outside the loop (thrown as CliError).\r\n */\r\nfunction isPaymentTerminal(record: unknown): boolean {\r\n const status = (record as { order_status?: unknown }).order_status;\r\n return status === 'PAID';\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug pay-order` — settle an existing hotel order created via\r\n * `create-order`. Calls `POST /hotel/{order_id}/pay` with an `Idempotency-Key`\r\n * header and an empty body.\r\n *\r\n * - `--order-id` (required): the order to pay. The settlement path is decided\r\n * server-side by the order's billing_mode.\r\n * - `--payment-method-id` / `--payment-token-id` / `--authorized-merchant-trans-id`\r\n * (all optional): payment credentials forwarded to the pay body. Charging happens\r\n * in this step (platform create-order only locks inventory); omit to let the\r\n * platform settle by the developer default card. Token wins over method id\r\n * server-side; `--authorized-merchant-trans-id` resumes a 3DS challenge.\r\n * - `--idempotency-key` (required): forwarded as header.\r\n * - `--watch` / `--watch-interval` / `--watch-timeout`: polling mode that\r\n * retries on PAYMENT_NOT_COMPLETED until PAID or timeout.\r\n *\r\n * This is the step that actually moves money, so the non-`--yes` path MUST\r\n * confirm before the write; `--yes` skips it. A declined confirm maps to\r\n * `CLIENT_ABORTED` (exit 5). Applies to both the single-shot and `--watch`\r\n * paths (the confirm happens once, before polling begins).\r\n *\r\n * On success: exit 0, print settlement result.\r\n * On business error: exit 1, error code to stderr.\r\n * Watch mode: NDJSON output per poll iteration.\r\n */\r\nexport function registerHotelPayOrderCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('pay-order')\r\n .description('Settle an existing hotel order (path decided by billing_mode: monthly_settlement or pay_per_call)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Order ID to pay (from create-order response)')\r\n .option('--payment-method-id <id>', 'Optional bound-card id to charge (pay_per_call / EVO preauth)')\r\n .option('--payment-token-id <id>', 'Optional network-token id (unionpay/visa charge path)')\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'Resume an EVO-card 3DS challenge: merchant trans id of an already-authorised preauth',\r\n )\r\n .option(\r\n '--authenticate',\r\n 'Opt-in to require cardholder 3DS on the network-token direct charge (--payment-token-id, EVO/Mastercard). When a step-up is needed the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume with --authorized-charge-no. Default off = frictionless.',\r\n )\r\n .option(\r\n '--return-url <url>',\r\n 'Optional 3DS/passkey return URL for the network-token authenticate path (falls back to the platform EVO_3DS_RETURN_URL)',\r\n )\r\n .option(\r\n '--authorized-charge-no <no>',\r\n 'Resume a network-token 3DS challenge: charge_no returned by a prior AUTHENTICATION_REQUIRED response (settled via ChargeService.resume_token)',\r\n )\r\n .option(\r\n '--evo-explicit',\r\n '[方案 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side.',\r\n )\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n )\r\n .option('--original-amount-cents <cents>', PRICE_ANNOTATION_FLAGS['original-amount-cents'].description)\r\n .option('--discount-amount-cents <cents>', PRICE_ANNOTATION_FLAGS['discount-amount-cents'].description)\r\n .option('--watch', 'Poll until PAID or timeout (NDJSON output)', false)\r\n .option(\r\n '--watch-interval <seconds>',\r\n 'Seconds between polls when --watch is set',\r\n String(DEFAULT_PAY_WATCH_INTERVAL_SECONDS),\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n 'Max seconds to poll before giving up',\r\n String(DEFAULT_PAY_WATCH_TIMEOUT_SECONDS),\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelPayOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required: --order-id\r\n const orderId = opts.orderId as string | undefined;\r\n if (orderId === undefined) {\r\n throw new CliError('PARAM_INVALID', 'Missing required --order-id.');\r\n }\r\n\r\n // Idempotency key resolution\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'hotel-redaug pay-order',\r\n });\r\n\r\n // Watch mode params\r\n const watchEnabled = Boolean(opts.watch);\r\n const watchInterval = resolveSeconds(opts.watchInterval as string, DEFAULT_PAY_WATCH_INTERVAL_SECONDS);\r\n const watchTimeout = resolveSeconds(opts.watchTimeout as string, DEFAULT_PAY_WATCH_TIMEOUT_SECONDS);\r\n\r\n // Pay-order 携带支付凭证(扣款发生在本步骤):平台侧 create-order 只锁库存/锁价、\r\n // 分文不碰钱(lock-then-pay),扣款后移到这一步。全部可选——省略时平台按订单\r\n // billing_mode 自行分流(月结扣额度、现结选默认卡)。CLI 是薄透传层,不做必填校验。\r\n const body: Record<string, unknown> = {};\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n if (opts.authorizedMerchantTransId !== undefined) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 网络令牌支付时 3DS(opt-in):仅置位时透传 authenticate=true(平台默认 false=免摩擦);\r\n // return_url 可选(缺省平台回落 EVO_3DS_RETURN_URL);authorized_charge_no 是续付句柄。\r\n if (opts.authenticate) body.authenticate = true;\r\n if (opts.returnUrl !== undefined) body.return_url = opts.returnUrl as string;\r\n if (opts.authorizedChargeNo !== undefined) {\r\n body.authorized_charge_no = opts.authorizedChargeNo as string;\r\n }\r\n // 方案 B/R16 显式 EVO 选择信号:仅在置位时透传 evo_explicit=true;缺省则不发(平台默认 false)。\r\n if (opts.evoExplicit) body.evo_explicit = true;\r\n // 价格批注(原价 / 优惠,纯记录):落订单 auth_snapshot + 统一流水并在订单详情回显,\r\n // 不进网关报文、不参与权威价核验。\r\n applyPriceAnnotation(body, opts);\r\n\r\n // Confirm before the write unless --yes. This is the step that actually\r\n // moves money (settlement account debit for monthly_settlement, or EVO\r\n // verification for pay_per_call), decided server-side by billing_mode. The\r\n // prompt goes to stderr; declining maps to CLIENT_ABORTED (exit 5) via the\r\n // top-level envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Settle hotel order ${orderId}? This moves money via the order's configured billing mode (monthly_settlement or pay_per_call).`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Payment aborted by user.');\r\n }\r\n }\r\n\r\n const path = `/hotel/${encodeURIComponent(orderId)}/pay`;\r\n const headers = { 'Idempotency-Key': idempotencyKey };\r\n const auth = { type: 'api-key' as const, key: apiKey };\r\n\r\n if (!watchEnabled) {\r\n // Single-shot mode\r\n const spinner = format === 'json' ? null : createSpinner('Paying hotel order...');\r\n\r\n const result = await deps.apiClient.post<PayHotelOrderResponse>(\r\n path,\r\n auth,\r\n body,\r\n headers,\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<PayHotelOrderResponse> = {\r\n data,\r\n text: () => formatPayOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n } else {\r\n // Watch mode: poll until PAID or timeout, output NDJSON per iteration\r\n const deadline = Date.now() + watchTimeout * 1000;\r\n let lastRecord: unknown = null;\r\n\r\n for (;;) {\r\n const result = await deps.apiClient.post<PayHotelOrderResponse>(\r\n path,\r\n auth,\r\n body,\r\n headers,\r\n );\r\n\r\n if (result.success) {\r\n const data = result.data;\r\n lastRecord = data;\r\n ndjsonWriteLine(data);\r\n\r\n if (isPaymentTerminal(data)) {\r\n return;\r\n }\r\n } else {\r\n // Business error — check if it's PAYMENT_NOT_COMPLETED (retryable in watch)\r\n const errorCode = (result as any).code ?? (result as any).errorCode;\r\n const errorCodeStr = String(errorCode);\r\n\r\n if (errorCodeStr === 'PAYMENT_NOT_COMPLETED' || errorCodeStr === '1933') {\r\n // Retryable: output the error as NDJSON line and continue\r\n const errorLine = {\r\n watch_status: 'pending',\r\n error_code: errorCodeStr === '1933' ? 'PAYMENT_NOT_COMPLETED' : errorCodeStr,\r\n message: (result as any).errorMessage ?? 'Payment not yet completed',\r\n };\r\n lastRecord = errorLine;\r\n ndjsonWriteLine(errorLine);\r\n } else {\r\n // Non-retryable business error → exit 1\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n }\r\n\r\n // Check timeout\r\n if (Date.now() + watchInterval * 1000 >= deadline) {\r\n const timeoutLine = {\r\n watch_status: 'timeout',\r\n message: `Polling stopped after ${watchTimeout}s without reaching PAID status.`,\r\n last_status: lastRecord,\r\n };\r\n ndjsonWriteLine(timeoutLine);\r\n return;\r\n }\r\n\r\n await realSleep(watchInterval * 1000);\r\n }\r\n }\r\n });\r\n}\r\n","import type { ApiClient } from '@agenzo/cli-core';\r\nimport { CliError } from '@agenzo/cli-core';\r\nimport type { GetCheckoutResponse, GetHotelOrderResponse } from '../types/hotel.js';\r\nimport { ndjsonWriteLine, realSleep, resolveSeconds } from '../ride-elife/watch.js';\r\n\r\n/**\r\n * NDJSON status-polling for the hotel long-running reads `hotel-redaug get\r\n * --watch` (Requirement 5.4-5.6) and `hotel-redaug get-checkout --watch`\r\n * (Requirement 8.4-8.5). Merchant-domain logic — stays in the app per\r\n * requirement 15.x (NOT pushed down to cli-core), mirroring `ride-elife/watch.ts`.\r\n *\r\n * The watch stream is a line stream: each poll result is written as ONE\r\n * independent, compact JSON line on stdout. It is deliberately NOT routed\r\n * through `renderWithContext`, so the profile/endpoint envelope is never\r\n * wrapped around the stream (Requirement 11.4 — an agent consumes it with a\r\n * line reader).\r\n *\r\n * The polling engine is split from its I/O so it can be unit/PBT-tested with a\r\n * fake clock and shortened constants (Requirement 15.5): `fetchStatus`,\r\n * `writeLine`, `sleep`, `now`, `isTerminal` and `lastStatusOf` are all\r\n * injected. Unlike `ride-elife` (single verb), the hotel engine serves two\r\n * verbs with different terminal semantics, so the terminal predicate and the\r\n * \"last status\" accessor are injected seams rather than hard-coded.\r\n *\r\n * `resolveSeconds`, `realSleep` and `ndjsonWriteLine` are reused verbatim from\r\n * the ride watch module (which already exports them) and re-exported here so\r\n * the hotel verb modules can pull the whole watch surface from this single,\r\n * self-contained module.\r\n */\r\n\r\nexport { ndjsonWriteLine, realSleep, resolveSeconds };\r\n\r\n// ============================================================\r\n// Defaults (per the verb-schema `polling` blocks)\r\n// ============================================================\r\n\r\n/** `get` schema `polling.recommended_interval_seconds`. */\r\nexport const DEFAULT_ORDER_WATCH_INTERVAL_SECONDS = 5;\r\n/** `get-checkout` schema `polling.recommended_interval_seconds`. */\r\nexport const DEFAULT_CHECKOUT_WATCH_INTERVAL_SECONDS = 10;\r\n/** Safety cap so `--watch` can never poll forever (shared by both verbs). */\r\nexport const DEFAULT_WATCH_TIMEOUT_SECONDS = 600;\r\n\r\n// ============================================================\r\n// Terminal predicates + constants — order status (`get`)\r\n// ============================================================\r\n\r\n/**\r\n * Terminal `order_status_code` set (schema `polling.terminal_statuses`). Once\r\n * the order reaches one of these, `--watch` stops polling. 3 = Confirmed,\r\n * 4 = Cancelled, 5 = Completed.\r\n */\r\nexport const HOTEL_TERMINAL_ORDER_CODES: ReadonlySet<number> = new Set([3, 4, 5]);\r\n/** In-progress `order_status_code` set (schema `polling.in_progress_statuses`). 2 = Processing. */\r\nexport const HOTEL_IN_PROGRESS_ORDER_CODES: ReadonlySet<number> = new Set([2]);\r\n/**\r\n * Terminal `order_status` STRING set — the local-cache fallback path omits\r\n * `order_status_code`, so the string is the robust signal there. CASE-SENSITIVE.\r\n */\r\nexport const HOTEL_TERMINAL_ORDER_STATUS: ReadonlySet<string> = new Set([\r\n 'CONFIRMED',\r\n 'CANCELLED',\r\n 'COMPLETED',\r\n]);\r\n\r\n/** Read the integer `order_status_code` off a poll result (provider path only). */\r\nexport function orderStatusCodeOf(record: unknown): number | undefined {\r\n const code = (record as { order_status_code?: unknown }).order_status_code;\r\n return typeof code === 'number' ? code : undefined;\r\n}\r\n\r\n/** Read the std `order_status` STRING off a poll result. */\r\nexport function orderStatusOf(record: unknown): string | undefined {\r\n const status = (record as { order_status?: unknown }).order_status;\r\n return typeof status === 'string' ? status : undefined;\r\n}\r\n\r\n/**\r\n * Pure terminal-state predicate for `get` (exported for direct unit/PBT\r\n * testing). True when `order_status_code ∈ {3,4,5}` OR `order_status ∈\r\n * {CONFIRMED, CANCELLED, COMPLETED}` — robust across the provider path (carries\r\n * both the int and the string) and the local-cache fallback (string only). A\r\n * missing/unknown status is never terminal, so polling continues until a known\r\n * terminal status or the timeout.\r\n */\r\nexport function isTerminalOrderStatus(record: unknown): boolean {\r\n const code = orderStatusCodeOf(record);\r\n if (code !== undefined && HOTEL_TERMINAL_ORDER_CODES.has(code)) {\r\n return true;\r\n }\r\n const status = orderStatusOf(record);\r\n return status !== undefined && HOTEL_TERMINAL_ORDER_STATUS.has(status);\r\n}\r\n\r\n/**\r\n * Most recent order status for the timeout line: the human-readable\r\n * `order_status` string when present, else the integer `order_status_code`,\r\n * else null.\r\n */\r\nexport function lastOrderStatusOf(record: unknown): string | number | null {\r\n return orderStatusOf(record) ?? orderStatusCodeOf(record) ?? null;\r\n}\r\n\r\n// ============================================================\r\n// Terminal predicates + constants — refund status (`get-checkout`)\r\n// ============================================================\r\n\r\n/** Terminal `refund_status` set (schema `polling.terminal_statuses`). */\r\nexport const CHECKOUT_TERMINAL_REFUND: ReadonlySet<string> = new Set([\r\n 'approved',\r\n 'rejected',\r\n 'refunded',\r\n]);\r\n/** In-progress `refund_status` set (schema `polling.in_progress_statuses`). */\r\nexport const CHECKOUT_IN_PROGRESS_REFUND: ReadonlySet<string> = new Set(['pending']);\r\n\r\n/** Read the `refund_status` STRING off a check-out poll result. */\r\nexport function refundStatusOf(record: unknown): string | undefined {\r\n const status = (record as { refund_status?: unknown }).refund_status;\r\n return typeof status === 'string' ? status : undefined;\r\n}\r\n\r\n/**\r\n * Pure terminal-state predicate for `get-checkout` (exported for direct\r\n * unit/PBT testing). True when `refund_status ∈ {approved, rejected,\r\n * refunded}`. A missing/unknown status is never terminal.\r\n */\r\nexport function isTerminalRefundStatus(record: unknown): boolean {\r\n const status = refundStatusOf(record);\r\n return status !== undefined && CHECKOUT_TERMINAL_REFUND.has(status);\r\n}\r\n\r\n/** Most recent refund status for the timeout line, or null when absent. */\r\nexport function lastRefundStatusOf(record: unknown): string | number | null {\r\n return refundStatusOf(record) ?? null;\r\n}\r\n\r\n// ============================================================\r\n// Engine (pure, fully injected)\r\n// ============================================================\r\n\r\n/** The final NDJSON line emitted when polling gives up before a terminal status. */\r\nexport interface HotelWatchTimeoutLine {\r\n watch_status: 'timeout';\r\n message: string;\r\n last_status: string | number | null;\r\n}\r\n\r\n/** I/O + clock + predicate seams the polling engine depends on (all injectable for tests). */\r\nexport interface HotelWatchDeps {\r\n /** Fetch one status snapshot (throws to abort the whole stream). */\r\n fetchStatus: () => Promise<unknown>;\r\n /** Write one NDJSON record as a single compact line. */\r\n writeLine: (record: unknown) => void;\r\n /** Resolve after `ms` (real timer in prod; fake clock in tests). */\r\n sleep: (ms: number) => Promise<void>;\r\n /** Current epoch millis (real `Date.now` in prod; fake clock in tests). */\r\n now: () => number;\r\n /** Verb-specific terminal-state predicate. */\r\n isTerminal: (record: unknown) => boolean;\r\n /** Verb-specific accessor for the timeout line's `last_status`. */\r\n lastStatusOf: (record: unknown) => string | number | null;\r\n}\r\n\r\n/** Interval / timeout budget for one watch run, in milliseconds. */\r\nexport interface HotelWatchOptions {\r\n intervalMs: number;\r\n timeoutMs: number;\r\n}\r\n\r\n/**\r\n * Poll `fetchStatus`, writing each result as an NDJSON line, until the record\r\n * reaches a terminal status (per the injected `isTerminal`) or the timeout\r\n * elapses. On timeout the FINAL line is `{ watch_status: 'timeout', ... }`\r\n * (Requirements 5.5 / 8.5).\r\n *\r\n * Termination: every iteration either returns (terminal status) or, when the\r\n * next poll would land at/after the deadline, emits the timeout line and\r\n * returns. With a monotonically advancing clock (real time, or a fake clock\r\n * advanced by `sleep`) the deadline is always reached, so the loop is\r\n * guaranteed to terminate for any status sequence. Loop shape is identical to\r\n * `ride-elife`'s `runWatch`.\r\n */\r\nexport async function runHotelWatch(\r\n deps: HotelWatchDeps,\r\n opts: HotelWatchOptions,\r\n): Promise<void> {\r\n const deadline = deps.now() + opts.timeoutMs;\r\n for (;;) {\r\n const record = await deps.fetchStatus();\r\n deps.writeLine(record);\r\n\r\n if (deps.isTerminal(record)) {\r\n return;\r\n }\r\n\r\n if (deps.now() + opts.intervalMs >= deadline) {\r\n const timeoutLine: HotelWatchTimeoutLine = {\r\n watch_status: 'timeout',\r\n message: `Polling stopped after ${opts.timeoutMs / 1000}s without reaching a terminal status.`,\r\n last_status: deps.lastStatusOf(record),\r\n };\r\n deps.writeLine(timeoutLine);\r\n return;\r\n }\r\n\r\n await deps.sleep(opts.intervalMs);\r\n }\r\n}\r\n\r\n// ============================================================\r\n// Production wirings (live endpoints, real timers, system clock)\r\n// ============================================================\r\n\r\n/**\r\n * Production wiring for `hotel-redaug get --watch`: bind the polling engine to\r\n * a live `ApiClient` (order-status endpoint + api-key auth), the compact NDJSON\r\n * stdout writer, real timers and the system clock. A network/backend failure on\r\n * any poll surfaces as a `CliError` to the top-level handler, exactly like the\r\n * single-shot path. The order is terminal at `order_status_code ∈ {3,4,5}`\r\n * (or `order_status ∈ {CONFIRMED, CANCELLED, COMPLETED}`).\r\n */\r\nexport async function watchOrderStatus(\r\n apiClient: ApiClient,\r\n apiKey: string,\r\n orderId: string,\r\n opts: { intervalSeconds: number; timeoutSeconds: number },\r\n): Promise<void> {\r\n const path = `/hotel/${encodeURIComponent(orderId)}/status`;\r\n await runHotelWatch(\r\n {\r\n fetchStatus: async () => {\r\n const result = await apiClient.get<GetHotelOrderResponse>(path, {\r\n type: 'api-key',\r\n key: apiKey,\r\n });\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n return result.data;\r\n },\r\n writeLine: ndjsonWriteLine,\r\n sleep: realSleep,\r\n now: () => Date.now(),\r\n isTerminal: isTerminalOrderStatus,\r\n lastStatusOf: lastOrderStatusOf,\r\n },\r\n {\r\n intervalMs: opts.intervalSeconds * 1000,\r\n timeoutMs: opts.timeoutSeconds * 1000,\r\n },\r\n );\r\n}\r\n\r\n/**\r\n * Production wiring for `hotel-redaug get-checkout --watch`: bind the polling\r\n * engine to a live `ApiClient` (checkout-status endpoint + api-key auth), the\r\n * compact NDJSON stdout writer, real timers and the system clock. A poll\r\n * failure surfaces as a `CliError` to the top-level handler. The refund is\r\n * terminal at `refund_status ∈ {approved, rejected, refunded}`.\r\n */\r\nexport async function watchCheckoutStatus(\r\n apiClient: ApiClient,\r\n apiKey: string,\r\n taskOrderCode: string,\r\n opts: { intervalSeconds: number; timeoutSeconds: number },\r\n): Promise<void> {\r\n const path = `/hotel/checkout/${encodeURIComponent(taskOrderCode)}`;\r\n await runHotelWatch(\r\n {\r\n fetchStatus: async () => {\r\n const result = await apiClient.get<GetCheckoutResponse>(path, {\r\n type: 'api-key',\r\n key: apiKey,\r\n });\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n return result.data;\r\n },\r\n writeLine: ndjsonWriteLine,\r\n sleep: realSleep,\r\n now: () => Date.now(),\r\n isTerminal: isTerminalRefundStatus,\r\n lastStatusOf: lastRefundStatusOf,\r\n },\r\n {\r\n intervalMs: opts.intervalSeconds * 1000,\r\n timeoutMs: opts.timeoutSeconds * 1000,\r\n },\r\n );\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { GetHotelOrderResponse } from '../types/hotel.js';\r\nimport {\r\n DEFAULT_ORDER_WATCH_INTERVAL_SECONDS,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n resolveSeconds,\r\n watchOrderStatus,\r\n} from './watch.js';\r\nimport { attachSchemaHelp, hotelGetSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/get.ts and the sibling\r\n// hotel-redaug/quote.ts and search.ts each define their own need) rather than\r\n// pulled from a shared helpers file. `get` is read-only — no idempotency key.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 5.2 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary, non-watch path only)\r\n// ============================================================\r\n\r\n/**\r\n * Render a single hotel order as a key/value block for `--format table`.\r\n * `order_status` is the std STRING (PROCESSING|CONFIRMED|CANCELLED|COMPLETED|\r\n * INIT); `order_status_code` is the integer mirror (2/3/4/5) shown only when\r\n * present (the provider path carries it; the local-cache fallback omits it).\r\n * `hotel_confirm_no` is populated once the order reaches CONFIRMED (3) and is\r\n * null while PROCESSING (2). `total_amount` is a DECIMAL currency unit (NOT\r\n * cents), always paired with `currency` (sourced from the local record on\r\n * both the provider and local-cache paths) so an amount is never shown\r\n * without its unit. `rooms` / `settlement_path` / `created_at` / `updated_at`\r\n * plus the booking-detail fields (guest / contact / rooms booked / arrive\r\n * time / special requests) surface the order detail persisted at create-order\r\n * time — modeled on what a booking-confirmation view shows, not the raw\r\n * create-order inputs (occupancy counts / nationality are excluded).\r\n */\r\nfunction formatGetOrder(data: GetHotelOrderResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['FC Order Code', String(data.fc_order_code ?? '-')],\r\n ['Status', String(data.order_status ?? '-')],\r\n ];\r\n if (data.order_status_code !== undefined) {\r\n lines.push(['Status code', String(data.order_status_code)]);\r\n }\r\n if (data.hotel_confirm_no !== undefined && data.hotel_confirm_no !== null) {\r\n lines.push(['Hotel confirm no', String(data.hotel_confirm_no)]);\r\n }\r\n if (data.hotel_name) lines.push(['Hotel', String(data.hotel_name)]);\r\n if (data.room_name) lines.push(['Room', String(data.room_name)]);\r\n if (data.check_in) lines.push(['Check-in', String(data.check_in)]);\r\n if (data.check_out) lines.push(['Check-out', String(data.check_out)]);\r\n if (data.total_amount !== undefined && data.total_amount !== null) {\r\n const currency = data.currency ? ` ${data.currency}` : '';\r\n lines.push(['Total amount', `${String(data.total_amount)}${currency}`]);\r\n }\r\n if (data.settlement_path) lines.push(['Settlement path', String(data.settlement_path)]);\r\n if (data.rooms && data.rooms.length > 0) {\r\n lines.push([\r\n 'Rooms',\r\n data.rooms.map((r) => `${r.room_index}:${r.guest_name}`).join(', '),\r\n ]);\r\n }\r\n if (data.room_num !== undefined && data.room_num !== null) {\r\n lines.push(['Rooms booked', String(data.room_num)]);\r\n }\r\n if (data.guest?.name) lines.push(['Guest', String(data.guest.name)]);\r\n if (data.contact?.name) {\r\n const phone = data.contact.phone\r\n ? ` (+${data.contact.country_code ?? ''} ${data.contact.phone})`\r\n : '';\r\n lines.push(['Contact', `${data.contact.name}${phone}`]);\r\n }\r\n if (data.arrive_time) lines.push(['Arrive time', String(data.arrive_time)]);\r\n if (data.special_requests) lines.push(['Special requests', String(data.special_requests)]);\r\n if (data.channel_state) lines.push(['Channel state', String(data.channel_state)]);\r\n if (data.created_at) lines.push(['Created at', String(data.created_at)]);\r\n if (data.updated_at) lines.push(['Updated at', String(data.updated_at)]);\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug get` — query a hotel order status by id (§ get schema).\r\n * Read-only (no idempotency key); path built from `--order-id` ONLY (the\r\n * platform status endpoint `/hotel/{order_id}/status` consumes no supplier\r\n * reference, so `--fc-order-code` is intentionally not accepted here).\r\n *\r\n * Two modes (branching mirrors `ride-elife/get.ts`):\r\n * - Non-`--watch`: a single `GET /hotel/<order_id>/status` → `CommandResult` +\r\n * `renderWithContext` (json carries the profile/endpoint envelope). Renders\r\n * `order_status` (string), `order_status_code` (int, when present),\r\n * `hotel_confirm_no`, and the other key fields.\r\n * - `--watch`: hands off to `watchOrderStatus` (watch.ts), which polls until a\r\n * terminal status (`order_status_code ∈ {3,4,5}` or `order_status ∈\r\n * {CONFIRMED, CANCELLED, COMPLETED}`) or timeout, writing each result as ONE\r\n * NDJSON line on stdout. The watch stream is NOT wrapped in the\r\n * profile/endpoint envelope (it is a line stream); on timeout the final line\r\n * is `{ watch_status: 'timeout', ... }`.\r\n *\r\n * Required-flag validation (`--order-id`) throws `PARAM_INVALID` BEFORE any\r\n * request. Named `registerHotelGetCommand` to avoid clashing with the\r\n * `ride-elife` `registerRideGetCommand` when both are imported into `index.ts`.\r\n */\r\nexport function registerHotelGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('get')\r\n .description('Retrieve a hotel order status by id (repeatable for polling)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Our order reference (coOrderCode) returned by `hotel-redaug create-order`')\r\n .option('--watch', 'Poll until a terminal status, emitting one NDJSON line per update')\r\n .option(\r\n '--watch-interval <seconds>',\r\n `Seconds between polls when --watch is set (default ${DEFAULT_ORDER_WATCH_INTERVAL_SECONDS})`,\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n `Max seconds to poll before giving up (default ${DEFAULT_WATCH_TIMEOUT_SECONDS})`,\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelGetSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n // Required-flag validation BEFORE any request → PARAM_INVALID. The path is\r\n // built from --order-id ONLY (no --fc-order-code).\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n\r\n // --watch: NDJSON line stream (no profile/endpoint envelope). The stream\r\n // itself is the progress, so no spinner/notify is emitted.\r\n if (opts.watch) {\r\n await watchOrderStatus(deps.apiClient, apiKey, orderId, {\r\n intervalSeconds: resolveSeconds(\r\n opts.watchInterval as string | undefined,\r\n DEFAULT_ORDER_WATCH_INTERVAL_SECONDS,\r\n ),\r\n timeoutSeconds: resolveSeconds(\r\n opts.watchTimeout as string | undefined,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n ),\r\n });\r\n return;\r\n }\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching hotel order status...');\r\n\r\n const result = await deps.apiClient.get<GetHotelOrderResponse>(\r\n `/hotel/${encodeURIComponent(orderId)}/status`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<GetHotelOrderResponse> = {\r\n data,\r\n text: () => formatGetOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { CancelHotelResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelCancelSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/cancel.ts and the sibling\r\n// hotel-redaug/book.ts each define their own need) rather than pulled from a\r\n// shared helpers file.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 6.3 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render a cancellation result as a key/value block for `--format table`.\r\n *\r\n * The platform returns one of TWO shapes (modeled on\r\n * `order_mapping.format_cancel` / `format_cancel_pending`), and this formatter\r\n * handles BOTH:\r\n * - CONFIRMED shape — a `cancellation` breakdown (`cancellation_fee`,\r\n * `reversal_amount`, `currency`) and/or a flat `cancellation_fee`, plus a\r\n * `refund_amount`.\r\n * - ACCEPTED-BUT-PENDING shape — `cancel_status` is `'cancel_pending'` with an\r\n * upstream `cancel_result` acknowledgement (no fee/refund settled yet).\r\n *\r\n * Amounts are decimal currency units (NOT cents) — printed verbatim. A closing\r\n * info line conveys the acceptance-is-not-proof contract (requirement 6.5): a\r\n * successful response is acceptance only, so the Agent MUST poll `get` until\r\n * `order_status=CANCELLED` (code 4) to confirm the cancellation actually took\r\n * effect.\r\n */\r\nfunction formatCancel(data: CancelHotelResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['Order status', String(data.order_status ?? '-')],\r\n ];\r\n\r\n // Accepted-but-pending shape: surface the pending marker so the operator sees\r\n // the cancellation was only accepted, not yet observed as CANCELLED.\r\n if (data.cancel_status !== undefined) {\r\n lines.push(['Cancel status', String(data.cancel_status)]);\r\n }\r\n\r\n // Confirmed shape: prefer the structured `cancellation` breakdown, falling\r\n // back to the flat `cancellation_fee` when only that is present.\r\n if (data.cancellation) {\r\n const c = data.cancellation;\r\n const cur = c.currency ? ` ${c.currency}` : '';\r\n if (c.cancellation_fee !== undefined) {\r\n lines.push(['Cancellation fee', `${c.cancellation_fee}${cur}`]);\r\n }\r\n if (c.reversal_amount !== undefined) {\r\n lines.push(['Reversal amount', `${c.reversal_amount}${cur}`]);\r\n }\r\n } else if (data.cancellation_fee !== undefined && data.cancellation_fee !== null) {\r\n lines.push(['Cancellation fee', String(data.cancellation_fee)]);\r\n }\r\n\r\n if (data.refund_amount !== undefined && data.refund_amount !== null) {\r\n lines.push(['Refund amount', String(data.refund_amount)]);\r\n }\r\n\r\n const out: string[] = [Formatter.keyValue(lines)];\r\n\r\n out.push(\r\n '',\r\n Formatter.status(\r\n 'info',\r\n `A successful response is acceptance only, NOT proof of cancellation — poll 'hotel-redaug get --order-id ${data.order_id ?? '<order_id>'}' until order_status=CANCELLED (code 4) to confirm.`,\r\n ),\r\n );\r\n\r\n return out.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug cancel` — cancel an entire hotel order within its cancellation\r\n * policy (§ cancel schema). Write op (W/Y) — a cancellation fee may apply.\r\n *\r\n * `POST /hotel/<order-id>/cancel` with `X-Api-Key` auth, the resolved\r\n * `Idempotency-Key` header (key forwarded verbatim, never in the body), and a\r\n * snake_case body carrying `fc_order_code` (and `reason` when supplied).\r\n * Required-flag validation (`--order-id`, `--fc-order-code`) raises\r\n * `PARAM_INVALID` before any request is sent. There is NO interactive cancel\r\n * confirmation prompt (it was removed so the command never blocks on stdin);\r\n * cancel proceeds directly. A missing `--idempotency-key` under `--yes` throws\r\n * `PARAM_IDEMPOTENCY_KEY_REQUIRED` before any request, otherwise it is prompted.\r\n *\r\n * Renders `CancelHotelResponse` (both the confirmed and the accepted-but-pending\r\n * shapes) via `renderWithContext` (json carries the profile/endpoint envelope);\r\n * the progress spinner goes to stderr and stays silent in json mode. A\r\n * successful response is ACCEPTANCE ONLY — the Agent must poll `get` until\r\n * `order_status=CANCELLED` (code 4) to confirm (requirement 6.5).\r\n */\r\nexport function registerHotelCancelCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('cancel')\r\n .description('Cancel a whole hotel order within its policy (a cancellation fee may apply)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Our order reference (coOrderCode) to cancel (book.response.order_id)')\r\n .option('--fc-order-code <code>', 'Supplier order reference (book.response.fc_order_code)')\r\n .option('--reason <text>', 'Cancellation reason')\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelCancelSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required input throws PARAM_INVALID before any request is sent (mirrors\r\n // the sibling book/get commands). snake_case keys match the platform\r\n // contract; --order-id is the URL path, --fc-order-code rides in the body.\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n const fcOrderCode = need(opts.fcOrderCode as string | undefined, 'fc-order-code');\r\n\r\n const body: Record<string, unknown> = { fc_order_code: fcOrderCode };\r\n // Optional reason — included only when supplied (an omitted key never\r\n // enters the body). --idempotency-key is NEVER in the body.\r\n if (opts.reason !== undefined) body.reason = opts.reason as string;\r\n\r\n // No interactive cancel confirmation — cancel proceeds directly (the extra\r\n // \"A cancellation fee may apply\" y/N prompt was removed so the command never\r\n // blocks on stdin in non-interactive/automation contexts).\r\n\r\n // Idempotency key (requirement 13.1-13.6): resolved before the request via\r\n // the reused merchant-cli policy. Under --yes a missing key is a hard error\r\n // and no request is sent. The key is sent as a header, never in the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'hotel-redaug cancel',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Cancelling hotel order...');\r\n\r\n const result = await deps.apiClient.post<CancelHotelResponse>(\r\n `/hotel/${encodeURIComponent(orderId)}/cancel`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CancelHotelResponse> = {\r\n data,\r\n text: () => formatCancel(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { CheckoutHotelResponse, CheckoutRoom } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelCheckoutSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/cancel.ts and the sibling\r\n// hotel-redaug/book.ts and cancel.ts each define their own need/num) rather\r\n// than pulled from a shared helpers file.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 7.3 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. Used for\r\n * `--refund-type` (an upstream refund-handling code; default 1).\r\n */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Structured-flag parser (pure builder — directly property-testable)\r\n// ============================================================\r\n\r\n/**\r\n * Parse and shape-validate `--checkout-rooms` (requirement 7.4, design Property 3).\r\n *\r\n * The raw flag MUST be a JSON array in which every element carries `room_index`\r\n * (string), `guest_name` (string), and `cancel_check_in_date` (string). Any\r\n * deviation — non-JSON, a non-array, or any element missing/mistyping a required\r\n * field — raises `PARAM_INVALID` before any request is issued.\r\n *\r\n * `room_index` and `guest_name` come VERBATIM from the `book` response\r\n * `rooms[]`; `cancel_check_in_date` is the check-in date of the night(s) being\r\n * dropped. The parsed array is returned VERBATIM (the actual parsed objects,\r\n * extra keys untouched) and forwarded as-is in the request body.\r\n *\r\n * Exported so the task-6 property suite can import and exercise it directly.\r\n */\r\nexport function parseCheckoutRooms(raw: string): CheckoutRoom[] {\r\n const INVALID =\r\n '--checkout-rooms must be a JSON array of {room_index (string), guest_name (string), cancel_check_in_date (string)}.';\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n for (const el of parsed) {\r\n if (typeof el !== 'object' || el === null || Array.isArray(el)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n const room = el as Record<string, unknown>;\r\n if (\r\n typeof room.room_index !== 'string' ||\r\n typeof room.guest_name !== 'string' ||\r\n typeof room.cancel_check_in_date !== 'string'\r\n ) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n }\r\n\r\n // Forwarded verbatim — the parsed objects are returned unchanged.\r\n return parsed as CheckoutRoom[];\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render a check-out application result as a key/value block for\r\n * `--format table`. The synchronous response is an ACCEPTANCE only: it returns a\r\n * `task_order_code` while the supplier decides asynchronously. A closing info\r\n * line conveys the async contract (requirement 7.6): poll `get-checkout` with\r\n * the `task_order_code` until a terminal refund status.\r\n */\r\nfunction formatCheckout(data: CheckoutHotelResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['Task order code', String(data.task_order_code ?? '-')],\r\n ];\r\n if (data.apply_status !== undefined && data.apply_status !== null) {\r\n lines.push(['Apply status', String(data.apply_status)]);\r\n }\r\n if (data.checkout_status !== undefined) {\r\n lines.push(['Checkout status', String(data.checkout_status)]);\r\n }\r\n\r\n const out: string[] = [Formatter.keyValue(lines)];\r\n\r\n out.push(\r\n '',\r\n Formatter.status(\r\n 'info',\r\n `Check-out is ASYNC — this response is acceptance only, NOT proof of refund. Poll 'hotel-redaug get-checkout --task-order-code ${data.task_order_code ?? '<task_order_code>'}' until refund_status is approved/rejected/refunded.`,\r\n ),\r\n );\r\n\r\n return out.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug checkout` — request a partial check-out or an out-of-policy\r\n * cancellation (§ checkout schema). Write op (W/Y) — an APPLICATION the property\r\n * must approve; charges/refund are decided asynchronously.\r\n *\r\n * `POST /hotel/<order-id>/checkout` with `X-Api-Key` auth, the resolved\r\n * `Idempotency-Key` header (key forwarded verbatim, never in the body), and a\r\n * snake_case body `{ fc_order_code, reason, refund_type, checkout_rooms }`.\r\n * `--order-id` is the URL path; `--fc-order-code` rides in the body. All flag\r\n * validation — required fields (`--order-id`, `--fc-order-code`, `--reason`,\r\n * `--checkout-rooms`), the `--checkout-rooms` JSON shape, and numeric\r\n * `--refund-type` — raises `PARAM_INVALID` before any request is sent. `--yes`\r\n * skips the confirm; a declined confirm maps to `CLIENT_ABORTED` (exit 5); a\r\n * missing `--idempotency-key` under `--yes` throws\r\n * `PARAM_IDEMPOTENCY_KEY_REQUIRED` before any request, otherwise it is prompted.\r\n *\r\n * Renders `CheckoutHotelResponse` via `renderWithContext` (json carries the\r\n * profile/endpoint envelope); the progress spinner goes to stderr and stays\r\n * silent in json mode. The synchronous response is ACCEPTANCE ONLY — the Agent\r\n * must poll `get-checkout` until a terminal refund status (requirement 7.6).\r\n * Named `registerHotelCheckoutCommand` to avoid clashing with the `ride-elife`\r\n * registrars when both are imported into `index.ts`.\r\n */\r\nexport function registerHotelCheckoutCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('checkout')\r\n .description('Request a partial check-out or an out-of-policy cancellation (async; the property must approve)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Our order reference (coOrderCode) for the URL path (book.response.order_id)')\r\n .option('--fc-order-code <code>', 'Supplier order reference of the booking to change (book.response.fc_order_code)')\r\n .option('--reason <text>', 'Why the partial check-out / out-of-policy cancellation is requested')\r\n .option(\r\n '--checkout-rooms <json>',\r\n 'Rooms to check out of as a JSON array of {room_index, guest_name, cancel_check_in_date} (room_index/guest_name copied verbatim from book.response.rooms[])',\r\n )\r\n .option('--refund-type <type>', 'Requested refund handling (upstream refund-type code)', '1')\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelCheckoutSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required + typed validation — ALL before any request → PARAM_INVALID.\r\n // snake_case keys match the platform contract. --order-id is the URL path;\r\n // --fc-order-code rides in the body.\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n const fcOrderCode = need(opts.fcOrderCode as string | undefined, 'fc-order-code');\r\n const reason = need(opts.reason as string | undefined, 'reason');\r\n const checkoutRooms = parseCheckoutRooms(need(opts.checkoutRooms as string | undefined, 'checkout-rooms'));\r\n const refundType = num(opts.refundType as string | undefined, 'refund-type');\r\n\r\n const body: Record<string, unknown> = {\r\n fc_order_code: fcOrderCode,\r\n reason,\r\n refund_type: refundType,\r\n checkout_rooms: checkoutRooms,\r\n };\r\n\r\n // Confirm before the write unless --yes. A check-out application may incur\r\n // charges and must be approved by the property, so the prompt makes that\r\n // explicit. The prompt goes to stderr; declining maps to CLIENT_ABORTED\r\n // (exit 5) via the top-level envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Request check-out / out-of-policy cancellation for order ${orderId} (${checkoutRooms.length} room(s))? The property must approve and charges may apply.`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Check-out application aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key (requirement 13.1-13.6): resolved before the request via\r\n // the reused merchant-cli policy. Under --yes a missing key is a hard error\r\n // and no request is sent. The key is sent as a header, never in the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'hotel-redaug checkout',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Submitting check-out application...');\r\n\r\n const result = await deps.apiClient.post<CheckoutHotelResponse>(\r\n `/hotel/${encodeURIComponent(orderId)}/checkout`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CheckoutHotelResponse> = {\r\n data,\r\n text: () => formatCheckout(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { GetCheckoutResponse } from '../types/hotel.js';\r\nimport {\r\n DEFAULT_CHECKOUT_WATCH_INTERVAL_SECONDS,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n resolveSeconds,\r\n watchCheckoutStatus,\r\n} from './watch.js';\r\nimport { attachSchemaHelp, hotelGetCheckoutSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/get.ts and the sibling\r\n// hotel-redaug/get.ts and quote.ts each define their own need) rather than\r\n// pulled from a shared helpers file. `get-checkout` is read-only — no\r\n// idempotency key.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 8.2 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary, non-watch path only)\r\n// ============================================================\r\n\r\n/**\r\n * Render a single check-out application as a key/value block for\r\n * `--format table`. `refund_status` is the application/refund status string\r\n * (pending | approved | rejected | refunded); `refund` is the final refund\r\n * (amount + currency), populated only once `refund_status` is approved or\r\n * refunded. `refund.amount` is a DECIMAL currency unit (NOT cents) — printed\r\n * verbatim.\r\n */\r\nfunction formatGetCheckout(data: GetCheckoutResponse): string {\r\n const lines: [string, string][] = [\r\n ['Task order code', String(data.task_order_code ?? '-')],\r\n ['Refund status', String(data.refund_status ?? '-')],\r\n ];\r\n if (data.refund !== undefined && data.refund !== null) {\r\n lines.push(['Refund amount', String(data.refund.amount)]);\r\n lines.push(['Refund currency', String(data.refund.currency)]);\r\n }\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug get-checkout` — poll a check-out application by task order code\r\n * (§ get-checkout schema). Read-only (no idempotency key); path built from\r\n * `--task-order-code` only.\r\n *\r\n * Two modes (branching mirrors `hotel-redaug/get.ts`):\r\n * - Non-`--watch`: a single `GET /hotel/checkout/<task_order_code>` →\r\n * `CommandResult` + `renderWithContext` (json carries the profile/endpoint\r\n * envelope). Renders `task_order_code`, `refund_status`, and `refund`\r\n * (amount + currency, decimal units).\r\n * - `--watch`: hands off to `watchCheckoutStatus` (watch.ts), which polls\r\n * until a terminal refund status (`refund_status ∈ {approved, rejected,\r\n * refunded}`) or timeout, writing each result as ONE NDJSON line on stdout.\r\n * The watch stream is NOT wrapped in the profile/endpoint envelope (it is a\r\n * line stream); on timeout the final line is `{ watch_status: 'timeout',\r\n * ... }`.\r\n *\r\n * Required-flag validation (`--task-order-code`) throws `PARAM_INVALID` BEFORE\r\n * any request. Named `registerHotelGetCheckoutCommand` to avoid clashing with\r\n * the `ride-elife` registrars when both are imported into `index.ts`.\r\n */\r\nexport function registerHotelGetCheckoutCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('get-checkout')\r\n .description('Retrieve a check-out application status and refund outcome (repeatable for polling)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option(\r\n '--task-order-code <code>',\r\n 'Check-out application id returned by `hotel-redaug checkout`',\r\n )\r\n .option('--watch', 'Poll until a terminal status, emitting one NDJSON line per update')\r\n .option(\r\n '--watch-interval <seconds>',\r\n `Seconds between polls when --watch is set (default ${DEFAULT_CHECKOUT_WATCH_INTERVAL_SECONDS})`,\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n `Max seconds to poll before giving up (default ${DEFAULT_WATCH_TIMEOUT_SECONDS})`,\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelGetCheckoutSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n // Required-flag validation BEFORE any request → PARAM_INVALID. The path is\r\n // built from --task-order-code only.\r\n const taskOrderCode = need(opts.taskOrderCode as string | undefined, 'task-order-code');\r\n\r\n // --watch: NDJSON line stream (no profile/endpoint envelope). The stream\r\n // itself is the progress, so no spinner/notify is emitted.\r\n if (opts.watch) {\r\n await watchCheckoutStatus(deps.apiClient, apiKey, taskOrderCode, {\r\n intervalSeconds: resolveSeconds(\r\n opts.watchInterval as string | undefined,\r\n DEFAULT_CHECKOUT_WATCH_INTERVAL_SECONDS,\r\n ),\r\n timeoutSeconds: resolveSeconds(\r\n opts.watchTimeout as string | undefined,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n ),\r\n });\r\n return;\r\n }\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner =\r\n format === 'json' ? null : createSpinner('Fetching check-out application status...');\r\n\r\n const result = await deps.apiClient.get<GetCheckoutResponse>(\r\n `/hotel/checkout/${encodeURIComponent(taskOrderCode)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<GetCheckoutResponse> = {\r\n data,\r\n text: () => formatGetCheckout(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { ListHotelOrdersResponse, HotelOrderListItem } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelListOrdersSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — query assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/list-orders.ts and the sibling\r\n// hotel-redaug verbs each define their own helpers) rather than pulled from a\r\n// shared helpers file. `list-orders` is read-only — no idempotency key.\r\n\r\nconst DEFAULT_PAGE = '1';\r\nconst DEFAULT_PAGE_SIZE = '20';\r\n\r\n/**\r\n * Number-ify a pagination flag. Non-finite / non-integer / non-positive input\r\n * maps to `PARAM_INVALID` (catalog code, exit 1) BEFORE any request is sent\r\n * (requirement 9.3) — mirroring the `ride-elife/list-orders.ts` convention.\r\n * Returns the canonical string form to be passed through as a query parameter.\r\n */\r\nfunction positiveInt(value: string, flag: string): string {\r\n const n = Number(value);\r\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\r\n }\r\n return String(n);\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the hotel order list as a table for `--format table`. Each order is\r\n * one row; the price column pairs `price_amount` with `price_currency` as a\r\n * DECIMAL currency amount (NOT cents) — printed verbatim. An empty `orders`\r\n * list is a successful result, so it renders an info line (never an error).\r\n */\r\nfunction formatOrders(data: ListHotelOrdersResponse): string {\r\n const orders: HotelOrderListItem[] = data.orders ?? [];\r\n if (orders.length === 0) {\r\n return Formatter.status('info', 'No hotel orders found');\r\n }\r\n\r\n const headers = ['Order ID', 'FC Order Code', 'Status', 'Check-in', 'Check-out', 'Price', 'Payment'];\r\n const rows = orders.map((o) => [\r\n String(o.order_id ?? '-'),\r\n String(o.fc_order_code ?? '-'),\r\n String(o.status ?? '-'),\r\n String(o.check_in ?? '-'),\r\n String(o.check_out ?? '-'),\r\n o.price_amount != null ? `${o.price_amount} ${o.price_currency ?? ''}`.trim() : '-',\r\n String(o.payment_status ?? '-'),\r\n ]);\r\n\r\n const summary: [string, string][] = [\r\n ['Total', String(data.total ?? '-')],\r\n ['Page', String(data.page ?? '-')],\r\n ['Page size', String(data.page_size ?? '-')],\r\n ];\r\n\r\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(summary)}`;\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug list-orders` — list the developer's hotel orders with optional\r\n * status filtering and pagination (§ list-orders schema). Read-only (no\r\n * idempotency key).\r\n *\r\n * Passes `--page`(default 1) / `--page-size`(default 20) / `--status` through\r\n * as query parameters to `GET /hotel/orders` with the `X-Api-Key` auth, and\r\n * renders `ListHotelOrdersResponse` via `renderWithContext` (json carries the\r\n * profile/endpoint envelope). `page`/`page-size` are validated as positive\r\n * integers (invalid → `PARAM_INVALID` before any request); `status` is\r\n * forwarded if and only if `--status` was supplied (omitted entirely when\r\n * absent → all statuses, requirement 9.4). The progress line is emitted through\r\n * the spinner so it goes to stderr and stays silent in json mode.\r\n */\r\nexport function registerHotelListOrdersCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('list-orders')\r\n .description('List the developer\\'s hotel orders with optional status filtering and pagination')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--status <status>', 'Filter by order status (omitted entirely when absent → all statuses)')\r\n .option('--page <page>', 'Page number', DEFAULT_PAGE)\r\n .option('--page-size <size>', 'Page size', DEFAULT_PAGE_SIZE)\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n\r\n attachSchemaHelp(cmd, hotelListOrdersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build query params. page/page-size are validated as positive integers\r\n // (invalid → PARAM_INVALID before any request); status is forwarded\r\n // verbatim if and only if --status was supplied. Sent as a query string,\r\n // never a body.\r\n const params: Record<string, string> = {\r\n page: positiveInt((opts.page as string | undefined) ?? DEFAULT_PAGE, 'page'),\r\n page_size: positiveInt((opts.pageSize as string | undefined) ?? DEFAULT_PAGE_SIZE, 'page-size'),\r\n };\r\n if (opts.status !== undefined) params.status = opts.status as string;\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) params.member_id = member;\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching orders...');\r\n\r\n const result = await deps.apiClient.get<ListHotelOrdersResponse>(\r\n '/hotel/orders',\r\n { type: 'api-key', key: apiKey },\r\n params,\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<ListHotelOrdersResponse> = {\r\n data,\r\n text: () => formatOrders(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { FindDestinationResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelFindDestinationSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (local — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n\r\n/**\r\n * Require a non-empty flag value. Missing or empty input maps to\r\n * `PARAM_INVALID` before any request is issued.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || value.trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table formatter)\r\n// ============================================================\r\n\r\n/**\r\n * Render destinations as a table for `--format table`. An empty\r\n * `destinations[]` is a successful result (exit 0), not an error.\r\n */\r\nfunction formatFindDestination(data: FindDestinationResponse): string {\r\n const destinations = data.destinations ?? [];\r\n if (destinations.length === 0) {\r\n return Formatter.status('info', 'No destinations found for this keyword');\r\n }\r\n\r\n const headers = ['Destination ID', 'Type', 'Name', 'City Name', 'City Code', 'Country', 'Lat', 'Lng'];\r\n const rows = destinations.map((d) => [\r\n String(d.destination_id ?? '-'),\r\n String(d.type ?? '-'),\r\n String(d.name ?? '-'),\r\n String(d.city_name ?? '-'),\r\n String(d.city_code ?? '-'),\r\n String(d.country_name ?? '-'),\r\n String(d.lat ?? '-'),\r\n String(d.lng ?? '-'),\r\n ]);\r\n\r\n return Formatter.table(headers, rows);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug find-destination` — search for a destination by keyword\r\n * (§ find-destination schema). Read-only (no idempotency key, no\r\n * confirmation).\r\n *\r\n * Validates `--keyword` is present and non-empty before any request\r\n * (→ `PARAM_INVALID`), POSTs to `/hotel/find-destination` with `X-Api-Key`\r\n * auth, and renders `FindDestinationResponse` via `renderWithContext`. An\r\n * empty `destinations[]` renders as a successful result (exit 0).\r\n */\r\nexport function registerHotelFindDestinationCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('find-destination')\r\n .description('Search for a hotel destination by keyword (city, landmark, airport, etc.)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--keyword <text>', 'Destination search keyword (required)')\r\n .option('--data-type <type>', 'Optional data type filter');\r\n\r\n attachSchemaHelp(cmd, hotelFindDestinationSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Validate BEFORE any request: --keyword required AND non-empty\r\n const keyword = need(opts.keyword as string | undefined, 'keyword');\r\n\r\n // Build request body (snake_case keys match platform contract).\r\n // Omit data_type when absent.\r\n const body: Record<string, unknown> = { keyword };\r\n if (opts.dataType !== undefined) {\r\n body.data_type = opts.dataType as string;\r\n }\r\n\r\n const result = await deps.apiClient.post<FindDestinationResponse>(\r\n '/hotel/find-destination',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<FindDestinationResponse> = {\r\n data,\r\n text: () => formatFindDestination(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { HotelFiltersResponse, FacilityOption, FilterOption } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelFiltersSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (local — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n\r\n/**\r\n * Require a non-empty flag value. Missing or empty input maps to\r\n * `PARAM_INVALID` before any request is issued.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || value.trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Number-ify a coordinate flag and enforce its valid range. Missing,\r\n * non-finite, or out-of-range input maps to `PARAM_INVALID` (requirement 20.2)\r\n * before any request is sent.\r\n */\r\nfunction coord(value: string | undefined, flag: string, min: number, max: number): number {\r\n const n = num(value, flag);\r\n if (n < min || n > max) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be between ${min} and ${max}.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table formatter)\r\n// ============================================================\r\n\r\n/**\r\n * Render a single filter group as a labelled section. Each item shows\r\n * code, name, and count (plus type for facility groups). The code values\r\n * map directly to the corresponding search filter flags.\r\n */\r\nfunction renderGroup(title: string, items: FilterOption[], isFacility = false): string {\r\n if (items.length === 0) return '';\r\n\r\n const headers = isFacility\r\n ? ['Code', 'Name', 'Count', 'Type']\r\n : ['Code', 'Name', 'Count'];\r\n\r\n const rows = items.map((item) => {\r\n const base = [\r\n String(item.code ?? '-'),\r\n String(item.name ?? '-'),\r\n String(item.count ?? '-'),\r\n ];\r\n if (isFacility) {\r\n base.push(String((item as FacilityOption).type ?? '-'));\r\n }\r\n return base;\r\n });\r\n\r\n return `\\n[${title}]\\n${Formatter.table(headers, rows)}`;\r\n}\r\n\r\n/**\r\n * Render all hotel filter groups for `--format table`. Groups: stars, brands,\r\n * groups, labels, sub_categories, hotel_facilities, room_facilities. Each\r\n * item's code can be passed to the corresponding `search` filter flag.\r\n */\r\nfunction formatFilters(data: HotelFiltersResponse): string {\r\n const sections = [\r\n renderGroup('Stars (→ search --star)', data.stars ?? []),\r\n renderGroup('Brands (→ search --hotel-brand-codes)', data.brands ?? []),\r\n renderGroup('Groups', data.groups ?? []),\r\n renderGroup('Labels (→ search --hotel-label-ids)', data.labels ?? []),\r\n renderGroup('Sub-Categories (→ search --hotel-sub-category-ids)', data.sub_categories ?? []),\r\n renderGroup('Hotel Facilities (→ search --hotel-facility-codes)', data.hotel_facilities ?? [], true),\r\n renderGroup('Room Facilities (→ search --room-facility-codes)', data.room_facilities ?? [], true),\r\n ].filter(Boolean);\r\n\r\n if (sections.length === 0) {\r\n return Formatter.status('info', 'No filter options available for this location');\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug hotel-filters` — retrieve available filter options for a\r\n * location (§ hotel-filters schema). Read-only (no idempotency key, no\r\n * confirmation).\r\n *\r\n * Accepts exactly one location branch: `--destination-id` XOR (`--lat` AND\r\n * `--lng`). Supplying both branches or neither is `PARAM_INVALID` before any\r\n * request. The coordinate branch additionally validates lat∈[-90,90] and\r\n * lng∈[-180,180]. `--distance` (default 20) is always included in the body.\r\n *\r\n * The response groups filter options (stars, brands, groups, labels,\r\n * sub_categories, hotel_facilities, room_facilities) whose codes map directly\r\n * to the corresponding `search` filter flags.\r\n */\r\nexport function registerHotelFiltersCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('hotel-filters')\r\n .description('Get available filter options for hotel search at a given location (codes map to search filters)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--destination-id <id>', 'Destination ID (alternative to --lat/--lng)')\r\n .option('--lat <lat>', 'Latitude (-90 to 90, requires --lng)')\r\n .option('--lng <lng>', 'Longitude (-180 to 180, requires --lat)')\r\n .option('--distance <km>', 'Search radius in kilometers', '20');\r\n\r\n attachSchemaHelp(cmd, hotelFiltersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // ---- Location branch validation (BEFORE any request) ----\r\n // Exactly one branch must be supplied:\r\n // Branch A: --destination-id (alone)\r\n // Branch B: --lat AND --lng (both required together)\r\n // Both branches OR neither → PARAM_INVALID.\r\n const hasDestination = opts.destinationId !== undefined;\r\n const hasLat = opts.lat !== undefined;\r\n const hasLng = opts.lng !== undefined;\r\n const hasCoordBranch = hasLat || hasLng;\r\n\r\n if (hasDestination && hasCoordBranch) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Supply either --destination-id OR --lat/--lng, not both.',\r\n );\r\n }\r\n\r\n if (!hasDestination && !hasCoordBranch) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Supply either --destination-id OR --lat/--lng (one location branch is required).',\r\n );\r\n }\r\n\r\n // Coordinate branch: both lat AND lng must be present, with valid ranges.\r\n if (hasCoordBranch && !(hasLat && hasLng)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n '--lat and --lng must both be provided together.',\r\n );\r\n }\r\n\r\n // Build request body (snake_case keys match platform contract).\r\n const body: Record<string, unknown> = {};\r\n\r\n if (hasDestination) {\r\n body.destination_id = need(opts.destinationId as string | undefined, 'destination-id');\r\n } else {\r\n body.lat = coord(opts.lat as string | undefined, 'lat', -90, 90);\r\n body.lng = coord(opts.lng as string | undefined, 'lng', -180, 180);\r\n }\r\n\r\n // --distance always included (default 20)\r\n body.distance = num(opts.distance as string | undefined, 'distance');\r\n\r\n const result = await deps.apiClient.post<HotelFiltersResponse>(\r\n '/hotel/filters',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<HotelFiltersResponse> = {\r\n data,\r\n text: () => formatFilters(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { ListCitiesResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelListCitiesSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (local — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n\r\n/**\r\n * Require a non-empty flag value. Missing or empty input maps to\r\n * `PARAM_INVALID` before any request is issued.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || value.trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table formatter)\r\n// ============================================================\r\n\r\n/**\r\n * Render cities as a table for `--format table`. An empty `cities[]` is\r\n * a successful result (exit 0), not an error.\r\n */\r\nfunction formatListCities(data: ListCitiesResponse): string {\r\n const cities = data.cities ?? [];\r\n if (cities.length === 0) {\r\n return Formatter.status('info', 'No cities found for this country');\r\n }\r\n\r\n const headers = ['City Code', 'City Name', 'Destination ID', 'Lat', 'Lng', 'Country', 'Time Zone'];\r\n const rows = cities.map((c) => [\r\n String(c.city_code ?? '-'),\r\n String(c.city_name ?? '-'),\r\n String(c.destination_id ?? '-'),\r\n String(c.lat ?? '-'),\r\n String(c.lng ?? '-'),\r\n String(c.country_name ?? '-'),\r\n String(c.time_zone ?? '-'),\r\n ]);\r\n\r\n return Formatter.table(headers, rows);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug list-cities` — list cities for a given country code\r\n * (§ list-cities schema). Read-only (no idempotency key, no confirmation).\r\n *\r\n * Validates `--country` is present and non-empty before any request\r\n * (→ `PARAM_INVALID`), POSTs to `/hotel/cities` with `X-Api-Key` auth,\r\n * and renders `ListCitiesResponse` via `renderWithContext`. An empty\r\n * `cities[]` renders as a successful result (exit 0).\r\n */\r\nexport function registerHotelListCitiesCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('list-cities')\r\n .description('List cities available for hotel booking in a given country')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--country <code>', 'ISO country code (required)');\r\n\r\n attachSchemaHelp(cmd, hotelListCitiesSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Validate BEFORE any request: --country required AND non-empty\r\n const country = need(opts.country as string | undefined, 'country');\r\n\r\n // Build request body (snake_case keys match platform contract).\r\n // Flag is --country, body field is country_code.\r\n const body: Record<string, unknown> = { country_code: country };\r\n\r\n const result = await deps.apiClient.post<ListCitiesResponse>(\r\n '/hotel/cities',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<ListCitiesResponse> = {\r\n data,\r\n text: () => formatListCities(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { HotelDetailResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelDetailSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (local — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n\r\n/**\r\n * Require a non-empty flag value. Missing or empty input maps to\r\n * `PARAM_INVALID` before any request is issued.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || value.trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Parse `--settings` (comma-separated or JSON array string) into a string[].\r\n * Validation of allowed codes happens server-side (provider); this is pure\r\n * parsing, no whitelist duplicated here.\r\n */\r\nfunction parseSettings(value: string | undefined): string[] | undefined {\r\n if (value === undefined || value.trim() === '') {\r\n return undefined;\r\n }\r\n const trimmed = value.trim();\r\n if (trimmed.startsWith('[')) {\r\n try {\r\n const parsed = JSON.parse(trimmed);\r\n if (Array.isArray(parsed) && parsed.every((v) => typeof v === 'string')) {\r\n return parsed;\r\n }\r\n } catch {\r\n // fall through to comma-split below\r\n }\r\n throw new CliError('PARAM_INVALID', 'Invalid --settings JSON array.');\r\n }\r\n return trimmed\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter((s) => s.length > 0);\r\n}\r\n\r\n// ============================================================\r\n// Output helpers (table formatter)\r\n// ============================================================\r\n\r\n/**\r\n * Render hotel detail as a key/value block + facilities table + images table.\r\n * Images table is empty when `--with-images false`.\r\n */\r\nfunction formatHotelDetail(data: HotelDetailResponse): string {\r\n const lines: string[] = [];\r\n\r\n // Key/value block\r\n const kvPairs: [string, string][] = [\r\n ['Hotel ID', String(data.hotel_id ?? '-')],\r\n ['Hotel Name', String(data.hotel_name ?? '-')],\r\n ['English Name', String(data.hotel_eng_name ?? '-')],\r\n ['Star', String(data.star ?? '-')],\r\n ['Address', String(data.address ?? '-')],\r\n ['Intro', String(data.intro ?? '-')],\r\n ['Telephone', String(data.telephone ?? '-')],\r\n ['Country', String(data.country_name ?? '-')],\r\n ['Province', String(data.province_name ?? '-')],\r\n ['City', String(data.city_name ?? '-')],\r\n ['District', String(data.district_name ?? '-')],\r\n ['Business Area', String(data.business_name ?? '-')],\r\n ['Latitude', String(data.lat ?? '-')],\r\n ['Longitude', String(data.lng ?? '-')],\r\n ['Check-in Time', String(data.check_in_time ?? '-')],\r\n ['Check-out Time', String(data.check_out_time ?? '-')],\r\n ['Room Count', String(data.room_num ?? '-')],\r\n ];\r\n\r\n lines.push(Formatter.keyValue(kvPairs));\r\n\r\n // Special check-in instructions — MUST be shown to the user when present\r\n // (upstream data provider does not accept liability for booking issues\r\n // caused by this not being displayed). Only non-null when --settings\r\n // included 'hotelTextPolicies'.\r\n if (data.special_instructions) {\r\n lines.push('');\r\n lines.push(Formatter.status('warning', `Special Check-in Instructions: ${data.special_instructions}`));\r\n }\r\n\r\n // Facilities table\r\n const facilities = data.facilities ?? [];\r\n if (facilities.length > 0) {\r\n lines.push('');\r\n lines.push('Facilities:');\r\n const facHeaders = ['Name', 'Type'];\r\n const facRows = facilities.map((f) => [\r\n String(f.name ?? '-'),\r\n String(f.type ?? '-'),\r\n ]);\r\n lines.push(Formatter.table(facHeaders, facRows));\r\n } else {\r\n lines.push('');\r\n lines.push(Formatter.status('info', 'No facilities listed'));\r\n }\r\n\r\n // Images table\r\n const images = data.images ?? [];\r\n if (images.length > 0) {\r\n lines.push('');\r\n lines.push('Images:');\r\n const imgHeaders = ['URL', 'Is Main'];\r\n const imgRows = images.map((img) => [\r\n String(img.url ?? '-'),\r\n String(img.is_main ?? false),\r\n ]);\r\n lines.push(Formatter.table(imgHeaders, imgRows));\r\n } else {\r\n lines.push('');\r\n lines.push(Formatter.status('info', 'No images available'));\r\n }\r\n\r\n // Rooms table — static room-type info (area/floor/beds/occupancy) + a\r\n // per-room image count. room_id is the SAME id space as quote's\r\n // roomItems[].roomId, so this can be related to quote's live rates.\r\n const rooms = data.rooms ?? [];\r\n if (rooms.length > 0) {\r\n lines.push('');\r\n lines.push('Rooms:');\r\n const roomHeaders = ['Room ID', 'Room Name', 'Area', 'Floor', 'Max Person', 'Beds', 'Images'];\r\n const roomRows = rooms.map((r) => {\r\n const bedsStr = (r.beds ?? [])\r\n .map((b) => `${b.name ?? '-'}${b.num ? ` x${b.num}` : ''}`)\r\n .join(', ') || '-';\r\n return [\r\n String(r.room_id ?? '-'),\r\n String(r.room_name ?? '-'),\r\n String(r.area_sqm ?? '-'),\r\n String(r.floor ?? '-'),\r\n String(r.max_person ?? '-'),\r\n bedsStr,\r\n String((r.images ?? []).length),\r\n ];\r\n });\r\n lines.push(Formatter.table(roomHeaders, roomRows));\r\n lines.push(\r\n '',\r\n Formatter.status(\r\n 'info',\r\n 'room_id matches quote\\'s roomItems[].roomId — use it to relate a room here to its live rate in quote.',\r\n ),\r\n );\r\n } else {\r\n lines.push('');\r\n lines.push(Formatter.status('info', 'No room-type details available'));\r\n }\r\n\r\n // Review scores — only present when --settings included 'comment'.\r\n const comments = data.comment ?? [];\r\n if (comments.length > 0) {\r\n lines.push('');\r\n lines.push('Review Scores:');\r\n const headers = ['Channel', 'Average Score'];\r\n const rows = comments.map((c) => [String(c.channel ?? '-'), String(c.average_score ?? '-')]);\r\n lines.push(Formatter.table(headers, rows));\r\n }\r\n\r\n // Certificates/qualifications — only present when --settings included 'hotelCertificates'.\r\n const certs = data.hotel_certificates ?? [];\r\n if (certs.length > 0) {\r\n lines.push('');\r\n lines.push('Certificates:');\r\n const headers = ['Name', 'Unify Code'];\r\n const rows = certs.map((c) => [String(c.certification_name ?? '-'), String(c.unify_code ?? '-')]);\r\n lines.push(Formatter.table(headers, rows));\r\n }\r\n\r\n // Text policies (hotelPolicy/instructions/mandatoryFees/etc) — only present when\r\n // --settings included 'hotelTextPolicies'. specialInstructions is shown separately\r\n // above (must-display), so it is excluded here to avoid duplication.\r\n const textPolicies = (data.hotel_text_policies ?? []).filter(\r\n (p) => p.code !== 'specialInstructions',\r\n );\r\n if (textPolicies.length > 0) {\r\n lines.push('');\r\n lines.push('Hotel Policies:');\r\n const headers = ['Policy', 'Text'];\r\n const rows = textPolicies.map((p) => [String(p.code_name ?? p.code ?? '-'), String(p.text ?? '-')]);\r\n lines.push(Formatter.table(headers, rows));\r\n }\r\n\r\n return lines.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug hotel-detail` — get detailed information about a specific hotel\r\n * (§ hotel-detail schema). Read-only (no idempotency key, no confirmation).\r\n *\r\n * Validates `--hotel-id` is present and non-empty before any request\r\n * (→ `PARAM_INVALID`), POSTs to `/hotel/detail` with `X-Api-Key` auth,\r\n * and renders `HotelDetailResponse` via `renderWithContext`. When\r\n * `--with-images false`, the body sends `with_images: false` and the\r\n * platform returns an empty `images[]`.\r\n */\r\nexport function registerHotelDetailCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('hotel-detail')\r\n .description('Get detailed information about a specific hotel (facilities, images, etc.)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--hotel-id <id>', 'Hotel ID (required)')\r\n .option('--with-images [value]', 'Include hotel images (default: true)', true)\r\n .option(\r\n '--settings <list>',\r\n 'Optional on-demand upstream fields, comma-separated or JSON array ' +\r\n '(hotelFacilityNew, breakfast, importantNotices, parking, chargingParking, ' +\r\n 'hotelCertificates, comment, hotelMeetingInfos, hotelVideoInfos, hotelTextPolicies, ' +\r\n 'hotelStructuredPolicies.childPolicy, hotelStructuredPolicies.extraBedPolicy, ' +\r\n 'hotelStructuredPolicies.petPolicy). Pass hotelTextPolicies to get special_instructions.',\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelDetailSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Validate BEFORE any request: --hotel-id required AND non-empty\r\n const hotelId = need(opts.hotelId as string | undefined, 'hotel-id');\r\n\r\n // Resolve --with-images boolean. Commander parses boolean-like options:\r\n // --with-images / --with-images true → true (default)\r\n // --with-images false → 'false' (string)\r\n const rawWithImages = opts.withImages;\r\n const withImages = rawWithImages !== 'false' && rawWithImages !== false;\r\n\r\n const settings = parseSettings(opts.settings as string | undefined);\r\n\r\n // Build request body (snake_case keys match platform contract).\r\n const body: Record<string, unknown> = {\r\n hotel_id: hotelId,\r\n with_images: withImages,\r\n };\r\n if (settings !== undefined) {\r\n body.settings = settings;\r\n }\r\n\r\n const result = await deps.apiClient.post<HotelDetailResponse>(\r\n '/hotel/detail',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<HotelDetailResponse> = {\r\n data,\r\n text: () => formatHotelDetail(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\n\r\nconst SKILL_TEXT = `\r\n---\r\nname: hotel-redaug\r\ndescription: Search, create orders, and manage international hotel reservations via the Redaug provider. Two-step create-then-pay flow supporting monthly_settlement and pay_per_call (EVO) billing modes. Use when the user wants to find hotels, check room prices/availability, make a hotel booking, or view/cancel/modify an existing hotel order. Not for flights, rides, or domestic-only stays.\r\n---\r\n\r\n# hotel-redaug — Agent Skill\r\n\r\nYou orchestrate hotel bookings through CLI verbs. This guide covers HOW to chain\r\nthe verbs and pass data between them. For exact flags and field types, read the\r\nschema (\\`services get svc_01J0HT5REDAUG0001 --api-key <key> --format json\\`) or\r\nrun \\`hotel-redaug <verb> --help\\`.\r\n\r\n## Prerequisites\r\n\r\n- API key with merchant scope\r\n- Two billing modes supported (set on the developer, not chosen per-call):\r\n - **monthly_settlement**: developer has a settlement account with sufficient balance\r\n - **pay_per_call**: developer collects payment from their end-user via EVO; the user pays using the create-order \\`order_id\\` as the EVO merchantTransID, and the platform verifies by querying EVO for that order_id (the pay-order response reports settlement_path \"pay_per_call\")\r\n- BILLING_MODE_MISMATCH means the order billing_mode is not one of the two modes above\r\n- Pass --api-key <key> --format json on every call; add --yes on writes\r\n\r\n## Workflow\r\n\r\n1. Resolve location\r\n - find-destination --keyword \"<place>\" → lat/lng or destination_id\r\n - list-cities --country <code> → destination_id\r\n - (Need exactly one of these for search.)\r\n\r\n2. Search hotels\r\n - Pass ONE location branch (coordinates OR destination_id) + dates + guests\r\n - Optional: hotel-filters first to get valid filter codes, then pass to search\r\n\r\n3. Choose a hotel (MANDATORY unless the user already named one exact hotel)\r\n - MUST present the candidates to the user (name, address/distance, star/score if useful)\r\n and get an explicit pick — never auto-select by distance or price alone, even for an\r\n open-ended request like \"book me something near the Bund\"\r\n - hotel-detail <hotel-id> for the shortlisted/chosen hotel is OPTIONAL AT THIS STEP for\r\n the hotel-level info (address/intro/hotel photos) — the candidate list above is enough\r\n to pick a HOTEL. But you WILL need hotel-detail's rooms[] at step 4 below to describe\r\n ROOMS, so in practice call it once the user has picked (or shortlisted) a hotel, before\r\n moving to quote — don't make two round trips when one will do\r\n\r\n4. Quote + show room options (ALWAYS call hotel-detail here — this is the mandatory part)\r\n - quote the chosen hotel + same dates/guests → rates[]\r\n - Empty rates[] = no availability → stop, tell the user\r\n - Each rate carries the inputs for create-order: product_token, total_price, price_items\r\n - quote's rates[].room_name is only a bare one-line label with NO area/beds/photos. MUST\r\n call hotel-detail on the same hotel_id (if not already called in step 3) and match its\r\n rooms[] to quote's rates by room_name — do this proactively, BEFORE presenting rate\r\n options, not only if the user asks for more detail. The room is the actual product being\r\n booked, so the user picking a rate MUST see area_sqm, floor, beds, and images alongside\r\n rate_plan_name/breakfast/free_cancellation/total_price+currency — never present rate\r\n options as a bare list of room_name + price only.\r\n - MUST present the combined rate+room options and get the user's explicit pick of which\r\n rate to book — same rule as step 3, and now with real room detail attached, not optional\r\n\r\n5. Create order (lock inventory, no charge) — MUST NOT run until step 3+4 confirmation happened\r\n - create-order: forward quote outputs VERBATIM (product_token, amount, currency, price_items)\r\n - Collect from user: guest_name, contact_name, contact_phone\r\n - Generate a unique idempotency-key\r\n - Response → save order_id + fc_order_code + total_amount + currency\r\n - Order status: AWAITING_PAYMENT (no money charged yet)\r\n\r\n6. BRANCH ON BILLING_MODE — decide THIS before calling pay-order, not inside it\r\n - You (the developer/Agent) know your own billing_mode; the order does not expose it.\r\n a) monthly_settlement → skip straight to step 7 (pay-order). Nothing to do here.\r\n b) pay_per_call → STOP. Do NOT call pay-order yet.\r\n - Drive YOUR OWN EVO payment integration now, using the order_id from step 5 AS THE\r\n EVO merchantTransID (this is the id you pass to your EVO payment call — not a new\r\n or random id).\r\n - Wait for the end-user to actually complete that EVO payment for total_amount+currency.\r\n - Only once EVO shows the payment as complete, proceed to step 7 — pay-order is what\r\n tells the platform \"go verify and settle this\", it does NOT itself collect payment.\r\n\r\n7. Pay order (settle the locked order) — MUST confirm with the user before calling this\r\n - Before calling: show the user total_amount + currency from create-order and which\r\n billing path applies, and get explicit go-ahead — pay-order is the step that actually\r\n moves money (for pay_per_call, confirm the EVO payment from step 6 was completed first)\r\n - pay-order --order-id <order_id from create-order> (that's the only identifier needed)\r\n - Billing path determined server-side by developer's billing_mode:\r\n a) monthly_settlement:\r\n - Platform deducts from settlement account → calls upstream payOrder\r\n b) pay_per_call:\r\n - Requires step 6 to have already happened (user paid via EVO under this order_id).\r\n Calling pay-order now just makes the platform query EVO for that order_id and\r\n verify exact amount/currency — it does NOT initiate the EVO payment itself.\r\n There is no merchant-transaction-id flag: the EVO key IS the order_id, so a\r\n foreign already-paid EVO transaction cannot be substituted.\r\n - If EVO not yet confirmed → PAYMENT_NOT_COMPLETED; use --watch to poll\r\n - On success → order status becomes PAID\r\n\r\n8. Confirm (upstream confirmation is async)\r\n - Poll get --order-id until CONFIRMED (success) or CANCELLED (failed)\r\n - Do not report success before CONFIRMED\r\n\r\n9. Post-booking (only when the user asks)\r\n - cancel: order_id + fc_order_code + reason\r\n - checkout: partial leave-early → then poll get-checkout with task_order_code\r\n - list-orders: view all orders\r\n\r\n## Data passing (where each value comes from)\r\n\r\n- product_token : quote → create-order (opaque; never fabricate or edit)\r\n- price_items : quote → create-order (JSON array; copy exactly)\r\n- order_id : create-order → pay-order / get / cancel\r\n- fc_order_code : create-order → cancel / checkout\r\n- order_id (again): for pay_per_call it IS the EVO merchantTransID — YOU (the developer/Agent)\r\n use it to drive your own EVO payment call BEFORE pay-order (see step 6); pay-order itself\r\n takes no separate merchant-transaction-id, it only verifies the payment already made\r\n- task_order_code : checkout → get-checkout\r\n\r\n## Billing modes (chosen server-side by billing_mode)\r\n\r\npay-order takes only --order-id; there is NO merchant-transaction-id flag. The platform\r\nroutes purely by the order's billing_mode:\r\n\r\n| Developer billing_mode | Behavior |\r\n|------------------------|----------|\r\n| monthly_settlement | Deducts settlement balance → payOrder |\r\n| pay_per_call | Platform queries EVO for the order_id → verify exact amount/currency → payOrder (response settlement_path is \"pay_per_call\") |\r\n| anything else | ERROR: BILLING_MODE_MISMATCH (only the two modes above are valid) |\r\n\r\n## pay_per_call flow — the EVO merchantTransID IS the order_id\r\n\r\n1. create-order returns order_id + total_amount + currency (no EVO credentials in response)\r\n2. YOU drive your own EVO payment integration now, passing the order_id as the EVO\r\n merchantTransID, and get the user to pay total_amount+currency\r\n (the shared EVO parameters are onboarded separately, out of band — pay-order does not do\r\n this step for you)\r\n3. ONLY once that EVO payment is complete, call pay-order --order-id <order_id>\r\n (no other identifier)\r\n4. Platform queries EVO for that order_id: paid + exact amount/currency match → payOrder → PAID\r\n5. If not yet paid → PAYMENT_NOT_COMPLETED; use --watch to auto-poll\r\n6. Why order_id (not an arbitrary id): it binds the payment to this exact order, so a caller\r\n cannot present some other already-paid EVO transaction of the same amount.\r\n\r\n## Invariants\r\n\r\n- search: exactly one location branch (both or neither = error)\r\n- Never create-order without a fresh quote (tokens expire)\r\n- Never claim \"booked\" until get returns CONFIRMED\r\n- create-order and pay-order are separate steps; create-order does NOT charge\r\n- pay-order depends on create-order's output (order_id)\r\n- Write verbs (create-order/pay-order/cancel/checkout) always need --idempotency-key and --yes\r\n- IMPORTANT: --yes only skips this CLI's own interactive TTY prompt (needed because the Agent\r\n runs non-interactively). It is NOT a substitute for showing the user the hotel/rate/price and\r\n getting their decision in the chat UI. Passing --yes does not remove the confirmation steps in\r\n step 3/4 (choose hotel + rate) or step 7 (confirm before pay-order) above.\r\n- After a cancel call returns successfully (including the cancel_status='cancel_pending' shape),\r\n do NOT call cancel again for the same order — poll get instead. A pending acknowledgement is\r\n success, not failure.\r\n\r\n## Errors\r\n\r\n- RESOURCE_NOT_FOUND (find-destination) → platform 404 for this keyword, distinct from an\r\n empty destinations[] (which is a normal no-match, not an error). Do not keep retrying the\r\n keyword — fall back to the coordinate branch (search/hotel-filters --lat/--lng) if you can\r\n geocode the place or already know its coordinates; otherwise ask the user for a city or a\r\n more specific landmark.\r\n- BILLING_MODE_MISMATCH → order billing_mode is not monthly_settlement or pay_per_call\r\n- ACCOUNT_INSUFFICIENT_BALANCE → settlement account needs top-up; inform user\r\n- PAYMENT_NOT_COMPLETED → EVO not confirmed yet; retry (--watch) or wait\r\n- PAYMENT_NOT_FOUND → no EVO transaction for that ID; verify with user\r\n- PAYMENT_AMOUNT_MISMATCH → EVO amount/currency ≠ order; user must pay correct amount\r\n- PAYORDER_FAILED → upstream payOrder failed; money refunded, safe to retry\r\n- PAYORDER_FAILED_AFTER_PAYMENT → EVO confirmed but payOrder failed; needs reconciliation\r\n- UPSTREAM_ERROR → transient provider issue; wait and retry once\r\n- PARAM_INVALID → bad argument; run <verb> --help and correct it\r\n- empty rates[] → no rooms; suggest other dates or hotels\r\n`.trim();\r\n\r\n/**\r\n * \\`hotel-redaug skill\\` — output the usage guide for AI Agents.\r\n *\r\n * Pure read-only command: no API call, no state change. Prints a structured\r\n * skill document that teaches an Agent how to orchestrate hotel-redaug verbs.\r\n * Detailed parameter specs live in the schema (services get) and per-verb --help.\r\n */\r\nexport function registerHotelSkillCommand(parent: Command): void {\r\n parent\r\n .command('skill')\r\n .description('Print the hotel-redaug usage guide (orchestration flow, data passing, rules)')\r\n .action(() => {\r\n console.log(SKILL_TEXT);\r\n });\r\n}\r\n","/**\r\n * Shared input/output helpers for the flight-flink command group.\r\n *\r\n * Mirrors the ride-elife / hotel-redaug conventions: required-flag validation\r\n * maps to `PARAM_INVALID` (catalog code, exit 1); JSON array flags are parsed +\r\n * shape-checked before any request; results render via renderWithContext.\r\n */\r\nimport { CliError, Formatter, PromptEngine } from '@agenzo/cli-core';\r\nimport type { ApiClient, CommandResult } from '@agenzo/cli-core';\r\nimport { ConfigManager, resolveFormat, renderWithContext } from '@agenzo/cli-core';\r\n\r\nexport type Deps = { apiClient: ApiClient };\r\n\r\n/** Require a flag value; missing → PARAM_INVALID. */\r\nexport function need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Parse a numeric flag; non-number → PARAM_INVALID. */\r\nexport function num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/** Parse a JSON-array flag; non-JSON / non-array → PARAM_INVALID. Returned verbatim. */\r\nexport function jsonArray(raw: string, flag: string): unknown[] {\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a JSON array.`);\r\n }\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a JSON array.`);\r\n }\r\n return parsed;\r\n}\r\n\r\n/** Resolve the API key (flag or interactive password prompt). */\r\nexport function resolveApiKey(flag: string | undefined): Promise<string> {\r\n return PromptEngine.resolveInput(flag, { message: 'API Key:', type: 'password' });\r\n}\r\n\r\n/** Render a success result: JSON envelope in json mode, pretty text otherwise. */\r\nexport async function render<T>(\r\n data: T,\r\n format: string | undefined,\r\n text: (d: T) => string,\r\n): Promise<void> {\r\n const resolved = resolveFormat(format);\r\n const result: CommandResult<T> = { data, text: () => text(data) };\r\n await renderWithContext(result, { format: resolved }, new ConfigManager());\r\n}\r\n\r\n/** Compact key/value renderer for arbitrary record data. */\r\nexport function kv(data: Record<string, unknown>): string {\r\n const lines: [string, string][] = Object.entries(data).map(([k, v]) => [\r\n k,\r\n typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v ?? '-'),\r\n ]);\r\n return Formatter.keyValue(lines);\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightFindAirportSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink find-airport` — resolve free-text into city/airport candidates. */\r\nexport function registerFindAirportCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('find-airport')\r\n .description('Resolve free-text into city/airport candidates')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--keyword <text>', 'Free-text place/airport/city name');\r\n attachSchemaHelp(cmd, flightFindAirportSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const keyword = need(opts.keyword as string | undefined, 'keyword');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Resolving airports...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/find-airport',\r\n { type: 'api-key', key: apiKey },\r\n { keyword },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n JSON.stringify(d.airports ?? d, null, 2),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightListAirportsSchema } from '../verb-schema.js';\r\nimport { type Deps, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink list-airports` — paged airport dictionary. */\r\nexport function registerListAirportsCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-airports')\r\n .description('Paged airport dictionary')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--page <n>', 'Page (1-based)', '1')\r\n .option('--page-size <n>', 'Items per page (1-100)', '20')\r\n .option('--keyword <text>', 'Optional name filter');\r\n attachSchemaHelp(cmd, flightListAirportsSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body: Record<string, unknown> = {\r\n page: num(opts.page as string | undefined, 'page'),\r\n page_size: num(opts.pageSize as string | undefined, 'page-size'),\r\n };\r\n if (opts.keyword !== undefined) body.keyword = opts.keyword as string;\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching airports...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/airports',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightListAirlinesSchema } from '../verb-schema.js';\r\nimport { type Deps, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink list-airlines` — paged airline dictionary. */\r\nexport function registerListAirlinesCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-airlines')\r\n .description('Paged airline dictionary')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--page <n>', 'Page (1-based)', '1')\r\n .option('--page-size <n>', 'Items per page (1-100)', '20')\r\n .option('--keyword <text>', 'Optional name filter');\r\n attachSchemaHelp(cmd, flightListAirlinesSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body: Record<string, unknown> = {\r\n page: num(opts.page as string | undefined, 'page'),\r\n page_size: num(opts.pageSize as string | undefined, 'page-size'),\r\n };\r\n if (opts.keyword !== undefined) body.keyword = opts.keyword as string;\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching airlines...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/airlines',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightListNationalitiesSchema } from '../verb-schema.js';\r\nimport { type Deps, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink list-nationalities` — nationality list (no params). */\r\nexport function registerListNationalitiesCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-nationalities')\r\n .description('Nationality list')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n attachSchemaHelp(cmd, flightListNationalitiesSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching nationalities...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/nationalities',\r\n { type: 'api-key', key: apiKey },\r\n {},\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { SearchFlightResponse } from '../types/flight.js';\r\nimport { attachSchemaHelp, flightSearchSchema } from '../verb-schema.js';\r\nimport { type Deps, jsonArray, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink search` — search flights (one-way/round-trip/multi-city, journeyId relay). */\r\nexport function registerSearchCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('search')\r\n .description('Search flights (one-way/round-trip/multi-city, journeyId relay)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--trip-type <n>', '1=one-way, 2=round-trip, 3=multi-city')\r\n .option('--journeys <json>', 'JSON array of {date, origin, destination, origin_type?, destination_type?}')\r\n .option('--cabin-class <c>', 'economy | premium_economy | business | first', 'economy')\r\n .option('--adult-num <n>', 'Adults (1-9)', '1')\r\n .option('--child-num <n>', 'Children (0-9)', '0')\r\n .option('--infant-num <n>', 'Infants (0-9)', '0')\r\n .option('--airline <code>', 'Airline 2-letter code filter')\r\n .option('--transfer-number <n>', '0=any,1=direct,2=1 stop,3=2 stops', '0')\r\n .option('--journey-id <json>', \"Relay: the chosen offer's next_journey_ids, verbatim (round-trip/multi-city)\");\r\n attachSchemaHelp(cmd, flightSearchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const body: Record<string, unknown> = {\r\n trip_type: num(opts.tripType as string | undefined, 'trip-type'),\r\n journeys: jsonArray(need(opts.journeys as string | undefined, 'journeys'), 'journeys'),\r\n cabin_class: opts.cabinClass as string,\r\n adult_num: num(opts.adultNum as string | undefined, 'adult-num'),\r\n child_num: num(opts.childNum as string | undefined, 'child-num'),\r\n infant_num: num(opts.infantNum as string | undefined, 'infant-num'),\r\n transfer_number: num(opts.transferNumber as string | undefined, 'transfer-number'),\r\n };\r\n if (opts.airline !== undefined) body.airline = opts.airline as string;\r\n if (opts.journeyId !== undefined) {\r\n body.journey_id = jsonArray(opts.journeyId as string, 'journey-id');\r\n }\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Searching flights...');\r\n const result = await deps.apiClient.post<SearchFlightResponse>(\r\n '/flight/search',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightMoreOffersSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink more-offers` — more fare offers for a priceKey. */\r\nexport function registerMoreOffersCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('more-offers')\r\n .description('More fare offers for a priceKey (carried by product_token)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--product-token <token>', 'Opaque token from search');\r\n attachSchemaHelp(cmd, flightMoreOffersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const productToken = need(opts.productToken as string | undefined, 'product-token');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching offers...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/more-offers',\r\n { type: 'api-key', key: apiKey },\r\n { product_token: productToken },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { VerifyFlightResponse } from '../types/flight.js';\r\nimport { attachSchemaHelp, flightVerifySchema } from '../verb-schema.js';\r\nimport { type Deps, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink verify` — pre-booking price verification. */\r\nexport function registerVerifyCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('verify')\r\n .description('Verify the latest price before booking; returns the authoritative product_token')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--product-token <token>', 'Opaque token from search')\r\n // 任务 4「价格变了自动刷新」:以下 5 个全部可选,缺省不下发(请求体与加入前逐字相同)。\r\n // previous-total-price:选中那一轮 offer 的总价;带上它,供应商 1002/1950 时平台会按\r\n // token 自解行程重搜一次找回同一班,响应带回 previous_total_price 供确认卡显示 原价→新价。\r\n // 其余 4 个仅重搜时使用(token 里没有舱位/乘客数),保证找回用户原本选定的那档产品。\r\n .option('--previous-total-price <n>', 'Total price of the selected offer; enables the one-shot re-search refresh on supplier 1002/1950')\r\n .option('--cabin-class <c>', 'Cabin class to re-search with (economy | premium_economy | business | first)')\r\n .option('--adult-num <n>', 'Adults to re-search with (1-9)')\r\n .option('--child-num <n>', 'Children to re-search with (0-9)')\r\n .option('--infant-num <n>', 'Infants to re-search with (0-9)');\r\n attachSchemaHelp(cmd, flightVerifySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const productToken = need(opts.productToken as string | undefined, 'product-token');\r\n\r\n const body: Record<string, unknown> = { product_token: productToken };\r\n if (opts.previousTotalPrice !== undefined) {\r\n body.previous_total_price = num(opts.previousTotalPrice as string, 'previous-total-price');\r\n }\r\n if (opts.cabinClass !== undefined) body.cabin_class = opts.cabinClass as string;\r\n if (opts.adultNum !== undefined) body.adult_num = num(opts.adultNum as string, 'adult-num');\r\n if (opts.childNum !== undefined) body.child_num = num(opts.childNum as string, 'child-num');\r\n if (opts.infantNum !== undefined) body.infant_num = num(opts.infantNum as string, 'infant-num');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Verifying price...');\r\n const result = await deps.apiClient.post<VerifyFlightResponse>(\r\n '/flight/verify',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n Formatter.keyValue([\r\n ['Product token', String(d.product_token ?? '-')],\r\n ['Total price', `${d.total_price ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ['Price changed', String(d.price_changed)],\r\n // 刷新路径:平台带回选中时的原价,人读 output 里直接看出 原价 → 新价。\r\n ...(d.previous_total_price != null\r\n ? ([['Previous total price', String(d.previous_total_price)]] as [string, string][])\r\n : []),\r\n ]),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { CreateFlightOrderResponse } from '../types/flight.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightCreateOrderSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { type Deps, jsonArray, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/**\r\n * `flight-flink create-order` — create a flight order without charging (locks the\r\n * fare). Calls POST /flight/create-order with an Idempotency-Key header. The order\r\n * enters AWAITING_PAYMENT and must be settled via pay-order. Non-`--yes` path\r\n * confirms (restating amount) before the write; a declined confirm → CLIENT_ABORTED.\r\n */\r\nexport function registerCreateOrderCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('create-order')\r\n .description('Create a flight order without charging (locks the fare, await payment)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--product-token <token>', 'Authoritative rate token from verify')\r\n .option('--total-amount <amount>', 'Verified total price in decimal units')\r\n .option('--currency <currency>', 'ISO 4217 currency code')\r\n .option('--trip-type <n>', '1/2/3', '1')\r\n .option('--contact-name <name>', 'Booking contact name')\r\n .option('--contact-region <code>', \"Contact phone country code (no '+')\")\r\n .option('--contact-phone <phone>', 'Booking contact phone')\r\n .option('--contact-email <email>', 'Booking contact email')\r\n .option(\r\n '--passengers <json>',\r\n 'JSON array of passengers (gender/id_type are strings). A passenger may be just ' +\r\n '{\"traveller_token\":\"tvp_...\",\"type\":\"adult\"} from token-cli travellers list.',\r\n )\r\n .option('--save-travellers', 'Save the fully filled passengers as frequent travellers (only when the user asked)')\r\n .option('--payment-method-id <id>', 'Optional bound-card id (pay_per_call only)')\r\n .option('--payment-token-id <id>', 'Optional UPI network-token id (unionpay charge path)')\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'EVO merchant transaction id of an already-authorised preauth (3DS challenge resume). ' +\r\n 'When set, the server reuses that authorization instead of creating a new one, ' +\r\n 'avoiding a second hold on the card (pay_per_call mode only).',\r\n )\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightCreateOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const productToken = need(opts.productToken as string | undefined, 'product-token');\r\n const totalAmount = num(opts.totalAmount as string | undefined, 'total-amount');\r\n const currency = need(opts.currency as string | undefined, 'currency');\r\n const body: Record<string, unknown> = {\r\n product_token: productToken,\r\n total_amount: totalAmount,\r\n currency,\r\n trip_type: num(opts.tripType as string | undefined, 'trip-type'),\r\n contact_name: need(opts.contactName as string | undefined, 'contact-name'),\r\n contact_region: need(opts.contactRegion as string | undefined, 'contact-region'),\r\n contact_phone: need(opts.contactPhone as string | undefined, 'contact-phone'),\r\n contact_email: need(opts.contactEmail as string | undefined, 'contact-email'),\r\n passengers: jsonArray(need(opts.passengers as string | undefined, 'passengers'), 'passengers'),\r\n };\r\n // 常用旅客:只在用户要求保存时才带,缺省不出现在请求体里(老调用方逐字不变)。\r\n if (opts.saveTravellers) body.save_travellers = true;\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n // UPI(unionpay) 扣款路径:透传已 ACTIVE 的 network token id;platform create-order\r\n // 据 payment_token_id 非空走 ChargeService 实扣(跳过 EVO 预授权/捕获)。\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n // 3DS 挑战续单凭证:持卡人完成认证后带回该交易号,服务端复用那笔已授权的预授权,\r\n // 不再新发起一次(否则又拿到新挑战页且重复冻结资金)。\r\n if (opts.authorizedMerchantTransId) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 归因标签(可选):非空才写入,缺省保持无归属。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Create this flight order for ${totalAmount} ${currency}? This locks the fare but does NOT charge yet.`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Order creation aborted by user.');\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink create-order',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Creating flight order...');\r\n const result = await deps.apiClient.post<CreateFlightOrderResponse>(\r\n '/flight/create-order',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n [\r\n Formatter.keyValue([\r\n ['Order no', String(d.order_no ?? '-')],\r\n ['Upstream order no', String(d.upstream_order_no ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Total amount', `${d.total_amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ]),\r\n Formatter.status(\r\n 'info',\r\n `Order created (AWAITING_PAYMENT) — settle with 'flight-flink pay-order --order-no ${d.order_no ?? '<order_no>'}'.`,\r\n ),\r\n ].join('\\n\\n'),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { PayFlightOrderResponse } from '../types/flight.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { PRICE_ANNOTATION_FLAGS, applyPriceAnnotation } from '../price-annotation.js';\r\nimport { attachSchemaHelp, flightPayOrderSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/**\r\n * `flight-flink pay-order` — settle a created order by --order-no (triggers upstream\r\n * ticketing). AWAITING_PAYMENT → PAID. Non-`--yes` path confirms before the write.\r\n */\r\nexport function registerPayOrderCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('pay-order')\r\n .description('Settle a created order by --order-no (triggers ticketing)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference from create-order')\r\n .option('--payment-method-id <id>', 'Optional bound-card id to charge (pay_per_call only)')\r\n .option('--payment-token-id <id>', 'Optional network-token id (unionpay/visa charge path)')\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'Resume an EVO-card 3DS challenge: merchant trans id of an already-authorised preauth',\r\n )\r\n .option(\r\n '--authenticate',\r\n 'Opt-in to require cardholder 3DS on the network-token direct charge (--payment-token-id, EVO/Mastercard). When a step-up is needed the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume with --authorized-charge-no. Default off = frictionless.',\r\n )\r\n .option(\r\n '--return-url <url>',\r\n 'Optional 3DS/passkey return URL for the network-token authenticate path (falls back to the platform EVO_3DS_RETURN_URL)',\r\n )\r\n .option(\r\n '--authorized-charge-no <no>',\r\n 'Resume a network-token 3DS challenge: charge_no returned by a prior AUTHENTICATION_REQUIRED response (settled via ChargeService.resume_token)',\r\n )\r\n .option(\r\n '--evo-explicit',\r\n '[方案 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side.',\r\n )\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header')\r\n .option(\r\n '--original-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['original-amount-cents'].description,\r\n )\r\n .option(\r\n '--discount-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['discount-amount-cents'].description,\r\n );\r\n attachSchemaHelp(cmd, flightPayOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const orderNo = need(opts.orderNo as string | undefined, 'order-no');\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Pay and ticket order ${orderNo}? This settles the order and issues tickets.`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Payment aborted by user.');\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink pay-order',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Paying flight order...');\r\n // 支付凭证在 pay 而非 create-order:平台侧 create-order 只锁座位/锁价、分文不碰钱,\r\n // 扣款发生在这一步。全部可选 —— 省略时平台按订单 billing_mode 自行分流(月结扣额度、\r\n // 现结选默认卡)。CLI 是薄透传层,不做必填校验。\r\n const body: Record<string, unknown> = {};\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n if (opts.authorizedMerchantTransId !== undefined) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 网络令牌支付时 3DS(opt-in):仅置位时透传 authenticate=true;return_url 可选(缺省平台\r\n // 回落 EVO_3DS_RETURN_URL);authorized_charge_no 是续付句柄。\r\n if (opts.authenticate) body.authenticate = true;\r\n if (opts.returnUrl !== undefined) body.return_url = opts.returnUrl as string;\r\n if (opts.authorizedChargeNo !== undefined) {\r\n body.authorized_charge_no = opts.authorizedChargeNo as string;\r\n }\r\n // 方案 B/R16 显式 EVO 选择信号:仅在置位时透传 evo_explicit=true;缺省则不发(平台默认 false)。\r\n if (opts.evoExplicit) body.evo_explicit = true;\r\n // 价格批注(原价 / 优惠,纯记录):落订单 auth_snapshot + 统一流水并在订单详情回显,\r\n // 不进网关报文、不参与权威价核验。\r\n applyPriceAnnotation(body, opts);\r\n const result = await deps.apiClient.post<PayFlightOrderResponse>(\r\n `/flight/${encodeURIComponent(orderNo)}/pay`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => {\r\n const rows: [string, string][] = [\r\n ['Order no', String(d.order_no ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Amount', `${d.amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ];\r\n // 网络令牌 3DS 挑战:透出续付句柄与挑战地址,供调用方打开认证页并回带续付。\r\n if (d.charge_no) rows.push(['Charge no', String(d.charge_no)]);\r\n if (d.three_ds_url) rows.push(['3DS URL', String(d.three_ds_url)]);\r\n return Formatter.keyValue(rows);\r\n });\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { GetFlightOrderResponse } from '../types/flight.js';\r\nimport { attachSchemaHelp, flightGetOrderSchema } from '../verb-schema.js';\r\nimport { type Deps, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\nconst TERMINAL = new Set(['TICKETED', 'CANCELLED', 'FAILED']);\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((r) => setTimeout(r, ms));\r\n}\r\n\r\n/**\r\n * `flight-flink get-order` — query order status by --order-no. Read-only. With\r\n * --watch, polls until a terminal status (TICKETED/CANCELLED/FAILED) or timeout,\r\n * emitting one NDJSON line per update.\r\n */\r\nexport function registerGetOrderCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('get-order')\r\n .description('Query a flight order status by id (poll ticketing 5→8)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--watch', 'Poll until a terminal status, one NDJSON line per update')\r\n .option('--watch-interval <seconds>', 'Seconds between polls', '5')\r\n .option('--watch-timeout <seconds>', 'Max seconds to poll', '600');\r\n attachSchemaHelp(cmd, flightGetOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const orderNo = need(opts.orderNo as string | undefined, 'order-no');\r\n const path = `/flight/${encodeURIComponent(orderNo)}/status`;\r\n const auth = { type: 'api-key' as const, key: apiKey };\r\n\r\n if (opts.watch) {\r\n const interval = num(opts.watchInterval as string | undefined, 'watch-interval') * 1000;\r\n const timeoutMs = num(opts.watchTimeout as string | undefined, 'watch-timeout') * 1000;\r\n const deadline = Date.now() + timeoutMs;\r\n for (;;) {\r\n const r = await deps.apiClient.get<GetFlightOrderResponse>(path, auth);\r\n if (!r.success) throw CliError.fromApi(r, { auth: 'api-key' });\r\n process.stdout.write(`${JSON.stringify(r.data)}\\n`);\r\n if (TERMINAL.has(String(r.data.status))) return;\r\n if (Date.now() + interval >= deadline) {\r\n process.stdout.write(`${JSON.stringify({ watch_status: 'timeout', order_no: orderNo })}\\n`);\r\n return;\r\n }\r\n await sleep(interval);\r\n }\r\n }\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching flight order status...');\r\n const result = await deps.apiClient.get<GetFlightOrderResponse>(path, auth);\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n Formatter.keyValue([\r\n ['Order no', String(d.order_no ?? '-')],\r\n ['Upstream order no', String(d.upstream_order_no ?? '-')],\r\n ['PNR', String(d.pnr ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Total amount', `${d.total_amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ]),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { CancelFlightResponse } from '../types/flight.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightCancelOrderSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/**\r\n * `flight-flink cancel-order` — cancel an un-ticketed order by --order-no (with\r\n * refund). A ticketed order is rejected upstream. Non-`--yes` path confirms first.\r\n */\r\nexport function registerCancelOrderCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('cancel-order')\r\n .description('Cancel an un-ticketed flight order (with refund)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--reason <text>', 'Optional cancellation reason')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightCancelOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const orderNo = need(opts.orderNo as string | undefined, 'order-no');\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Cancel order ${orderNo}? This requests cancellation and a refund.`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Cancellation aborted by user.');\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink cancel-order',\r\n });\r\n\r\n const body: Record<string, unknown> = {};\r\n if (opts.reason !== undefined) body.reason = opts.reason as string;\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Cancelling flight order...');\r\n const result = await deps.apiClient.post<CancelFlightResponse>(\r\n `/flight/${encodeURIComponent(orderNo)}/cancel`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n Formatter.keyValue([\r\n ['Order no', String(d.order_no ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Refund amount', `${d.refund_amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ]),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { ListFlightOrdersResponse } from '../types/flight.js';\r\nimport { attachSchemaHelp, flightListOrdersSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { type Deps, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink list-orders` — list the developer's flight orders (local read). */\r\nexport function registerListOrdersCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-orders')\r\n .description(\"List the developer's flight orders (local read, no upstream call)\")\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--status <status>', 'Optional status filter')\r\n .option('--page <n>', 'Page (1-based)', '1')\r\n .option('--page-size <n>', 'Items per page (1-100)', '20')\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n attachSchemaHelp(cmd, flightListOrdersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const params = new URLSearchParams();\r\n if (opts.status !== undefined) params.set('status', opts.status as string);\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) params.set('member_id', member);\r\n params.set('page', String(num(opts.page as string | undefined, 'page')));\r\n params.set('page_size', String(num(opts.pageSize as string | undefined, 'page-size')));\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching flight orders...');\r\n const result = await deps.apiClient.get<ListFlightOrdersResponse>(\r\n `/flight/orders?${params.toString()}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => {\r\n const rows = (d.orders ?? []).map((o) => [\r\n String(o.order_no ?? '-'),\r\n String(o.status ?? '-'),\r\n `${o.total_amount ?? '-'} ${o.currency ?? ''}`.trim(),\r\n ]);\r\n return Formatter.table(['Order no', 'Status', 'Amount'], rows);\r\n });\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightChangeSearchSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink change-search` — search rebook-eligible flights for an order. */\r\nexport function registerChangeSearchCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-search')\r\n .description('Search rebook-eligible flights for an order')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--date <date>', 'Target change date YYYY-MM-DD')\r\n .option('--passenger <code>', 'passengerCode')\r\n .option('--segment-id <ids>', 'Comma-separated segment ids')\r\n .option('--cabin-class <c>', 'Cabin class', 'economy');\r\n attachSchemaHelp(cmd, flightChangeSearchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body = {\r\n order_no: need(opts.orderNo as string | undefined, 'order-no'),\r\n date: need(opts.date as string | undefined, 'date'),\r\n passenger: need(opts.passenger as string | undefined, 'passenger'),\r\n segment_id: need(opts.segmentId as string | undefined, 'segment-id'),\r\n cabin_class: opts.cabinClass as string,\r\n };\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Searching change options...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/change/search',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightChangeApplySchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink change-apply` — submit a change request (pending review). */\r\nexport function registerChangeApplyCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-apply')\r\n .description('Submit a change request (returns change_order_no, pending review)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--passenger <code>', 'passengerCode')\r\n .option('--segment-id <ids>', 'Comma-separated segment ids')\r\n .option('--product-token <token>', 'Change priceKey token')\r\n .option('--contact-name <name>', 'Contact name')\r\n .option('--contact-region <code>', 'Contact region')\r\n .option('--contact-phone <phone>', 'Contact phone')\r\n .option('--contact-email <email>', 'Contact email')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightChangeApplySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body = {\r\n order_no: need(opts.orderNo as string | undefined, 'order-no'),\r\n passenger: need(opts.passenger as string | undefined, 'passenger'),\r\n segment_id: need(opts.segmentId as string | undefined, 'segment-id'),\r\n product_token: need(opts.productToken as string | undefined, 'product-token'),\r\n contact_name: need(opts.contactName as string | undefined, 'contact-name'),\r\n contact_region: need(opts.contactRegion as string | undefined, 'contact-region'),\r\n contact_phone: need(opts.contactPhone as string | undefined, 'contact-phone'),\r\n contact_email: need(opts.contactEmail as string | undefined, 'contact-email'),\r\n };\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Submit a change request for order ${body.order_no}?`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Change request aborted by user.');\r\n }\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink change-apply',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Submitting change request...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/change/apply',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightChangeDetailSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink change-detail` — change request detail by --change-order-no. */\r\nexport function registerChangeDetailCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-detail')\r\n .description('Change request detail by change order number')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--change-order-no <id>', 'Change order number');\r\n attachSchemaHelp(cmd, flightChangeDetailSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const changeOrderNo = need(opts.changeOrderNo as string | undefined, 'change-order-no');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching change detail...');\r\n const result = await deps.apiClient.get<Record<string, unknown>>(\r\n `/flight/change/${encodeURIComponent(changeOrderNo)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightChangeCancelSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink change-cancel` — cancel a change request (immediate terminal). */\r\nexport function registerChangeCancelCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-cancel')\r\n .description('Cancel a change request (immediate terminal)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--change-order-no <id>', 'Change order number')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightChangeCancelSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const changeOrderNo = need(opts.changeOrderNo as string | undefined, 'change-order-no');\r\n\r\n if (!isYes) {\r\n const ok = await confirm({ message: `Cancel change request ${changeOrderNo}?`, default: false });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Change cancellation aborted by user.');\r\n }\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink change-cancel',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Cancelling change request...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n `/flight/change/${encodeURIComponent(changeOrderNo)}/cancel`,\r\n { type: 'api-key', key: apiKey },\r\n {},\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { PRICE_ANNOTATION_FLAGS, applyPriceAnnotation } from '../price-annotation.js';\r\nimport { attachSchemaHelp, flightChangePaySchema } from '../verb-schema.js';\r\nimport { type Deps, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/**\r\n * `flight-flink change-pay` — pay a change request's fee and trigger upstream change\r\n * ticketing. Charges the change fee like a normal order (UPI network-token when\r\n * --payment-token-id is given, else EVO), then calls flink pay(type=1) for the change\r\n * order. Calls POST /flight/change/{change_order_no}/pay with an Idempotency-Key header.\r\n * Non-`--yes` path confirms (restating amount) before the write.\r\n * --authorized-merchant-trans-id re-enters this verb after a 3DS challenge: no second\r\n * authorization is made — the platform reuses the already-authorised preauth, captures it\r\n * and finishes ticketing.\r\n */\r\nexport function registerChangePayCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-pay')\r\n .description('Pay a change request fee (like a normal order) and trigger change ticketing')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--change-order-no <id>', 'Change order number')\r\n .option('--order-no <id>', 'Original order reference (ownership check)')\r\n .option('--amount <amount>', 'Change fee total in decimal units (change-detail price_total)')\r\n .option('--currency <currency>', 'ISO 4217 currency code', 'USD')\r\n .option('--payment-method-id <id>', 'Optional bound-card id (EVO path)')\r\n .option('--payment-token-id <id>', 'Optional UPI network-token id (unionpay charge path)')\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'Resume a 3DS challenge: merchant trans id of the already-authorised preauth',\r\n )\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header')\r\n .option(\r\n '--original-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['original-amount-cents'].description,\r\n )\r\n .option(\r\n '--discount-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['discount-amount-cents'].description,\r\n );\r\n attachSchemaHelp(cmd, flightChangePaySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const changeOrderNo = need(opts.changeOrderNo as string | undefined, 'change-order-no');\r\n const orderNo = need(opts.orderNo as string | undefined, 'order-no');\r\n const amount = num(opts.amount as string | undefined, 'amount');\r\n const currency = need(opts.currency as string | undefined, 'currency');\r\n const body: Record<string, unknown> = {\r\n order_no: orderNo,\r\n amount,\r\n currency,\r\n };\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n // UPI(unionpay) 扣款路径:透传已 ACTIVE 的 network token id;platform change-pay\r\n // 据 payment_token_id 非空走 ChargeService 实扣(跳过 EVO 预授权/捕获)。\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n // 3DS 挑战续付凭证:改签费现结走 EVO 预授权 + 捕获。预授权遇 EVO 要求持卡人认证时资金\r\n // 尚未冻结,平台返回挑战;前端带用户认证完成后用这个参数重入 change-pay,平台复用那笔\r\n // 已认证通过的预授权再 capture,不再新发起一次授权(否则每轮都在卡上多冻结一笔)。\r\n if (opts.authorizedMerchantTransId !== undefined) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 价格批注(原价 / 优惠,纯记录):改签扣款额仍是上游权威 price_total,这两个值只落\r\n // 改签单的 payment_snapshot + 统一流水,不进网关报文、不参与那道权威价交叉校验。\r\n applyPriceAnnotation(body, opts);\r\n\r\n if (!isYes) {\r\n // 续单路径上钱已经扣过了,别再跟操作员说「charges the customer」。\r\n const isResume = opts.authorizedMerchantTransId !== undefined;\r\n const message = isResume\r\n ? `Resume change fee ${amount} ${currency} for change order ${changeOrderNo}? The card is already authorised; this captures it and triggers change ticketing.`\r\n : `Pay change fee ${amount} ${currency} for change order ${changeOrderNo}? This charges the customer and triggers change ticketing.`;\r\n const ok = await confirm({ message, default: false });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Change payment aborted by user.');\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink change-pay',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Paying change request...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n `/flight/change/${encodeURIComponent(changeOrderNo)}/pay`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => {\r\n // 3DS 挑战:平台把它放在 `challenge` 键下(内含自己的 `status`),顶层没有\r\n // payment_status。照原样按已扣款渲染会打出一张几乎全是 '-' 的表,并且告诉操作员\r\n // 「Change fee charged」——而这笔连预授权都还没冻结成功。\r\n const challenge = (d.challenge ?? null) as Record<string, unknown> | null;\r\n if (challenge) {\r\n return [\r\n Formatter.keyValue([\r\n ['Change order no', String(challenge.change_order_no ?? '-')],\r\n ['Status', String(challenge.status ?? '-')],\r\n ['Amount', `${challenge.amount ?? '-'} ${challenge.currency ?? ''}`.trim()],\r\n ['Authentication URL', String(challenge.three_ds_url ?? '-')],\r\n ['Merchant trans id', String(challenge.merchant_trans_id ?? '-')],\r\n ]),\r\n Formatter.status(\r\n 'warning',\r\n 'Not charged yet — the card requires 3-D Secure and the funds are not held. '\r\n + 'Open the authentication URL, then re-run change-pay with '\r\n + '--authorized-merchant-trans-id <merchant trans id>.',\r\n ),\r\n ].join('\\n\\n');\r\n }\r\n return [\r\n Formatter.keyValue([\r\n ['Change order no', String(d.change_order_no ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Amount', `${d.amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ['Payment status', String(d.payment_status ?? '-')],\r\n ]),\r\n Formatter.status('info', 'Change fee charged; change ticketing triggered. Poll change-detail until SUCCESS.'),\r\n ].join('\\n\\n');\r\n });\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightRefundApplySchema } from '../verb-schema.js';\r\nimport { type Deps, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink refund-apply` — submit a refund request (pending review). */\r\nexport function registerRefundApplyCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('refund-apply')\r\n .description('Submit a refund request (returns refund_order_no, pending review)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--passenger <code>', 'passengerCode')\r\n .option('--segment-id <ids>', 'Comma-separated segment ids')\r\n .option('--reason-type <n>', 'Refund reason type code')\r\n .option('--reason <text>', 'Free-text reason')\r\n .option('--contact-name <name>', 'Contact name')\r\n .option('--contact-region <code>', 'Contact region')\r\n .option('--contact-phone <phone>', 'Contact phone')\r\n .option('--contact-email <email>', 'Contact email')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightRefundApplySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body: Record<string, unknown> = {\r\n order_no: need(opts.orderNo as string | undefined, 'order-no'),\r\n passenger: need(opts.passenger as string | undefined, 'passenger'),\r\n segment_id: need(opts.segmentId as string | undefined, 'segment-id'),\r\n reason_type: num(opts.reasonType as string | undefined, 'reason-type'),\r\n contact_name: need(opts.contactName as string | undefined, 'contact-name'),\r\n contact_region: need(opts.contactRegion as string | undefined, 'contact-region'),\r\n contact_phone: need(opts.contactPhone as string | undefined, 'contact-phone'),\r\n contact_email: need(opts.contactEmail as string | undefined, 'contact-email'),\r\n };\r\n if (opts.reason !== undefined) body.reason = opts.reason as string;\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Submit a refund request for order ${body.order_no}?`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Refund request aborted by user.');\r\n }\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink refund-apply',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Submitting refund request...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/refund/apply',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightRefundDetailSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink refund-detail` — refund request detail by --refund-order-no. */\r\nexport function registerRefundDetailCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('refund-detail')\r\n .description('Refund request detail by refund order number')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--refund-order-no <id>', 'Refund order number');\r\n attachSchemaHelp(cmd, flightRefundDetailSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const refundOrderNo = need(opts.refundOrderNo as string | undefined, 'refund-order-no');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching refund detail...');\r\n const result = await deps.apiClient.get<Record<string, unknown>>(\r\n `/flight/refund/${encodeURIComponent(refundOrderNo)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightRefundConfirmSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink refund-confirm` — confirm (\"1\") or cancel (\"2\") a refund. */\r\nexport function registerRefundConfirmCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('refund-confirm')\r\n .description('Confirm (\"1\") or cancel (\"2\") a refund')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--refund-order-no <id>', 'Refund order number')\r\n .option('--confirm <flag>', '\"1\" confirm / \"2\" cancel')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightRefundConfirmSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const refundOrderNo = need(opts.refundOrderNo as string | undefined, 'refund-order-no');\r\n const confirmFlag = need(opts.confirm as string | undefined, 'confirm');\r\n if (confirmFlag !== '1' && confirmFlag !== '2') {\r\n throw new CliError('PARAM_INVALID', '--confirm must be \"1\" (confirm) or \"2\" (cancel).');\r\n }\r\n\r\n if (!isYes) {\r\n const action = confirmFlag === '1' ? 'confirm' : 'cancel';\r\n const ok = await confirm({ message: `${action} refund ${refundOrderNo}?`, default: false });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Refund confirmation aborted by user.');\r\n }\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink refund-confirm',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Processing refund confirmation...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n `/flight/refund/${encodeURIComponent(refundOrderNo)}/confirm`,\r\n { type: 'api-key', key: apiKey },\r\n { confirm: confirmFlag },\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\n\r\nconst SKILL_TEXT = `\r\n---\r\nname: flight-flink\r\ndescription: Search, book, and manage international flight reservations. Two-step create-then-pay ticketing with journeyId relay for round-trip/multi-city, plus change (rebooking) and refund flows. Use when the user wants to find flights, verify a fare, book a ticket, or view/cancel/change/refund an existing flight order. Not for hotels or rides.\r\n---\r\n\r\n# flight-flink — Agent Skill\r\n\r\nYou orchestrate flight bookings through CLI verbs. This guide covers HOW to chain\r\nverbs and pass data between them. For exact flags and field types, read the schema\r\n(\\`flight-flink <verb> --help --format json\\`).\r\n\r\n## Prerequisites\r\n- API key with merchant scope. Pass --api-key <key> --format json on every call; add --yes on writes.\r\n- Billing is decided server-side by the developer's billing_mode (monthly_settlement or pay_per_call).\r\n\r\n## Workflow (book)\r\n1. find-airport --keyword \"<place>\" → resolve to IATA city/airport codes\r\n2. search --trip-type <1|2|3> --journeys '<json>'\r\n - journeys ALWAYS carries ALL legs, on every call including relay calls.\r\n - Round-trip/multi-city: keep searching until is_final_leg is true. Each round, present the\r\n candidates, let the USER pick one, and pass THAT candidate's next_journey_ids verbatim as\r\n --journey-id on the next search. Never assemble the list yourself (the top-level journey_ids\r\n is flattened across all candidates) and never send more ids than there are legs — it is\r\n rejected, because upstream would otherwise silently answer with the FIRST leg's candidates.\r\n - Only offers where price_key_ready is true carry a real product_token. Earlier-leg candidates\r\n are NOT bare flight rows: total_sale_price is already the WHOLE-TRIP total and\r\n paired_segment_ids names the legs upstream paired with it, so you can show the full\r\n itinerary and real total from the first round — they just are not bookable yet.\r\n - A relay search returning ZERO offers means the journey ids went stale OR that leg sold out\r\n (upstream reports both as an empty list). Restart from leg 1 for fresh ids.\r\n - Code<->type consistency: tag each code with its matching type — an AIRPORT code (e.g. NRT)\r\n uses type 2, a CITY code (e.g. TYO) uses type 1. Mislabeling (e.g. NRT with type 1, since NRT\r\n is an airport whose city is TYO) is rejected with code 400 \"destination not exist\".\r\n find-airport returns the correct type per candidate (city hit → type 1 with children airports;\r\n airport hit → type 2) — pass code + type together verbatim.\r\n3. verify --product-token <token from search>\r\n - Returns the authoritative product_token + price_changed. If price_changed, re-confirm\r\n the new price with the user before booking. Pass the RETURNED token to create-order.\r\n4. create-order --product-token <verify token> --total-amount <verify total> --currency <cur>\r\n --contact-* --passengers '<json>' --idempotency-key <k>\r\n - Locks the fare, NO charge. Order status → AWAITING_PAYMENT. Save order_no.\r\n - passengers: gender/id_type are STRINGS (\"1\"/\"2\"); child/infant require adult_passenger_name.\r\n5. pay-order --order-no <order_no> --idempotency-key <k>\r\n - Settles + triggers ticketing. Status → PAID.\r\n6. get-order --order-no <order_no> [--watch]\r\n - Ticketing is asynchronous. Poll until TICKETED (ticket_infos populated). Do NOT\r\n report success before TICKETED. Single-passenger orders ticket in ~100-110s;\r\n multi-passenger orders (adult+child+infant) take longer (150s+) — widen --watch-timeout\r\n for multi-passenger bookings; still TICKETING past 150s is normal, not a failure.\r\n\r\n## Change (rebooking)\r\n- change-search → change-apply (returns change_order_no) → change-detail\r\n- Confirm branch: pay-order the change order (settlement). Cancel branch: change-cancel.\r\n\r\n## Refund\r\n- refund-apply (returns refund_order_no) → refund-detail → refund-confirm --confirm 1 (confirm)\r\n or --confirm 2 (cancel). Cancel takes effect immediately.\r\n\r\n## Cancel (un-ticketed order)\r\n- cancel-order --order-no <order_no> --idempotency-key <k> → CANCELLED + refund.\r\n A ticketed order is rejected upstream — use refund-apply instead.\r\n\r\n## Data passing\r\n- product_token : search → verify → create-order (opaque; never fabricate or edit; verify's token wins)\r\n- order_no : create-order → pay-order / get-order / cancel-order\r\n- next_journey_ids : chosen offer → next search's --journey-id (relay for round-trip/multi-city)\r\n- change_order_no / refund_order_no : *-apply → *-detail / *-confirm / pay-order (change)\r\n\r\n## Invariants\r\n- Never create-order without a fresh verify (tokens/prices change).\r\n- Never claim \"booked\" until get-order returns TICKETED.\r\n- create-order and pay-order are separate steps; create-order does NOT charge.\r\n- Write verbs (create-order/pay-order/cancel-order/change-apply/change-cancel/refund-apply/\r\n refund-confirm) always need --idempotency-key; reuse the SAME key when retrying the same intent.\r\n- --yes only skips this CLI's interactive prompt (for non-interactive Agents); it does NOT\r\n remove the requirement to confirm the flight/fare/price with the user in the chat UI.\r\n\r\n## Errors\r\n- INVALID_ARGUMENT → bad argument; run <verb> --help and correct it.\r\n- PRICE_CHANGED → price changed since verify; re-verify and confirm the new price.\r\n- ORDER_CREATE_FAILED → upstream create failed; funds released. Safe to retry with same key.\r\n- PAYMENT_FAILED → settlement/payment failed; check balance/method and retry.\r\n- NOT_FOUND → no such order for this key/owner. Do NOT retry blindly.\r\n- IDEMPOTENCY_CONFLICT → same key reused with different params; use a fresh key.\r\n- UPSTREAM_ERROR → transient; retry once after a short wait.\r\n`.trim();\r\n\r\n/** \\`flight-flink skill\\` — print the usage guide for AI Agents (read-only). */\r\nexport function registerFlightSkillCommand(parent: Command): void {\r\n parent\r\n .command('skill')\r\n .description('Print the flight-flink usage guide (orchestration flow, data passing, rules)')\r\n .action(() => {\r\n console.log(SKILL_TEXT);\r\n });\r\n}\r\n"],"mappings":"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","names":["readFile","writeFile","mkdir","chmod","join","homedir","join","homedir","mkdir","chmod","readFile","writeFile","render","need","num","confirm","need","num","phone","seatCount","confirm","confirm","need","confirm","need","phone","confirm","need","confirm","confirm","need","num","confirm","need","need","render","DEFAULT_PAGE","DEFAULT_PAGE_SIZE","positiveInt","formatOrders","confirm","need","confirm","need","num","positiveInt","need","num","YMD_RE","stayDate","formatQuote","confirm","need","num","YMD_RE","stayDate","formatCreateOrder","confirm","confirm","DEFAULT_WATCH_TIMEOUT_SECONDS","formatPayOrder","confirm","need","formatGetOrder","phone","DEFAULT_WATCH_TIMEOUT_SECONDS","need","formatCancel","confirm","need","num","confirm","need","DEFAULT_WATCH_TIMEOUT_SECONDS","DEFAULT_PAGE","DEFAULT_PAGE_SIZE","positiveInt","formatOrders","need","need","num","coord","need","need","need","num","render","need","render","num","render","num","render","render","num","need","render","need","render","need","num","render","confirm","need","num","confirm","render","confirm","need","confirm","render","need","num","render","confirm","need","confirm","render","registerListOrdersCommand","num","render","need","render","confirm","need","confirm","render","need","render","confirm","need","confirm","render","confirm","need","num","confirm","render","confirm","need","num","confirm","render","need","render","confirm","need","confirm","render","SKILL_TEXT","registerListOrdersCommand"]}
1
+ {"version":3,"sources":["../src/index.ts","../../../packages/cli-core/errors/error-catalog.ts","../../../packages/cli-core/errors/errors.ts","../../../packages/cli-core/version/version.ts","../../../packages/cli-core/api-client/client.ts","../../../packages/cli-core/credential-store/credential-store.ts","../../../packages/cli-core/key-store/key-store.ts","../../../packages/cli-core/config/config-manager.ts","../../../packages/cli-core/exit/exit.ts","../../../packages/cli-core/formatter/formatter.ts","../../../packages/cli-core/formatter/output.ts","../../../packages/cli-core/formatter/render-context.ts","../../../packages/cli-core/prompt-engine/prompt-engine.ts","../src/member.ts","../src/price-annotation.ts","../src/ride-elife/watch.ts","../src/verb-schema.ts","../src/ride-elife/quote.ts","../src/ride-elife/book.ts","../src/idempotency.ts","../src/ride-elife/create-order.ts","../src/ride-elife/pay-order.ts","../src/ride-elife/get.ts","../src/ride-elife/cancel.ts","../src/ride-elife/update.ts","../src/ride-elife/trip-status.ts","../src/ride-elife/list-orders.ts","../src/ride-elife/callback.ts","../src/services/registry.ts","../src/services/local-caps.ts","../src/services/list.ts","../src/services/get.ts","../src/orders/list.ts","../src/orders/get.ts","../src/orders/pay-batch.ts","../src/orders/get-payment-group.ts","../src/hotel-redaug/search.ts","../src/hotel-redaug/quote.ts","../src/hotel-redaug/create-order.ts","../src/hotel-redaug/pay-order.ts","../src/hotel-redaug/watch.ts","../src/hotel-redaug/get.ts","../src/hotel-redaug/cancel.ts","../src/hotel-redaug/checkout.ts","../src/hotel-redaug/get-checkout.ts","../src/hotel-redaug/list-orders.ts","../src/hotel-redaug/find-destination.ts","../src/hotel-redaug/hotel-filters.ts","../src/hotel-redaug/list-cities.ts","../src/hotel-redaug/hotel-detail.ts","../src/hotel-redaug/skill.ts","../src/flight-flink/_helpers.ts","../src/flight-flink/find-airport.ts","../src/flight-flink/list-airports.ts","../src/flight-flink/list-airlines.ts","../src/flight-flink/list-nationalities.ts","../src/flight-flink/search.ts","../src/flight-flink/more-offers.ts","../src/flight-flink/verify.ts","../src/flight-flink/create-order.ts","../src/flight-flink/pay-order.ts","../src/flight-flink/get-order.ts","../src/flight-flink/cancel-order.ts","../src/flight-flink/list-orders.ts","../src/flight-flink/change-search.ts","../src/flight-flink/change-apply.ts","../src/flight-flink/change-detail.ts","../src/flight-flink/change-cancel.ts","../src/flight-flink/change-pay.ts","../src/flight-flink/refund-apply.ts","../src/flight-flink/refund-detail.ts","../src/flight-flink/refund-confirm.ts","../src/flight-flink/skill.ts","../src/data-aisa/_helpers.ts","../src/data-aisa/list-categories.ts","../src/data-aisa/search.ts","../src/data-aisa/describe.ts","../src/data-aisa/query.ts"],"sourcesContent":["import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n Formatter,\r\n CliError,\r\n UserCancelError,\r\n toErrorEnvelope,\r\n errorDetailLines,\r\n resolveFormat,\r\n type OutputFormat,\r\n exitCodeFor,\r\n getCurrentVersion,\r\n} from '@agenzo/cli-core';\r\n\r\n// ride-elife commands (injection-style register, D6)\r\nimport { registerQuoteCommand } from './ride-elife/quote.js';\r\nimport { registerBookCommand } from './ride-elife/book.js';\r\nimport { registerRideCreateOrderCommand } from './ride-elife/create-order.js';\r\nimport { registerRidePayOrderCommand } from './ride-elife/pay-order.js';\r\nimport { registerRideGetCommand } from './ride-elife/get.js';\r\nimport { registerCancelCommand } from './ride-elife/cancel.js';\r\nimport { registerRideUpdateCommand } from './ride-elife/update.js';\r\nimport { registerRideTripStatusCommand } from './ride-elife/trip-status.js';\r\nimport { registerListOrdersCommand } from './ride-elife/list-orders.js';\r\nimport { registerRideCallbackCommands } from './ride-elife/callback.js';\r\n\r\n// services commands (CLI-bundled registry, D4)\r\nimport { registerServicesListCommand } from './services/list.js';\r\nimport { registerServiceGetCommand } from './services/get.js';\r\n\r\n// orders commands (unified cross-provider order index — GET /orders)\r\nimport { registerOrdersListCommand } from './orders/list.js';\r\nimport { registerOrdersGetCommand } from './orders/get.js';\r\nimport { registerOrdersPayBatchCommand } from './orders/pay-batch.js';\r\nimport { registerOrdersGetPaymentGroupCommand } from './orders/get-payment-group.js';\r\n\r\n// hotel-redaug commands (injection-style register, D6)\r\nimport { registerHotelSearchCommand } from './hotel-redaug/search.js';\r\nimport { registerHotelQuoteCommand } from './hotel-redaug/quote.js';\r\nimport { registerHotelCreateOrderCommand } from './hotel-redaug/create-order.js';\r\nimport { registerHotelPayOrderCommand } from './hotel-redaug/pay-order.js';\r\nimport { registerHotelGetCommand } from './hotel-redaug/get.js';\r\nimport { registerHotelCancelCommand } from './hotel-redaug/cancel.js';\r\nimport { registerHotelCheckoutCommand } from './hotel-redaug/checkout.js';\r\nimport { registerHotelGetCheckoutCommand } from './hotel-redaug/get-checkout.js';\r\nimport { registerHotelListOrdersCommand } from './hotel-redaug/list-orders.js';\r\nimport { registerHotelFindDestinationCommand } from './hotel-redaug/find-destination.js';\r\nimport { registerHotelFiltersCommand } from './hotel-redaug/hotel-filters.js';\r\nimport { registerHotelListCitiesCommand } from './hotel-redaug/list-cities.js';\r\nimport { registerHotelDetailCommand } from './hotel-redaug/hotel-detail.js';\r\nimport { registerHotelSkillCommand } from './hotel-redaug/skill.js';\r\n\r\n// flight-flink commands (injection-style register, D6)\r\nimport { registerFindAirportCommand } from './flight-flink/find-airport.js';\r\nimport { registerListAirportsCommand } from './flight-flink/list-airports.js';\r\nimport { registerListAirlinesCommand } from './flight-flink/list-airlines.js';\r\nimport { registerListNationalitiesCommand } from './flight-flink/list-nationalities.js';\r\nimport { registerSearchCommand as registerFlightSearchCommand } from './flight-flink/search.js';\r\nimport { registerMoreOffersCommand } from './flight-flink/more-offers.js';\r\nimport { registerVerifyCommand } from './flight-flink/verify.js';\r\nimport { registerCreateOrderCommand as registerFlightCreateOrderCommand } from './flight-flink/create-order.js';\r\nimport { registerPayOrderCommand as registerFlightPayOrderCommand } from './flight-flink/pay-order.js';\r\nimport { registerGetOrderCommand as registerFlightGetOrderCommand } from './flight-flink/get-order.js';\r\nimport { registerCancelOrderCommand as registerFlightCancelOrderCommand } from './flight-flink/cancel-order.js';\r\nimport { registerListOrdersCommand as registerFlightListOrdersCommand } from './flight-flink/list-orders.js';\r\nimport { registerChangeSearchCommand } from './flight-flink/change-search.js';\r\nimport { registerChangeApplyCommand } from './flight-flink/change-apply.js';\r\nimport { registerChangeDetailCommand } from './flight-flink/change-detail.js';\r\nimport { registerChangeCancelCommand } from './flight-flink/change-cancel.js';\r\nimport { registerChangePayCommand } from './flight-flink/change-pay.js';\r\nimport { registerRefundApplyCommand } from './flight-flink/refund-apply.js';\r\nimport { registerRefundDetailCommand } from './flight-flink/refund-detail.js';\r\nimport { registerRefundConfirmCommand } from './flight-flink/refund-confirm.js';\r\nimport { registerFlightSkillCommand } from './flight-flink/skill.js';\r\n\r\n// data-aisa commands (AIsa read-only information lookup, injection-style register, D6)\r\nimport { registerDataListCategoriesCommand } from './data-aisa/list-categories.js';\r\nimport { registerDataSearchCommand } from './data-aisa/search.js';\r\nimport { registerDataDescribeCommand } from './data-aisa/describe.js';\r\nimport { registerDataQueryCommand } from './data-aisa/query.js';\r\n\r\n// Holds the parsed program so the top-level error handler can read the\r\n// resolved `--format` global flag. Assigned inside `main()` once the program\r\n// is constructed; may be undefined if an error is thrown before then.\r\nlet programRef: Command | undefined;\r\n\r\nasync function main() {\r\n // Instantiate shared infrastructure. merchant-cli authenticates per-command\r\n // via `--api-key` (X-Api-Key); there is no Bearer session / AuthService /\r\n // keystore. The no-arg ConfigManager reuses cli-core's default config (the\r\n // environment admin-cli governs) purely to supply the ApiClient baseUrl and\r\n // the json envelope's profile/endpoint — merchant-cli exposes no host\r\n // commands of its own.\r\n const configManager = new ConfigManager(undefined, '/api/merchant/v1');\r\n await configManager.ensureDirectories();\r\n\r\n const apiBaseUrl = await configManager.getApiBaseUrl();\r\n const apiClient = new ApiClient({ baseUrl: apiBaseUrl });\r\n\r\n // Discovery lives at the host root (/api/discovery/v1/catalog), NOT under the\r\n // per-binary merchant prefix, so it needs its own client built from the raw\r\n // host. Built here (not inside the action) so it can be injected/mocked.\r\n const apiHost = await configManager.getApiHost();\r\n const discoveryClient = new ApiClient({ baseUrl: apiHost });\r\n\r\n // Shared deps object for networked commands — API Key is supplied per-command\r\n // (or interactively), so commands only need the HTTP client.\r\n const deps = { apiClient };\r\n\r\n // Create program\r\n const program = new Command();\r\n programRef = program;\r\n program\r\n .name('agenzo-merchant-cli')\r\n .version(getCurrentVersion())\r\n .description(\r\n 'Agenzo merchant fulfillment plane: service discovery (services), ride ordering (ride-elife), hotel booking (hotel-redaug), and flight booking (flight-flink)',\r\n )\r\n .option('--verbose', 'Show verbose logs')\r\n .option('--yes', 'Skip confirmation prompts (for automation/AI Agents)')\r\n // merchant-cli is an agent-first entrypoint, so it defaults to json (D2),\r\n // unlike the cli-core default (table). resolveFormat only acts as a\r\n // fallback when the flag is absent.\r\n .option(\r\n '--format <format>',\r\n 'Output format: json | table (default: json; or set AGENZO_FORMAT)',\r\n 'json',\r\n )\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n\r\n // Mirror the resolved global --format into AGENZO_FORMAT before any action\r\n // runs, so code paths without direct format access can resolve the active\r\n // format and stay silent in json mode.\r\n program.hook('preAction', (thisCommand) => {\r\n const flag = thisCommand.opts().format as string | undefined;\r\n process.env.AGENZO_FORMAT = resolveFormat(flag);\r\n });\r\n\r\n // ride-elife command group (eLife ride ordering)\r\n const rideCmd = program.command('ride-elife').description(\r\n `Ride ordering (eLife) — quote a fare, book it, poll status, modify it, and cancel.\r\n\r\nWorkflow (typical order):\r\n 1. quote Get fare quotes between two points → vehicle_classes[] each with a quote_id\r\n 2. book Book one vehicle_class using its quote_id → ride_id (write; needs --idempotency-key)\r\n 3. get Poll ride status by --order-id=<ride_id> until terminal (or use --watch for NDJSON)\r\n 4. cancel (optional) Cancel a ride by --order-id (write; may incur a fee)\r\n update (optional) Modify trip details and/or passenger of a booked ride\r\n (write; needs --idempotency-key; the fare may change)\r\n trip-status (optional) Status + driver location points of ONE leg of a multi-leg ride\r\n list-orders (standalone) List the developer's previous ride orders\r\n callback-* (standalone) Status-event forwarding to your own https endpoint:\r\n callback-set/-get (one ride), callback-default-set/-get (fallback for all\r\n rides), callback-deliveries / callback-replay (inspect and re-send)\r\n\r\nKey notes:\r\n • Coordinates are NOT geocoded by the backend — supply --pickup-lat/lng and --dropoff-lat/lng.\r\n book must repeat the SAME pickup/dropoff coordinates+names and pickup-time used in quote;\r\n the quote_id does NOT carry them forward.\r\n • quote_id from quote is opaque and provider-specific — pass it unchanged to book, never reuse\r\n it across services.\r\n • vehicle_class values are case-sensitive literals (Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury /\r\n Train) — pass back to book verbatim.\r\n • --pickup-time is UTC epoch seconds or the literal \"now\"; convert the user's local time to UTC.\r\n • All amounts are DECIMAL currency units (e.g. 42.50 = $42.50), never minor units (cents).\r\n • Billing mode is decided server-side: pay_per_call needs a PAID --payment-order-id (from\r\n payment-cli); monthly_settlement forbids it (settled against the developer's account).\r\n • Write verbs (book / cancel / update) require --idempotency-key; reuse the SAME key when\r\n retrying the same intent.\r\n • update changes ONLY the fields you pass. Trip-side and passenger-side changes are two separate\r\n upstream calls with no transaction: the response reports ride_updated / passenger_updated, and a\r\n partial application returns UPSTREAM_ERROR with data.partial_update — re-issue update for the\r\n failed side only.`,\r\n );\r\n registerQuoteCommand(rideCmd, deps);\r\n registerBookCommand(rideCmd, deps);\r\n registerRideCreateOrderCommand(rideCmd, deps);\r\n registerRidePayOrderCommand(rideCmd, deps);\r\n registerRideGetCommand(rideCmd, deps);\r\n registerCancelCommand(rideCmd, deps);\r\n registerRideUpdateCommand(rideCmd, deps);\r\n registerRideTripStatusCommand(rideCmd, deps);\r\n registerListOrdersCommand(rideCmd, deps);\r\n registerRideCallbackCommands(rideCmd, deps);\r\n\r\n // services command group (capability discovery via platform backend + local fallback).\r\n // These commands gate backend capabilities against the CLI's own command tree,\r\n // so they need the root `program` to introspect registered nouns/verbs, plus\r\n // the host-root discovery client.\r\n const servicesCmd = program.command('services').description('Merchant service discovery');\r\n registerServicesListCommand(servicesCmd, { discoveryClient, program });\r\n registerServiceGetCommand(servicesCmd, { discoveryClient, program });\r\n\r\n // orders command group (unified cross-provider order index, GET /orders).\r\n // Spans ride + hotel + flight (+ future providers) in one call. Prefer a\r\n // domain-specific command only when provider-specific columns are needed.\r\n const ordersCmd = program.command('orders').description(\r\n 'Unified cross-provider order index (spans ride + hotel + flight). Use list/get for generic \"my orders\" requests (use ride-elife/hotel-redaug/flight-flink commands once the business is known); pay-batch settles a batch of AWAITING_PAYMENT orders in one aggregate payment (trip checkout).',\r\n );\r\n registerOrdersListCommand(ordersCmd, deps);\r\n registerOrdersGetCommand(ordersCmd, deps);\r\n // 行程聚合支付:orders pay-batch —— `orders__aggregate__pay-batch` 逻辑工具名的物理落点\r\n // (供 trip-aggregate 的 pay-orders write verb 经 UniversalGateway 调用)。\r\n registerOrdersPayBatchCommand(ordersCmd, deps);\r\n // 查 pay-batch 结算进度(只读,不重发付款)。\r\n registerOrdersGetPaymentGroupCommand(ordersCmd, deps);\r\n\r\n // hotel-redaug command group (Redaug hotel booking) — 13 verbs\r\n const hotelCmd = program.command('hotel-redaug').description(\r\n `Hotel booking (Redaug) — international hotel search, quote, create-order, pay-order, cancel, and check-out.\r\n\r\nWorkflow (typical order):\r\n 1. find-destination Resolve a place name → coordinates (or destination_id via list-cities)\r\n 2. hotel-filters (optional) Get filter options for a location (star/brand/facility codes)\r\n 3. search Search hotels by coordinates OR destination_id, with date/guest/filter params\r\n 4. hotel-detail View hotel + rooms[] (area/floor/beds/photos). Call it for the chosen/\r\n shortlisted hotel BEFORE quote — quote's room_name alone has no detail,\r\n and the user should see real room info before picking a rate at step 5.\r\n 5. quote Get real-time room rates for a hotel + dates → product_token + price_items.\r\n Pair each rate with hotel-detail's rooms[] (match by room_name) before\r\n presenting options to the user.\r\n 6. create-order Create order using product_token from quote (lock inventory, no charge)\r\n 7. pay-order Settle the order by --order-id (path chosen server-side by billing_mode)\r\n 8. get Poll order status until CONFIRMED (or use --watch for NDJSON stream)\r\n 9. cancel Cancel an order (whole-order, within policy)\r\n 10. checkout Apply for partial check-out / out-of-policy cancellation (async)\r\n 11. get-checkout Poll checkout application status\r\n 12. list-orders List developer's hotel orders\r\n\r\nKey notes:\r\n • search has two location branches: --destination-id OR --lat/--lng (exactly one required)\r\n • hotel-detail's rooms[] is the actual room info (area/beds/photos) — quote's room_name is\r\n just a bare label; show both together before asking the user to pick a rate\r\n • create-order locks inventory without charging; order enters AWAITING_PAYMENT\r\n • pay-order settles the order by --order-id; the path is chosen server-side by\r\n billing_mode. For pay_per_call the user pays via EVO using the order_id\r\n as the merchantTransID first; use --watch to poll until PAID\r\n • All amounts are DECIMAL (e.g. 10.00 = ten yuan), never minor units (cents)\r\n • product_token from quote is opaque — pass it unchanged to create-order\r\n • price_items from quote must be copied verbatim as --price-items JSON array to create-order`,\r\n );\r\n registerHotelSearchCommand(hotelCmd, deps);\r\n registerHotelQuoteCommand(hotelCmd, deps);\r\n registerHotelCreateOrderCommand(hotelCmd, deps);\r\n registerHotelPayOrderCommand(hotelCmd, deps);\r\n registerHotelGetCommand(hotelCmd, deps);\r\n registerHotelCancelCommand(hotelCmd, deps);\r\n registerHotelCheckoutCommand(hotelCmd, deps);\r\n registerHotelGetCheckoutCommand(hotelCmd, deps);\r\n registerHotelListOrdersCommand(hotelCmd, deps);\r\n registerHotelFindDestinationCommand(hotelCmd, deps);\r\n registerHotelFiltersCommand(hotelCmd, deps);\r\n registerHotelListCitiesCommand(hotelCmd, deps);\r\n registerHotelDetailCommand(hotelCmd, deps);\r\n registerHotelSkillCommand(hotelCmd);\r\n\r\n // flight-flink command group (Flink flight booking) — 18 verbs\r\n const flightCmd = program.command('flight-flink').description(\r\n `Flight booking (Flink) — international flight search, price verification, two-step create-then-pay ticketing, plus change (rebooking) and refund.\r\n\r\nWorkflow (typical order):\r\n 1. find-airport Resolve a place name → IATA city/airport codes\r\n 2. search Search flights (one-way/round-trip/multi-city). journeys carries ALL legs;\r\n round-trip/multi-city: relay the chosen offer's next_journey_ids into\r\n --journey-id until is_final_leg is true\r\n 3. verify Verify the fare → authoritative product_token + price_changed flag\r\n 4. create-order Create the order using verify's product_token (locks the fare, no charge)\r\n 5. pay-order Settle by --order-no (triggers ticketing); order → PAID\r\n 6. get-order Poll by --order-no until TICKETED (or use --watch for NDJSON)\r\n cancel-order (optional) Cancel an un-ticketed order (+ refund)\r\n change-* (optional) change-search → change-apply → change-detail; confirm via pay-order, cancel via change-cancel\r\n refund-* (optional) refund-apply → refund-detail → refund-confirm (1=confirm, 2=cancel)\r\n list-orders List the developer's flight orders\r\n\r\nKey notes:\r\n • product_token from search/verify is opaque — pass it unchanged; verify's token supersedes search's\r\n • passengers is a JSON array; gender/id_type are STRINGS (\"1\"/\"2\"); child/infant need adult_passenger_name\r\n • Ticketing is asynchronous — never claim \"booked\" until get-order returns TICKETED\r\n • create-order and pay-order are separate steps; create-order does NOT charge\r\n • Write verbs require --idempotency-key; reuse the SAME key when retrying the same intent`,\r\n );\r\n registerFindAirportCommand(flightCmd, deps);\r\n registerListAirportsCommand(flightCmd, deps);\r\n registerListAirlinesCommand(flightCmd, deps);\r\n registerListNationalitiesCommand(flightCmd, deps);\r\n registerFlightSearchCommand(flightCmd, deps);\r\n registerMoreOffersCommand(flightCmd, deps);\r\n registerVerifyCommand(flightCmd, deps);\r\n registerFlightCreateOrderCommand(flightCmd, deps);\r\n registerFlightPayOrderCommand(flightCmd, deps);\r\n registerFlightGetOrderCommand(flightCmd, deps);\r\n registerFlightCancelOrderCommand(flightCmd, deps);\r\n registerFlightListOrdersCommand(flightCmd, deps);\r\n registerChangeSearchCommand(flightCmd, deps);\r\n registerChangeApplyCommand(flightCmd, deps);\r\n registerChangeDetailCommand(flightCmd, deps);\r\n registerChangeCancelCommand(flightCmd, deps);\r\n registerChangePayCommand(flightCmd, deps);\r\n registerRefundApplyCommand(flightCmd, deps);\r\n registerRefundDetailCommand(flightCmd, deps);\r\n registerRefundConfirmCommand(flightCmd, deps);\r\n registerFlightSkillCommand(flightCmd);\r\n\r\n // data-aisa command group (AIsa read-only information lookup) — 4 verbs\r\n const dataCmd = program.command('data-aisa').description(\r\n 'AIsa read-only information lookup (crypto, markets, web & news, SEO, social, prediction markets, research): ' +\r\n 'list-categories / search / describe / query. Pay-per-call READ-ONLY lookups — ' +\r\n 'it never places an order and never takes money.',\r\n );\r\n registerDataListCategoriesCommand(dataCmd, deps);\r\n registerDataSearchCommand(dataCmd, deps);\r\n registerDataDescribeCommand(dataCmd, deps);\r\n registerDataQueryCommand(dataCmd, deps);\r\n\r\n // Parse and execute\r\n await program.parseAsync(process.argv);\r\n}\r\n\r\n/**\r\n * Resolve the active output format for error reporting. Prefers the parsed\r\n * global `--format` flag (available on `programRef` once the program is\r\n * constructed; defaults to `json` for merchant-cli); if an error was thrown\r\n * before parsing, falls back to `resolveFormat(undefined)` (which consults\r\n * `AGENZO_FORMAT`, else `table`).\r\n */\r\nfunction resolveActiveFormat(): OutputFormat {\r\n const flag = programRef?.opts().format as string | undefined;\r\n return resolveFormat(flag);\r\n}\r\n\r\n/**\r\n * Top-level failure path. Writes the error envelope to stderr in the resolved\r\n * format and exits with the mapped code (1–5). stdout is left untouched so a\r\n * partial machine payload is never emitted on failure.\r\n *\r\n * - `json`: a single `{ error: { code, code_num, message, request_id?, upstream? } }` envelope (§8.2).\r\n * - `table`: `✗ [<code_num>] <message>`, plus a ` Order: <order_id>` line when the\r\n * error carries a recoverable order id (e.g. `PAYORDER_FAILED`, where the order\r\n * exists and only payment must be retried), plus a ` ↳ [<upstream.code>]\r\n * <upstream.message>` line when this failure originated from a third-party\r\n * upstream (e.g. Redaug/eLife) the platform calls out to.\r\n */\r\nfunction reportError(error: unknown): never {\r\n const envelope = toErrorEnvelope(error);\r\n const format = resolveActiveFormat();\r\n\r\n if (format === 'json') {\r\n console.error(JSON.stringify(envelope));\r\n } else {\r\n console.error(\r\n Formatter.status('error', `[${envelope.error.code_num}] ${envelope.error.message}`),\r\n );\r\n for (const line of errorDetailLines(envelope)) {\r\n console.error(line);\r\n }\r\n if (envelope.error.upstream) {\r\n console.error(` ↳ [${envelope.error.upstream.code}] ${envelope.error.upstream.message}`);\r\n }\r\n // Unknown (non-CliError) failures keep the --verbose raw-dump affordance.\r\n if (!(error instanceof CliError) && process.argv.includes('--verbose')) {\r\n console.error(error);\r\n }\r\n }\r\n\r\n // exitCodeFor owns the error-class → exit-code matrix, including\r\n // UpgradeRequiredError → 2 and UserCancelError → 5.\r\n process.exit(exitCodeFor(error));\r\n}\r\n\r\n// Ctrl+C / SIGINT maps to a user-cancel (exit 5) via the same envelope path.\r\nprocess.on('SIGINT', () => {\r\n reportError(new UserCancelError());\r\n});\r\n\r\n// Global error handler. Normal completion exits 0 naturally (the mapper is\r\n// never consulted on success).\r\nmain().catch(reportError);\r\n","/**\r\n * Unified outward-facing CLI error-code catalog (cli-design §8, single source of truth).\r\n *\r\n * Every outward code has both a string code (the preferred routing key) and a\r\n * numeric code (compact, convenient for log aggregation). The two map 1:1, bound\r\n * by {@link CODE_NUM}. String codes are grouped by domain prefix; numeric codes\r\n * are segmented by the same domains (§8.3).\r\n *\r\n * Note: `UPGRADE_REQUIRED` (CLI too old) and `CLIENT_ABORTED` (user-initiated\r\n * cancel) are non-business codes detected locally by the CLI. They are not part\r\n * of the §8.4 business dictionary and are allocated at the tail of the CLIENT range.\r\n */\r\nexport type ErrorCode =\r\n // AUTH_* (1000-1099)\r\n | 'AUTH_SESSION_EXPIRED'\r\n | 'AUTH_MAGIC_LINK_EXPIRED'\r\n | 'AUTH_INVITE_CODE_REQUIRED'\r\n | 'AUTH_INVITE_CODE_INVALID'\r\n // KEY_* (1100-1199)\r\n | 'KEY_INVALID'\r\n | 'KEY_SCOPE_DENIED'\r\n // PAYMENT_METHOD_* (1400-1499)\r\n | 'PAYMENT_METHOD_NOT_FOUND'\r\n | 'PAYMENT_METHOD_DISABLED'\r\n | 'INVALID_PAYMENT_METHOD'\r\n // RESOURCE_* (2000-2099)\r\n | 'RESOURCE_NOT_FOUND'\r\n | 'RESOURCE_CONFLICT'\r\n | 'RESOURCE_STATE_INVALID'\r\n // PARAM_* (2100-2199)\r\n | 'PARAM_INVALID'\r\n | 'PARAM_IDEMPOTENCY_KEY_REQUIRED'\r\n | 'PARAM_IDEMPOTENCY_KEY_CONFLICT'\r\n // BILLING_* (3000-3099)\r\n | 'BILLING_MODE_MISMATCH'\r\n // ACCOUNT_* (3100-3199)\r\n | 'ACCOUNT_NOT_FOUND'\r\n | 'ACCOUNT_SUSPENDED'\r\n | 'ACCOUNT_INSUFFICIENT_BALANCE'\r\n // PAYMENT_ORDER_* (3200-3299)\r\n | 'PAYMENT_ORDER_NOT_FOUND'\r\n | 'PAYMENT_ORDER_NOT_PAID'\r\n | 'PAYMENT_ORDER_MISMATCH'\r\n | 'PAYMENT_ORDER_ALREADY_CONSUMED'\r\n // TOKEN_* (4000-4099)\r\n | 'TOKEN_FEATURE_DISABLED'\r\n // SERVICE_* (4100-4199)\r\n | 'SERVICE_NOT_FOUND'\r\n // ride business codes (4200-4299)\r\n | 'VEHICLE_UNAVAILABLE'\r\n | 'QUOTE_EXPIRED'\r\n | 'BOOKING_FAILED'\r\n | 'CANCELLATION_NOT_ALLOWED'\r\n | 'PRICE_MISMATCH'\r\n | 'VEHICLE_CLASS_MISMATCH'\r\n | 'PAYMENT_METHOD_REQUIRED'\r\n | 'QUOTE_CACHE_UNAVAILABLE'\r\n | 'ARREARS_OUTSTANDING'\r\n | 'CONTACT_REQUIRED'\r\n | 'INVALID_PHONE'\r\n | 'SEAT_LIMIT_EXCEEDED'\r\n | 'RIDE_NOT_FOUND'\r\n // hotel business codes (4300-4399)\r\n | 'NO_AVAILABILITY'\r\n | 'PRICE_CHANGED'\r\n | 'NAME_FORMAT_INVALID'\r\n | 'HOTEL_ORDER_NOT_FOUND'\r\n | 'ALREADY_CANCELLED'\r\n | 'CHECKOUT_NOT_ALLOWED'\r\n | 'CHECKOUT_TASK_NOT_FOUND'\r\n | 'PAY_PER_CALL_NOT_AVAILABLE'\r\n | 'HOTEL_NOT_FOUND'\r\n | 'BOOKING_RESTRICTED'\r\n | 'PAYORDER_FAILED'\r\n | 'PAYORDER_FAILED_AFTER_PAYMENT'\r\n // flight business codes (4400-4499)\r\n | 'OFFER_UNAVAILABLE'\r\n // RATE_* (5000-5099)\r\n | 'RATE_LIMITED'\r\n // UPSTREAM_* (5100-5199)\r\n | 'UPSTREAM_ERROR'\r\n // INTERNAL_* (5200-5299)\r\n | 'INTERNAL_ERROR'\r\n // NOT_IMPLEMENTED (5300)\r\n | 'NOT_IMPLEMENTED'\r\n // CLIENT_* (9000-9099) — produced locally by the CLI\r\n | 'CLIENT_NOT_SIGNED_IN'\r\n | 'CLIENT_LOGIN_TIMEOUT'\r\n | 'CLIENT_ORG_NOT_LOCAL'\r\n | 'CLIENT_ORG_WRONG_ENV'\r\n | 'CLIENT_NO_PAYMENT_METHOD'\r\n | 'CLIENT_CARD_NOT_MATCHED'\r\n | 'CLIENT_ABORTED'\r\n // Non-business code (detected locally by the CLI)\r\n | 'UPGRADE_REQUIRED';\r\n\r\n/**\r\n * String code → numeric code (§8.4). Each outward code's numeric value is\r\n * uniquely bound by this table; once published it is append-only (never changed).\r\n */\r\nexport const CODE_NUM: Record<ErrorCode, number> = {\r\n AUTH_SESSION_EXPIRED: 1001,\r\n AUTH_MAGIC_LINK_EXPIRED: 1002,\r\n AUTH_INVITE_CODE_REQUIRED: 1003,\r\n AUTH_INVITE_CODE_INVALID: 1004,\r\n KEY_INVALID: 1101,\r\n KEY_SCOPE_DENIED: 1102,\r\n PAYMENT_METHOD_NOT_FOUND: 1401,\r\n PAYMENT_METHOD_DISABLED: 1402,\r\n INVALID_PAYMENT_METHOD: 1403,\r\n RESOURCE_NOT_FOUND: 2001,\r\n RESOURCE_CONFLICT: 2002,\r\n RESOURCE_STATE_INVALID: 2003,\r\n PARAM_INVALID: 2101,\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 2102,\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 2103,\r\n BILLING_MODE_MISMATCH: 3001,\r\n ACCOUNT_NOT_FOUND: 3101,\r\n ACCOUNT_SUSPENDED: 3102,\r\n ACCOUNT_INSUFFICIENT_BALANCE: 3103,\r\n PAYMENT_ORDER_NOT_FOUND: 3201,\r\n PAYMENT_ORDER_NOT_PAID: 3202,\r\n PAYMENT_ORDER_MISMATCH: 3203,\r\n PAYMENT_ORDER_ALREADY_CONSUMED: 3204,\r\n TOKEN_FEATURE_DISABLED: 4001,\r\n SERVICE_NOT_FOUND: 4101,\r\n VEHICLE_UNAVAILABLE: 4201,\r\n QUOTE_EXPIRED: 4202,\r\n BOOKING_FAILED: 4203,\r\n CANCELLATION_NOT_ALLOWED: 4204,\r\n PRICE_MISMATCH: 4205,\r\n VEHICLE_CLASS_MISMATCH: 4206,\r\n PAYMENT_METHOD_REQUIRED: 4207,\r\n QUOTE_CACHE_UNAVAILABLE: 4208,\r\n ARREARS_OUTSTANDING: 4209,\r\n CONTACT_REQUIRED: 4210,\r\n INVALID_PHONE: 4211,\r\n SEAT_LIMIT_EXCEEDED: 4213,\r\n RIDE_NOT_FOUND: 4212,\r\n NO_AVAILABILITY: 4301,\r\n PRICE_CHANGED: 4302,\r\n NAME_FORMAT_INVALID: 4303,\r\n HOTEL_ORDER_NOT_FOUND: 4304,\r\n ALREADY_CANCELLED: 4305,\r\n CHECKOUT_NOT_ALLOWED: 4306,\r\n CHECKOUT_TASK_NOT_FOUND: 4307,\r\n PAY_PER_CALL_NOT_AVAILABLE: 4308,\r\n HOTEL_NOT_FOUND: 4309,\r\n BOOKING_RESTRICTED: 4310,\r\n PAYORDER_FAILED: 4311,\r\n PAYORDER_FAILED_AFTER_PAYMENT: 4312,\r\n OFFER_UNAVAILABLE: 4401,\r\n RATE_LIMITED: 5001,\r\n UPSTREAM_ERROR: 5101,\r\n INTERNAL_ERROR: 5201,\r\n NOT_IMPLEMENTED: 5300,\r\n CLIENT_NOT_SIGNED_IN: 9001,\r\n CLIENT_LOGIN_TIMEOUT: 9002,\r\n CLIENT_ORG_NOT_LOCAL: 9003,\r\n CLIENT_ORG_WRONG_ENV: 9004,\r\n CLIENT_NO_PAYMENT_METHOD: 9005,\r\n CLIENT_CARD_NOT_MATCHED: 9006,\r\n CLIENT_ABORTED: 9007,\r\n UPGRADE_REQUIRED: 9008,\r\n};\r\n\r\n/** Look up the numeric code for a string error code. */\r\nexport function codeNum(code: ErrorCode): number {\r\n return CODE_NUM[code];\r\n}\r\n","import { type ErrorCode, CODE_NUM, codeNum } from './error-catalog.js';\r\nimport type { ApiError, UpstreamError } from '../api-client/client.js';\r\n\r\n/** Base class for all CLI errors. Carries the CLI-facing error code (§8.4). */\r\nexport class CliError extends Error {\r\n constructor(\r\n public readonly code: ErrorCode,\r\n message: string,\r\n public readonly statusCode?: number,\r\n public readonly requestId?: string,\r\n public readonly upstream?: UpstreamError,\r\n /**\r\n * The backend's own raw message for this error (e.g. a Pydantic\r\n * validation detail such as \"child_seat_count: must be between 0 and 5\",\r\n * or a provider adapter's `user_hint`). Kept SEPARATE from `message`\r\n * (the stable, catalog-owned text for `code`) so callers always get a\r\n * predictable top-level message while still being able to see exactly\r\n * what the backend said. Surfaced in the envelope as `backend_message`\r\n * when present and different from the stable message.\r\n */\r\n public readonly backendMessage?: string,\r\n /** Safe structured error data that callers may use for recovery. */\r\n public readonly data?: Record<string, unknown>,\r\n ) {\r\n super(message);\r\n this.name = 'CliError';\r\n }\r\n\r\n /**\r\n * Map a backend ApiError to a CLI-facing code (§8.5 transitional mapping).\r\n * Backend numeric codes / HTTP status are translated to §8.4 string codes.\r\n * The top-level `message` is always the stable, catalog-owned text for the\r\n * resolved code (§8.1 principle 4 — never let raw backend text become the\r\n * primary/stable message). The backend's own message is NOT discarded,\r\n * though: it is preserved on `backendMessage` and surfaced in the envelope\r\n * as `backend_message` so the caller can see the real reason (e.g. which\r\n * field failed validation) alongside the stable code/message.\r\n *\r\n * The optional `opts.auth` selects the auth semantics for the 401 mapping:\r\n * - `'bearer'` (default, admin-cli Bearer Token): 401 → `AUTH_SESSION_EXPIRED`.\r\n * - `'api-key'` (token-cli `X-Api-Key`): 401 → `KEY_INVALID`.\r\n * 403 maps to `KEY_SCOPE_DENIED` under both auth modes. Omitting `opts`\r\n * preserves the original Bearer behavior exactly (§8.5 / requirement 6.4).\r\n *\r\n * Domain string-code routing (D3 / requirement 5.4): when the backend\r\n * supplies a string `error.code` in the v3 envelope that is a known §8 code\r\n * (present in {@link CODE_NUM}), it is used verbatim as the CLI-facing code\r\n * so ride/merchant-specific codes (`QUOTE_EXPIRED`, `VEHICLE_UNAVAILABLE`,\r\n * `BILLING_MODE_MISMATCH`, `PAYMENT_ORDER_*`, …) survive intact. Otherwise —\r\n * including when no string code is provided, as is the case for admin/token\r\n * today — mapping falls back to the HTTP-status table below, leaving the\r\n * existing Bearer/api-key behavior unchanged.\r\n */\r\n static fromApi(error: ApiError, opts?: { auth?: 'bearer' | 'api-key' }): CliError {\r\n // D3: prefer the backend's string code when it is a known §8 catalog code.\r\n if (error.code && isKnownErrorCode(error.code)) {\r\n return new CliError(\r\n error.code,\r\n STABLE_MESSAGE[error.code] ?? 'Request failed. Please check your input and retry.',\r\n error.statusCode,\r\n error.requestId,\r\n error.upstream,\r\n error.errorMessage,\r\n error.data,\r\n );\r\n }\r\n\r\n const status = error.statusCode;\r\n let code: ErrorCode;\r\n\r\n if (status === 401) code = opts?.auth === 'api-key' ? 'KEY_INVALID' : 'AUTH_SESSION_EXPIRED';\r\n else if (status === 403) code = 'KEY_SCOPE_DENIED';\r\n else if (status === 404) code = 'RESOURCE_NOT_FOUND';\r\n else if (status === 409) code = 'RESOURCE_CONFLICT';\r\n else if (status === 429) code = 'RATE_LIMITED';\r\n else if (status >= 500) code = 'INTERNAL_ERROR';\r\n else code = 'PARAM_INVALID'; // other 4xx (incl. 400/422)\r\n\r\n return new CliError(\r\n code,\r\n STABLE_MESSAGE[code] ?? 'Request failed. Please check your input and retry.',\r\n status,\r\n error.requestId,\r\n error.upstream,\r\n error.errorMessage,\r\n error.data,\r\n );\r\n }\r\n}\r\n\r\n/** Network / connectivity failure → UPSTREAM_ERROR. Never leak the internal URL/path. */\r\nexport class NetworkError extends CliError {\r\n constructor(_url: string, timeout?: number, _cause?: Error) {\r\n super(\r\n 'UPSTREAM_ERROR',\r\n timeout\r\n ? 'The request timed out. The service may be temporarily unavailable — please retry.'\r\n : 'Connection failed. The service may be temporarily unavailable — please retry.',\r\n );\r\n }\r\n}\r\n\r\n/** Auth / session failures. Code chosen by message intent (§8.4 AUTH_* / CLIENT_*). */\r\nexport class AuthError extends CliError {\r\n constructor(message: string, public readonly suggestion: string) {\r\n const m = message.toLowerCase();\r\n const code: ErrorCode = m.includes('not signed in')\r\n ? 'CLIENT_NOT_SIGNED_IN'\r\n : m.includes('time')\r\n ? 'CLIENT_LOGIN_TIMEOUT'\r\n : m.includes('magic link')\r\n ? 'AUTH_MAGIC_LINK_EXPIRED'\r\n : 'AUTH_SESSION_EXPIRED';\r\n super(code, message || 'Unknown error');\r\n }\r\n}\r\n\r\nexport class ConfigError extends CliError {\r\n constructor(message: string, public readonly filePath: string) {\r\n super('INTERNAL_ERROR', message || 'Unknown error');\r\n }\r\n}\r\n\r\nexport class ValidationError extends CliError {\r\n constructor(message: string) {\r\n super('PARAM_INVALID', message || 'Unknown error');\r\n }\r\n}\r\n\r\nexport class IdempotencyKeyRequiredError extends CliError {\r\n constructor(commandPath: string) {\r\n super(\r\n 'PARAM_IDEMPOTENCY_KEY_REQUIRED',\r\n `\\`${commandPath}\\` requires --idempotency-key <key>. Supply a unique key so the write can be safely retried.`,\r\n );\r\n }\r\n}\r\n\r\nexport class UpgradeRequiredError extends CliError {\r\n constructor(currentVersion: string, minVersion: string, upgradeCommand: string) {\r\n super(\r\n 'UPGRADE_REQUIRED',\r\n `agenzo-admin-cli ${currentVersion} is out of date — the server requires ${minVersion} or newer. To upgrade, run: ${upgradeCommand}`,\r\n );\r\n }\r\n}\r\n\r\nexport class UserCancelError extends CliError {\r\n constructor(message = 'Operation cancelled by user') {\r\n super('CLIENT_ABORTED', message || 'Unknown error');\r\n }\r\n}\r\n\r\n/** Type guard: is `value` a known §8 string error code (present in CODE_NUM)? */\r\nfunction isKnownErrorCode(value: string): value is ErrorCode {\r\n return Object.prototype.hasOwnProperty.call(CODE_NUM, value);\r\n}\r\n\r\n/**\r\n * Stable, CLI-owned message per code used when mapping opaque backend errors\r\n * (§8.1 principle 4: never surface raw backend detail).\r\n */\r\nconst STABLE_MESSAGE: Partial<Record<ErrorCode, string>> = {\r\n AUTH_SESSION_EXPIRED: 'Your session has expired. Please run `agenzo-admin-cli auth login` again.',\r\n AUTH_MAGIC_LINK_EXPIRED: 'Verification link is invalid or has expired. Please request a new one.',\r\n AUTH_INVITE_CODE_REQUIRED: 'An invitation code is required to register.',\r\n AUTH_INVITE_CODE_INVALID: 'The invitation code is invalid.',\r\n KEY_INVALID: 'The API key is invalid or has been revoked. Please check your --api-key and retry.',\r\n KEY_SCOPE_DENIED: 'This API key does not have the required scope for this command.',\r\n PAYMENT_METHOD_NOT_FOUND: 'Payment method not found.',\r\n PAYMENT_METHOD_DISABLED: 'This payment method has been disabled.',\r\n INVALID_PAYMENT_METHOD: 'The payment method is not available for this operation.',\r\n RESOURCE_NOT_FOUND: 'The resource was not found or does not belong to the current organization.',\r\n RESOURCE_CONFLICT: 'A resource with the same unique value already exists.',\r\n RESOURCE_STATE_INVALID: 'The resource is in a state that does not permit this operation.',\r\n RATE_LIMITED: 'Too many requests. Please back off and retry.',\r\n UPSTREAM_ERROR: 'A third-party service is temporarily unavailable. Please try again later.',\r\n INTERNAL_ERROR: 'Something went wrong on the server. Please retry and note the request_id.',\r\n PARAM_INVALID: 'One or more parameters are invalid. Please check your input and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'A request with this idempotency key was already processed with different parameters.',\r\n TOKEN_FEATURE_DISABLED: 'VCN creation is not supported yet. Coming soon.',\r\n BILLING_MODE_MISMATCH: 'The billing mode does not match this operation. Please verify your account billing configuration.',\r\n ACCOUNT_NOT_FOUND: 'The settlement account was not found.',\r\n ACCOUNT_SUSPENDED: 'The settlement account is suspended. Please contact support.',\r\n ACCOUNT_INSUFFICIENT_BALANCE: 'The settlement account has insufficient balance for this operation.',\r\n PAYMENT_ORDER_NOT_FOUND: 'The payment order was not found.',\r\n PAYMENT_ORDER_NOT_PAID: 'The payment order has not been paid. Please complete payment and retry.',\r\n PAYMENT_ORDER_MISMATCH: 'The payment order does not match this order. Please check the --payment-order-id.',\r\n PAYMENT_ORDER_ALREADY_CONSUMED: 'The payment order has already been consumed by another booking.',\r\n SERVICE_NOT_FOUND: 'The requested service was not found.',\r\n VEHICLE_UNAVAILABLE: 'No vehicle is available for the requested trip. Please try a different time or class.',\r\n QUOTE_EXPIRED: 'The quote has expired. Please request a new quote and retry.',\r\n BOOKING_FAILED: 'The booking could not be completed. Please retry.',\r\n PRICE_MISMATCH: 'The price does not match the quote. Re-quote and use the exact amount from the quote response.',\r\n VEHICLE_CLASS_MISMATCH: 'The vehicle class does not match the quote. Use the vehicle class from the quote response.',\r\n PAYMENT_METHOD_REQUIRED: 'Pay-per-call billing requires an active payment method. Please add a card first.',\r\n QUOTE_CACHE_UNAVAILABLE: 'Quote cache is temporarily unavailable. Please request a new quote and retry.',\r\n ARREARS_OUTSTANDING: 'You have outstanding arrears. Please settle your balance before booking a new ride.',\r\n CONTACT_REQUIRED: 'Passenger contact information is required. Please provide a passenger name and phone number.',\r\n INVALID_PHONE: 'The passenger phone number is not valid. Please provide a valid international number.',\r\n SEAT_LIMIT_EXCEEDED: 'The number of child/infant/toddler seats exceeds the vehicle capacity. Reduce seats or choose a larger vehicle.',\r\n RIDE_NOT_FOUND: 'The ride order was not found or does not belong to you.',\r\n CANCELLATION_NOT_ALLOWED: 'This order cannot be cancelled in its current state.',\r\n NO_AVAILABILITY: 'No rooms available for the selected hotel and dates.',\r\n PRICE_CHANGED: 'The price changed since the quote. Re-quote and confirm.',\r\n NAME_FORMAT_INVALID: 'The guest name format is not accepted; use Latin letters.',\r\n HOTEL_ORDER_NOT_FOUND: 'Hotel order not found.',\r\n ALREADY_CANCELLED: 'This hotel order is already cancelled.',\r\n CHECKOUT_NOT_ALLOWED: 'A partial check-out is not allowed in the current state.',\r\n CHECKOUT_TASK_NOT_FOUND: 'Check-out application not found.',\r\n PAY_PER_CALL_NOT_AVAILABLE: 'Pay-per-call billing is not available; use monthly_settlement.',\r\n HOTEL_NOT_FOUND: 'This hotel is no longer available from the supplier.',\r\n BOOKING_RESTRICTED:\r\n \"This room has a booking condition that your request doesn't meet. Please check the room's booking rules and adjust your request.\",\r\n PAYORDER_FAILED: 'The hotel order was created, but payment failed. Retry payment for the existing order.',\r\n PAYORDER_FAILED_AFTER_PAYMENT: 'Payment was received, but hotel confirmation failed. Contact support for reconciliation.',\r\n OFFER_UNAVAILABLE: 'The selected flight is no longer available. Please search again and pick another flight.',\r\n NOT_IMPLEMENTED: 'This operation is not implemented yet.',\r\n};\r\n\r\n/**\r\n * §8.2 error envelope: `{ error: { code, code_num, message, request_id?, upstream?, backend_message? } }`.\r\n *\r\n * `message` is always the stable, catalog-owned text for `code` — safe to\r\n * match on and never changes shape. `backend_message` (when present) is the\r\n * backend's own raw text for this specific failure (e.g. which field failed\r\n * validation, or a provider's real rejection reason) — diagnostic, not a\r\n * stable contract, but no longer discarded.\r\n */\r\nexport interface ErrorEnvelope {\r\n error: {\r\n code: ErrorCode;\r\n code_num: number;\r\n message: string;\r\n request_id?: string;\r\n upstream?: UpstreamError;\r\n backend_message?: string;\r\n data?: Record<string, unknown>;\r\n };\r\n}\r\n\r\n/**\r\n * Recovery detail lines for the human-readable (`table`) error output.\r\n *\r\n * `json` callers read `error.data` straight off the envelope, but the table\r\n * format used to print only `message` — so a `PAYORDER_FAILED` telling the\r\n * user to \"retry payment for the existing order\" left them without the order\r\n * id to retry against. Returns one ` Order: <order_id>` line when the error\r\n * carries a usable order id, and nothing otherwise.\r\n */\r\nexport function errorDetailLines(envelope: ErrorEnvelope): string[] {\r\n const orderId = envelope.error.data?.order_id;\r\n if (typeof orderId !== 'string' || orderId.length === 0) return [];\r\n return [` Order: ${orderId}`];\r\n}\r\n\r\nexport function toErrorEnvelope(error: unknown): ErrorEnvelope {\r\n if (error instanceof CliError) {\r\n const stableMessage = error.message || 'Unknown error';\r\n // Only surface backend_message when it adds information beyond the\r\n // stable message (avoid noisy duplication when they already match).\r\n const backendMessage =\r\n error.backendMessage && error.backendMessage !== stableMessage\r\n ? error.backendMessage\r\n : undefined;\r\n return {\r\n error: {\r\n code: error.code,\r\n code_num: codeNum(error.code),\r\n message: stableMessage,\r\n ...(error.requestId ? { request_id: error.requestId } : {}),\r\n ...(error.upstream ? { upstream: error.upstream } : {}),\r\n ...(backendMessage ? { backend_message: backendMessage } : {}),\r\n ...(error.data ? { data: error.data } : {}),\r\n },\r\n };\r\n }\r\n\r\n const message =\r\n error instanceof Error\r\n ? error.message\r\n : typeof error === 'string'\r\n ? error\r\n : 'Unexpected error';\r\n return {\r\n error: {\r\n code: 'INTERNAL_ERROR',\r\n code_num: codeNum('INTERNAL_ERROR'),\r\n message: message || 'Unknown error',\r\n },\r\n };\r\n}\r\n","/**\r\n * CLI version + min-version comparator.\r\n *\r\n * The CLI's current version is read from `package.json` at runtime. This is\r\n * the single source of truth — bumping `package.json` automatically updates\r\n * what the CLI reports and what it compares against the server-advertised\r\n * minimum (`X-CLI-Min-Version` response header, driven by\r\n * `AGENT_PAY_CLI_MIN_VERSION` on the server).\r\n *\r\n * Only numeric major.minor.patch segments are compared; pre-release and build\r\n * metadata suffixes are stripped. This matches our versioning scheme and\r\n * avoids pulling in `semver` for a single `<` check.\r\n */\r\n\r\nimport { readFileSync } from 'node:fs';\r\nimport { dirname, join } from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\n\r\n/** Command the user should run to pick up the latest CLI. */\r\nexport const UPGRADE_COMMAND = 'npm install -g agenzo-admin-cli@latest';\r\n\r\n/**\r\n * Hard-coded fallback used only when `package.json` cannot be read at runtime\r\n * (unusual packaging/bundling edge cases). Keep this in sync with\r\n * `package.json`'s `version` on every release so the reported version and\r\n * the User-Agent stay accurate even in the degraded path.\r\n */\r\nexport const FALLBACK_VERSION = '0.1.1';\r\n\r\nlet cachedVersion: string | null = null;\r\n\r\nexport function getCurrentVersion(): string {\r\n if (cachedVersion !== null) return cachedVersion;\r\n // Walk up from the compiled file (dist/index.js) or source layout to find\r\n // package.json. Both `dist/..` and `src/utils/../..` resolve to the project\r\n // root, which is where package.json lives in a published npm install.\r\n const here = dirname(fileURLToPath(import.meta.url));\r\n const candidates = [\r\n join(here, '..', 'package.json'), // dist/ → project root\r\n join(here, '..', '..', 'package.json'), // src/utils/ → project root\r\n ];\r\n for (const p of candidates) {\r\n try {\r\n const pkg = JSON.parse(readFileSync(p, 'utf-8')) as { version?: string };\r\n if (typeof pkg.version === 'string') {\r\n cachedVersion = pkg.version;\r\n return cachedVersion;\r\n }\r\n } catch {\r\n // try next candidate\r\n }\r\n }\r\n // Degrade gracefully instead of crashing the CLI: if we can't locate\r\n // package.json at runtime, report the hard-coded fallback. The User-Agent\r\n // and any min-version comparison will still behave sensibly. We write a\r\n // one-line warning to stderr so packaging regressions remain visible.\r\n cachedVersion = FALLBACK_VERSION;\r\n // eslint-disable-next-line no-console\r\n console.warn(\r\n `[agenzo-admin-cli] package.json not found; using fallback version ${FALLBACK_VERSION}`,\r\n );\r\n return cachedVersion;\r\n}\r\n\r\n/**\r\n * Returns negative / zero / positive like `Array.sort`, comparing `a` against `b`.\r\n * Non-numeric segments and suffixes are treated as zero.\r\n */\r\nexport function compareVersions(a: string, b: string): number {\r\n const parse = (v: string): [number, number, number] => {\r\n const clean = v.trim().replace(/^v/, '').split(/[-+]/)[0];\r\n const parts = clean.split('.');\r\n return [\r\n parseInt(parts[0] ?? '0', 10) || 0,\r\n parseInt(parts[1] ?? '0', 10) || 0,\r\n parseInt(parts[2] ?? '0', 10) || 0,\r\n ];\r\n };\r\n const [a1, a2, a3] = parse(a);\r\n const [b1, b2, b3] = parse(b);\r\n if (a1 !== b1) return a1 - b1;\r\n if (a2 !== b2) return a2 - b2;\r\n return a3 - b3;\r\n}\r\n\r\nexport function isBelow(current: string, minimum: string): boolean {\r\n return compareVersions(current, minimum) < 0;\r\n}\r\n","import { NetworkError, UpgradeRequiredError } from '../errors/errors.js';\r\nimport { getCurrentVersion, isBelow, UPGRADE_COMMAND } from '../version/version.js';\r\n\r\n/**\r\n * W3C Trace Context `traceparent` 格式:`<version>-<trace-id>-<parent-id>-<flags>`。\r\n * 全零 trace-id 按规范无效,由下游解析时一并拒绝。\r\n */\r\nconst TRACEPARENT_PATTERN = /^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$/;\r\n\r\n/**\r\n * W3C `baggage` 里的业务旅程关联键 `flow_id`,以及它的合法字符集。\r\n *\r\n * `flow_id` 是「用户的一次任务」的关联键:一笔订单会横跨十几个 trace(`trace_id` 的\r\n * 粒度是一个对话轮次)和两个 A2A session,trace_id 串不起整条链路。本进程只做转发。\r\n *\r\n * 形状与 py-commons 的 `_FLOW_ID_RE` 保持一致:`flw_` 前缀 + 8~60 个 `[A-Za-z0-9_-]`。\r\n * `flw_` 前缀与仓里业务 ID 的既有约定同款(`hho_` / `ffo_` / `rio_` / `ptk_`),让这个值\r\n * 在日志里一眼可辨;前缀是强制的,等于多一道来源校验。字符集刻意比 W3C 允许的范围窄\r\n * 得多:该值来自环境变量、会被转成请求头并进入下游日志,宽松接受等于把日志注入与头部\r\n * 膨胀的风险一起转发下去。校验不过就不发,和 TRACEPARENT 同样处理。\r\n *\r\n * 两处正则必须同步改——这是跨语言的同一条契约,py-commons 侧收紧而这里没跟上,会变成\r\n * 「CLI 发出去的头被下游拒掉」这种只在集成时才暴露的错位。\r\n */\r\nconst FLOW_ID_BAGGAGE_KEY = 'agenzo.flow_id';\r\nconst FLOW_ID_PATTERN = /^flw_[A-Za-z0-9_-]{8,60}$/;\r\n\r\n/**\r\n * HTTP 超时默认值(毫秒)。可被构造参数或 AGENZO_CLI_HTTP_TIMEOUT_MS 覆盖。\r\n *\r\n * 这个值是跨服务超时阶梯的一层,不能单独调:\r\n * App 120s > orchestrator 90s > **本项 70s** > provider 45s > ledger 5s\r\n * 每层都要比下一层留出余量,好让下游的结构化错误有机会回传上来;两层取同值会导致\r\n * 上游在下游写出错误原因之前就放弃。完整依据见 platform 仓\r\n * docs/00-平台设计文档/01-跨仓文档/16-信任边界与超时预算设计.md。\r\n */\r\nexport const DEFAULT_HTTP_TIMEOUT_MS = 70000;\r\n\r\n/**\r\n * 从环境变量读 HTTP 超时;缺失或非法(非数字、<=0)时返回 null 交由调用方回落默认值。\r\n *\r\n * CLI 通常是被 orchestrator spawn 的子进程,环境变量是最自然的注入口——与\r\n * TRACEPARENT 走同一条路。这也是递减 deadline 的前置:上游要能按剩余预算\r\n * 压缩本跳超时,就必须有地方把值传进来。\r\n */\r\nexport function httpTimeoutFromEnv(\r\n env: Record<string, string | undefined> = process.env,\r\n): number | null {\r\n const raw = env.AGENZO_CLI_HTTP_TIMEOUT_MS;\r\n if (raw === undefined || raw.trim() === '') return null;\r\n const parsed = Number(raw);\r\n if (!Number.isFinite(parsed) || parsed <= 0) return null;\r\n return parsed;\r\n}\r\n\r\n/** 递减 deadline 的 HTTP 头名(剩余毫秒)。与 py-commons 的 DEADLINE_HEADER 对齐。 */\r\nexport const DEADLINE_HEADER = 'x-deadline-ms';\r\n\r\n/** W3C Baggage 的 HTTP 头名。与 py-commons 的 BAGGAGE_HEADER 对齐。 */\r\nexport const BAGGAGE_HEADER = 'baggage';\r\n\r\n/**\r\n * 从环境变量读上游给的 `flow_id` 并拼成 `baggage` 头值;缺失或不合规时返回 null。\r\n *\r\n * orchestrator spawn 本进程时经 `BAGGAGE` 注入,与 TRACEPARENT / DEADLINE_MS 同一机制。\r\n * 接受的是完整 baggage 头值(可能含其他成员),本函数只挑出 `agenzo.flow_id` 这一个成员\r\n * **重新拼**,不原样透传整串:入站 baggage 可达 8192 字节且来自不受信上游,无条件转发\r\n * 等于让外部往内部调用链里塞任意键值。\r\n */\r\nexport function baggageFromEnv(\r\n env: Record<string, string | undefined> = process.env,\r\n): string | null {\r\n const raw = env.BAGGAGE;\r\n if (raw === undefined || raw.trim() === '') return null;\r\n for (const member of raw.split(',')) {\r\n // `;` 之后是成员属性,与值无关。\r\n const pair = member.split(';', 1)[0] ?? '';\r\n const eq = pair.indexOf('=');\r\n if (eq < 0) continue;\r\n if (pair.slice(0, eq).trim() !== FLOW_ID_BAGGAGE_KEY) continue;\r\n let value = pair.slice(eq + 1).trim();\r\n try {\r\n value = decodeURIComponent(value);\r\n } catch {\r\n // 畸形百分号编码视同缺失,不把脏值发给下游。\r\n return null;\r\n }\r\n return FLOW_ID_PATTERN.test(value)\r\n ? `${FLOW_ID_BAGGAGE_KEY}=${encodeURIComponent(value)}`\r\n : null;\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * 出站前为回程预留的毫秒数:下游返回后本进程还要解析 JSON、渲染输出、写回 stdout。\r\n * 与 py-commons 的 DEFAULT_RESERVE_MS 取同值,六仓对\"预留多少\"保持一致。\r\n */\r\nexport const DEADLINE_RESERVE_MS = 200;\r\n\r\n/**\r\n * 从环境变量读上游给的剩余预算(毫秒);缺失或非法时返回 null。\r\n *\r\n * orchestrator spawn 本进程时经 DEADLINE_MS 注入(见其 backend_gateway/universal.py),\r\n * 与 TRACEPARENT 同一机制。不接受浮点串——协议规定整数毫秒,容忍浮点会让不同语言的\r\n * 实现出现取整分歧。\r\n */\r\nexport function deadlineFromEnv(\r\n env: Record<string, string | undefined> = process.env,\r\n): number | null {\r\n const raw = env.DEADLINE_MS;\r\n if (raw === undefined || raw.trim() === '') return null;\r\n if (!/^\\d+$/.test(raw.trim())) return null;\r\n const parsed = Number(raw);\r\n if (!Number.isFinite(parsed) || parsed <= 0) return null;\r\n return parsed;\r\n}\r\n\r\nexport interface ApiClientConfig {\r\n baseUrl: string;\r\n /**\r\n * HTTP 超时(毫秒)。优先级:本字段 > AGENZO_CLI_HTTP_TIMEOUT_MS > 60000。\r\n *\r\n * 显式传值优先于环境变量,这样调用方能对单个 client 做例外(如长轮询),\r\n * 不受进程级设置牵连。\r\n */\r\n timeout?: number;\r\n}\r\n\r\nexport interface ApiResponse<T> {\r\n success: true;\r\n data: T;\r\n /** Server-provided message from the unified response envelope. */\r\n message?: string;\r\n}\r\n\r\n/** Upstream error details (diagnostic only, not stable). */\r\nexport interface UpstreamError {\r\n /** Upstream-specific error code (stringified). */\r\n code: string;\r\n /** Upstream-specific error message. */\r\n message: string;\r\n}\r\n\r\nexport interface ApiError {\r\n success: false;\r\n errorCode: number;\r\n errorMessage: string;\r\n statusCode: number;\r\n /**\r\n * Raw string code from the v3 response envelope (`{ code, message, data }`),\r\n * surfaced verbatim so {@link CliError.fromApi} can route domain-specific\r\n * §8 codes (e.g. `QUOTE_EXPIRED`, `VEHICLE_UNAVAILABLE`) by string code\r\n * before falling back to HTTP-status mapping. Absent when the backend does\r\n * not provide a string code (e.g. non-JSON error responses).\r\n */\r\n code?: string;\r\n /** Server-provided request correlation id, surfaced in the error envelope. */\r\n requestId?: string;\r\n /** Safe structured error data, including recoverable order identifiers. */\r\n data?: Record<string, unknown>;\r\n /** Upstream error details for diagnostic transparency. */\r\n upstream?: UpstreamError;\r\n}\r\n\r\nexport type ApiResult<T> = ApiResponse<T> | ApiError;\r\n\r\nexport type AuthMode =\r\n | { type: 'bearer'; token: string }\r\n | { type: 'api-key'; key: string }\r\n | { type: 'none' };\r\n\r\nexport class ApiClient {\r\n private readonly baseUrl: string;\r\n private readonly timeout: number;\r\n /**\r\n * Correlation id for this CLI invocation. Generated once per `ApiClient`\r\n * instance (i.e. once per command execution — each `apps/*` entrypoint\r\n * constructs exactly one `ApiClient` per process run) and sent as\r\n * `X-Request-Id` on every request this client makes. The backend's\r\n * `RequestIdMiddleware` adopts a client-supplied `X-Request-Id` verbatim as\r\n * both `trace_id` and `request_id` (only generating its own when the header\r\n * is absent), so every HTTP call belonging to one CLI operation — including\r\n * multi-step flows like `payment-methods add`'s create + poll + get — shares\r\n * a single trace_id server-side and can be followed as one chain in logs.\r\n */\r\n private readonly requestId: string;\r\n /**\r\n * 上游给的剩余预算(毫秒),来自 `DEADLINE_MS`;未注入时为 null。\r\n *\r\n * 进程启动时读一次而不是每请求读:一次 CLI 调用就是链路上的一跳,预算属于这一跳\r\n * 整体。每请求重读会让多步流程(如 `payment-methods add` 的 create + poll + get)\r\n * 各自拿到完整预算,等于凭空放大了本跳的时间上限。\r\n */\r\n private readonly deadlineMs: number | null;\r\n /** 本进程开始时刻(单调时钟),用于算已用时间。 */\r\n private readonly startedAt: number;\r\n\r\n constructor(config: ApiClientConfig) {\r\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\r\n this.deadlineMs = deadlineFromEnv();\r\n this.startedAt = performance.now();\r\n // 超时优先级:显式传参 > AGENZO_CLI_HTTP_TIMEOUT_MS > 默认值,再由剩余预算收紧。\r\n // 预算只能压小不能放大——它代表上游还愿意等多久,本跳没有权限超出。\r\n const configured = config.timeout ?? httpTimeoutFromEnv() ?? DEFAULT_HTTP_TIMEOUT_MS;\r\n this.timeout =\r\n this.deadlineMs === null\r\n ? configured\r\n : Math.min(configured, Math.max(1, this.deadlineMs - DEADLINE_RESERVE_MS));\r\n this.requestId = crypto.randomUUID();\r\n }\r\n\r\n /** 交给下游的剩余毫秒:扣掉本进程已用时间与回程预留;无预算时返回 null。 */\r\n private remainingDeadlineMs(): number | null {\r\n if (this.deadlineMs === null) return null;\r\n const elapsed = performance.now() - this.startedAt;\r\n return Math.max(0, Math.round(this.deadlineMs - elapsed - DEADLINE_RESERVE_MS));\r\n }\r\n\r\n private buildHeaders(auth: AuthMode): Record<string, string> {\r\n const headers: Record<string, string> = {\r\n 'User-Agent': `agenzo-admin-cli/${getCurrentVersion()}`,\r\n 'X-Request-Id': this.requestId,\r\n };\r\n // 递减 deadline:把扣除本进程已用时间后的剩余量传给 platform,它再往下传给\r\n // provider / ledger。每一跳都只能收紧,链路末端因此不会超出 App 的等待上限。\r\n // 已耗尽时仍然发(值为 0),让下游能立刻返回 DEADLINE_EXCEEDED 而不是白跑一趟。\r\n const remaining = this.remainingDeadlineMs();\r\n if (remaining !== null) {\r\n headers[DEADLINE_HEADER] = String(remaining);\r\n }\r\n // 续链上游 trace:orchestrator 以子进程方式调用 CLI 时,把 W3C traceparent 放在\r\n // TRACEPARENT 环境变量里(见 orchestrator app/backend_gateway/universal.py)。\r\n // 不转发的话 platform 只能看到本进程自生成的 X-Request-Id,链路在 CLI 这里断开。\r\n // 格式非法时不发,避免把脏值写进下游 trace_id。\r\n const traceparent = process.env.TRACEPARENT;\r\n if (traceparent && TRACEPARENT_PATTERN.test(traceparent.trim())) {\r\n headers['traceparent'] = traceparent.trim();\r\n }\r\n // 业务旅程关联键 flow_id:与 traceparent 同一机制(环境变量 → 请求头)。\r\n // 不转发的话链路在 CLI 这里断开,platform 侧按 flow_id 查不到锁房 / 扣款这些调用。\r\n const baggage = baggageFromEnv();\r\n if (baggage !== null) {\r\n headers[BAGGAGE_HEADER] = baggage;\r\n }\r\n if (auth.type === 'bearer') {\r\n headers['Authorization'] = `Bearer ${auth.token}`;\r\n } else if (auth.type === 'api-key') {\r\n headers['X-Api-Key'] = auth.key;\r\n }\r\n return headers;\r\n }\r\n\r\n async get<T>(\r\n path: string,\r\n auth: AuthMode,\r\n params?: Record<string, string>,\r\n ): Promise<ApiResult<T>> {\r\n let url = `${this.baseUrl}${path}`;\r\n if (params && Object.keys(params).length > 0) {\r\n const searchParams = new URLSearchParams(params);\r\n url += `?${searchParams.toString()}`;\r\n }\r\n return this.request<T>(url, {\r\n method: 'GET',\r\n headers: this.buildHeaders(auth),\r\n });\r\n }\r\n\r\n async post<T>(\r\n path: string,\r\n auth: AuthMode,\r\n body?: Record<string, unknown>,\r\n extraHeaders?: Record<string, string>,\r\n ): Promise<ApiResult<T>> {\r\n const url = `${this.baseUrl}${path}`;\r\n const headers = this.buildHeaders(auth);\r\n headers['Content-Type'] = 'application/json';\r\n if (extraHeaders) {\r\n Object.assign(headers, extraHeaders);\r\n }\r\n return this.request<T>(url, {\r\n method: 'POST',\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n }\r\n\r\n private async request<T>(url: string, init: RequestInit): Promise<ApiResult<T>> {\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n ...init,\r\n signal: controller.signal,\r\n });\r\n\r\n // Enforce server-advertised CLI version floor before doing any work\r\n // on the response. Throws UpgradeRequiredError which is rendered and\r\n // exits at the top level (src/index.ts).\r\n this.enforceMinVersion(response.headers.get('x-cli-min-version'));\r\n\r\n // Handle non-JSON responses (e.g. 500 Internal Server Error returns plain text)\r\n const contentType = response.headers.get('content-type') ?? '';\r\n let responseBody: Record<string, unknown>;\r\n if (contentType.includes('application/json')) {\r\n responseBody = await response.json() as Record<string, unknown>;\r\n } else {\r\n const text = await response.text();\r\n if (!response.ok) {\r\n const statusMsg = this.friendlyStatusMessage(response.status);\r\n return {\r\n success: false,\r\n errorCode: 0,\r\n errorMessage: statusMsg,\r\n statusCode: response.status,\r\n };\r\n }\r\n // Try parsing as JSON anyway (some servers don't set content-type)\r\n try {\r\n responseBody = JSON.parse(text) as Record<string, unknown>;\r\n } catch {\r\n return {\r\n success: false,\r\n errorCode: 0,\r\n errorMessage: `Unexpected response from server (${response.status})`,\r\n statusCode: response.status,\r\n };\r\n }\r\n }\r\n\r\n // Server uses unified format: { code: \"0000\", message: \"...\", data: {...} }\r\n const code = responseBody.code as string | undefined;\r\n const message = responseBody.message as string | undefined;\r\n\r\n // Success: HTTP 2xx AND code is \"0000\" (or no code field for raw responses)\r\n if (response.ok && (!code || code === '0000')) {\r\n // If the server wraps the payload in a \"data\" field, unwrap it —\r\n // including when `data` is explicitly null (a valid empty payload,\r\n // e.g. GET /accounts for a developer without a settlement account).\r\n // We must distinguish \"no data field\" (raw response → use the whole\r\n // body) from \"data field present but null\" (→ return null), since\r\n // `data ?? responseBody` would wrongly fall back to the envelope and\r\n // surface { code, message, data: null } as the payload.\r\n const hasDataField = Object.prototype.hasOwnProperty.call(responseBody, 'data');\r\n const payload = hasDataField ? responseBody.data : responseBody;\r\n return { success: true, data: payload as T, message };\r\n }\r\n\r\n // Error: either HTTP non-2xx or code !== \"0000\"\r\n const errorCode = code ? parseInt(code, 10) : 0;\r\n // Handle FastAPI 422 validation errors where detail is an array\r\n let errorMsg = message ?? response.statusText;\r\n if (!errorMsg || errorMsg === response.statusText) {\r\n const detail = responseBody.detail;\r\n if (Array.isArray(detail)) {\r\n errorMsg = detail.map((d: Record<string, unknown>) => {\r\n const loc = (d.loc as string[])?.slice(1).join('.') ?? '';\r\n return loc ? `${loc}: ${d.msg}` : String(d.msg);\r\n }).join('; ');\r\n } else if (typeof detail === 'string') {\r\n errorMsg = detail;\r\n }\r\n }\r\n\r\n // Prefer string error_code (CLI D3 routing) over numeric code string\r\n const errorCodeStr = responseBody.error_code as string | undefined;\r\n\r\n // Preserve object-shaped error data for recoverable operations and extract\r\n // provider diagnostics from the same safe structure.\r\n const dataValue = responseBody.data;\r\n const rawData = dataValue && typeof dataValue === 'object' && !Array.isArray(dataValue)\r\n ? dataValue as Record<string, unknown>\r\n : undefined;\r\n const upstream = (rawData?.upstream && typeof rawData.upstream === 'object')\r\n ? rawData.upstream as UpstreamError\r\n : undefined;\r\n\r\n return {\r\n success: false,\r\n errorCode: isNaN(errorCode) ? 0 : errorCode,\r\n errorMessage: errorMsg,\r\n statusCode: response.status,\r\n ...(errorCodeStr ? { code: errorCodeStr } : (typeof code === 'string' && code ? { code } : {})),\r\n requestId: (responseBody.request_id ?? responseBody.requestId) as string | undefined,\r\n ...(rawData ? { data: rawData } : {}),\r\n ...(upstream ? { upstream } : {}),\r\n };\r\n } catch (error) {\r\n // UpgradeRequiredError is a CliError and must propagate untouched to the\r\n // top-level handler; don't rewrap it as a NetworkError.\r\n if (error instanceof UpgradeRequiredError) {\r\n throw error;\r\n }\r\n if (error instanceof DOMException && error.name === 'AbortError') {\r\n throw new NetworkError(url, this.timeout);\r\n }\r\n throw new NetworkError(url, undefined, error instanceof Error ? error : undefined);\r\n } finally {\r\n clearTimeout(timeoutId);\r\n }\r\n }\r\n\r\n /**\r\n * Validate that the running CLI meets the server-advertised minimum.\r\n * Missing or empty header → skip (backward compat with servers that don't\r\n * advertise yet, and clients hitting legacy proxies).\r\n */\r\n private enforceMinVersion(headerValue: string | null): void {\r\n const minVersion = headerValue?.trim();\r\n if (!minVersion) return;\r\n const current = getCurrentVersion();\r\n if (isBelow(current, minVersion)) {\r\n throw new UpgradeRequiredError(current, minVersion, UPGRADE_COMMAND);\r\n }\r\n }\r\n\r\n private friendlyStatusMessage(status: number): string {\r\n const messages: Record<number, string> = {\r\n 400: 'Invalid request. Please check your input.',\r\n 401: 'Authentication failed. Please check your API key or login again.',\r\n 403: 'Access denied. You do not have permission for this operation.',\r\n 404: 'Resource not found. Please check the ID.',\r\n 409: 'Conflict. This resource may already exist.',\r\n 422: 'Invalid input. Please check the request parameters.',\r\n 429: 'Too many requests. Please wait and try again.',\r\n 500: 'Something went wrong on the server. Please try again later.',\r\n 502: 'Service is temporarily unavailable. Please try again in a moment.',\r\n 503: 'Service is temporarily unavailable. Please try again in a moment.',\r\n 504: 'The request took too long. Please try again.',\r\n };\r\n return messages[status] ?? `Something went wrong (${status}). Please try again later.`;\r\n }\r\n}\r\n","import { readFile, writeFile, readdir, unlink, access, mkdir, chmod } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\nimport { OrgCredential } from '../types/config.js';\r\n\r\nexport class CredentialStore {\r\n private readonly basePath: string;\r\n\r\n constructor(basePath?: string) {\r\n this.basePath = basePath ?? join(homedir(), '.agenzo-admin-cli', 'credentials');\r\n }\r\n\r\n private filePath(orgId: string): string {\r\n return join(this.basePath, `${orgId}.json`);\r\n }\r\n\r\n private async ensureDir(): Promise<void> {\r\n // Credentials hold long-lived Bearer tokens — dir must be owner-only (0700).\r\n // mkdir mode is subject to umask, so chmod afterwards to enforce it on\r\n // both freshly created and pre-existing directories.\r\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\r\n await chmod(this.basePath, 0o700);\r\n }\r\n\r\n async get(orgId: string): Promise<OrgCredential | null> {\r\n try {\r\n const content = await readFile(this.filePath(orgId), 'utf-8');\r\n return JSON.parse(content) as OrgCredential;\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async save(credential: OrgCredential): Promise<void> {\r\n await this.ensureDir();\r\n const path = this.filePath(credential.org_id);\r\n // Owner read/write only (0600); chmod after write so pre-existing files\r\n // created before this safeguard also get tightened.\r\n await writeFile(path, JSON.stringify(credential, null, 2), {\r\n encoding: 'utf-8',\r\n mode: 0o600,\r\n });\r\n await chmod(path, 0o600);\r\n }\r\n\r\n async delete(orgId: string): Promise<void> {\r\n try {\r\n await unlink(this.filePath(orgId));\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return;\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async listAll(): Promise<OrgCredential[]> {\r\n try {\r\n const files = await readdir(this.basePath);\r\n const jsonFiles = files.filter((f) => f.endsWith('.json'));\r\n const credentials: OrgCredential[] = [];\r\n for (const file of jsonFiles) {\r\n try {\r\n const content = await readFile(join(this.basePath, file), 'utf-8');\r\n credentials.push(JSON.parse(content) as OrgCredential);\r\n } catch {\r\n // Skip corrupted files\r\n }\r\n }\r\n return credentials;\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return [];\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async exists(orgId: string): Promise<boolean> {\r\n try {\r\n await access(this.filePath(orgId));\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n}\r\n","import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\r\nimport { dirname, join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\nimport { StoredApiKey } from '../types/config.js';\r\n\r\nexport class KeyStore {\r\n private readonly basePath: string;\r\n\r\n constructor(basePath?: string) {\r\n // API keys are shared across runtime-plane CLIs (token/merchant/payment).\r\n // Stored under the legacy path for backward compatibility; will migrate to\r\n // ~/.agenzo/keys/ in a future release.\r\n this.basePath = basePath ?? join(homedir(), '.agenzo-token-cli', 'api-keys');\r\n }\r\n\r\n private filePath(orgId: string): string {\r\n return join(this.basePath, `${orgId}.json`);\r\n }\r\n\r\n private async loadData(orgId: string): Promise<StoredApiKey[]> {\r\n try {\r\n const content = await readFile(this.filePath(orgId), 'utf-8');\r\n return JSON.parse(content) as StoredApiKey[];\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return [];\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n private async saveData(orgId: string, data: StoredApiKey[]): Promise<void> {\r\n // Stored API keys are plaintext secrets — dir 0700, file 0600.\r\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\r\n await chmod(this.basePath, 0o700);\r\n const path = this.filePath(orgId);\r\n await writeFile(path, JSON.stringify(data, null, 2), {\r\n encoding: 'utf-8',\r\n mode: 0o600,\r\n });\r\n await chmod(path, 0o600);\r\n }\r\n\r\n async add(orgId: string, key: StoredApiKey): Promise<void> {\r\n const data = await this.loadData(orgId);\r\n data.push(key);\r\n await this.saveData(orgId, data);\r\n }\r\n\r\n async update(orgId: string, keyId: string, newKeyValue: string): Promise<void> {\r\n const data = await this.loadData(orgId);\r\n const key = data.find((k) => k.key_id === keyId);\r\n if (key) {\r\n key.key_value = newKeyValue;\r\n await this.saveData(orgId, data);\r\n }\r\n }\r\n\r\n async list(orgId: string): Promise<StoredApiKey[]> {\r\n return this.loadData(orgId);\r\n }\r\n\r\n async get(orgId: string, keyId: string): Promise<StoredApiKey | null> {\r\n const data = await this.loadData(orgId);\r\n return data.find((k) => k.key_id === keyId) ?? null;\r\n }\r\n}\r\n","import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\nimport { AppConfig } from '../types/config.js';\r\nimport { ConfigError, ValidationError } from '../errors/errors.js';\r\n\r\n// §6 target routing: each product line is served under its own prefix\r\n// (/api/{line}/v1). The prefix is a per-binary constant injected into\r\n// ConfigManager (see constructor `apiPath`), NOT a single shared value — the\r\n// four CLIs hit different product lines under one shared api_host.\r\n// This default is the admin control-plane prefix; other CLIs override it.\r\nconst DEFAULT_API_PATH = '/api/admin/v1';\r\n\r\nconst DEFAULT_CONFIG: AppConfig = {\r\n active_org: null,\r\n active_developer_id: null,\r\n api_host: 'https://agent.agenzo.com',\r\n api_path: DEFAULT_API_PATH,\r\n};\r\n\r\nexport const BUILTIN_PROFILES: Record<string, string> = {\r\n production: 'https://agent.agenzo.com',\r\n testing: 'https://agent-dev.agenzo.com',\r\n};\r\n\r\n/**\r\n * Resolve a user-supplied host argument (a built-in profile name or an\r\n * explicit URL) to the concrete API host URL that gets persisted.\r\n * Pure (no I/O) so callers can compute the resolved value before/without a\r\n * config write — e.g. `config set-host` needs it to match stored credentials\r\n * by their resolved `api_host` rather than the raw profile name.\r\n * Throws `ValidationError` for unknown profiles / malformed URLs.\r\n */\r\nexport function resolveApiHost(host: string): string {\r\n if (BUILTIN_PROFILES[host]) {\r\n return BUILTIN_PROFILES[host];\r\n }\r\n\r\n let url: URL;\r\n try {\r\n url = new URL(host);\r\n } catch {\r\n throw new ValidationError(`Unknown profile or invalid URL: ${host}`);\r\n }\r\n\r\n if (url.protocol === 'https:') {\r\n return host;\r\n }\r\n\r\n if (\r\n url.protocol === 'http:'\r\n && (url.hostname === 'localhost' || url.hostname === '127.0.0.1')\r\n ) {\r\n return host;\r\n }\r\n\r\n // Allow HTTP for Docker internal container-to-container traffic (gated by env var)\r\n if (url.protocol === 'http:' && process.env.AGENZO_ALLOW_INSECURE_HOST === '1') {\r\n return host;\r\n }\r\n\r\n throw new ValidationError(\r\n `Insecure API host is not allowed: ${host}. Use HTTPS, except for localhost or 127.0.0.1.`,\r\n );\r\n}\r\n\r\nexport class ConfigManager {\r\n private readonly basePath: string;\r\n private readonly configPath: string;\r\n /**\r\n * Product-line API prefix this CLI targets (e.g. /api/admin/v1,\r\n * /api/token/v1). Injected per binary so the four CLIs share one api_host\r\n * but route to different product lines. Overrides any persisted api_path.\r\n */\r\n private readonly apiPath: string;\r\n\r\n constructor(basePath?: string, apiPath?: string) {\r\n this.basePath = basePath ?? join(homedir(), '.agenzo-admin-cli');\r\n this.configPath = join(this.basePath, 'config.json');\r\n this.apiPath = apiPath ?? DEFAULT_API_PATH;\r\n }\r\n\r\n /** The resolved product-line API prefix for this CLI (per-binary constant). */\r\n getApiPath(): string {\r\n return this.apiPath;\r\n }\r\n\r\n async ensureDirectories(): Promise<void> {\r\n // Base dir contains the credentials/ subtree → owner-only (0700).\r\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\r\n await chmod(this.basePath, 0o700);\r\n const credDir = join(this.basePath, 'credentials');\r\n await mkdir(credDir, { recursive: true, mode: 0o700 });\r\n await chmod(credDir, 0o700);\r\n }\r\n\r\n async load(): Promise<AppConfig> {\r\n try {\r\n const content = await readFile(this.configPath, 'utf-8');\r\n try {\r\n const raw = JSON.parse(content) as Record<string, unknown>;\r\n // Migrate old api_base_url format\r\n if (raw.api_base_url && !raw.api_host) {\r\n const url = String(raw.api_base_url);\r\n const pathIndex = url.indexOf('/api/');\r\n raw.api_host = pathIndex > 0 ? url.slice(0, pathIndex) : url;\r\n raw.api_path = pathIndex > 0 ? url.slice(pathIndex) : DEFAULT_CONFIG.api_path;\r\n delete raw.api_base_url;\r\n }\r\n return {\r\n active_org: (raw.active_org as string) ?? null,\r\n active_developer_id: (raw.active_developer_id as string) ?? null,\r\n api_host: (raw.api_host as string) ?? DEFAULT_CONFIG.api_host,\r\n api_path: (raw.api_path as string) ?? DEFAULT_CONFIG.api_path,\r\n };\r\n } catch {\r\n throw new ConfigError(\r\n `Invalid config file: ${this.configPath}`,\r\n this.configPath,\r\n );\r\n }\r\n } catch (error) {\r\n if (error instanceof ConfigError) throw error;\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return { ...DEFAULT_CONFIG };\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n async save(config: AppConfig): Promise<void> {\r\n await this.ensureDirectories();\r\n await writeFile(this.configPath, JSON.stringify(config, null, 2), {\r\n encoding: 'utf-8',\r\n mode: 0o600,\r\n });\r\n await chmod(this.configPath, 0o600);\r\n }\r\n\r\n async getActiveOrg(): Promise<string | null> {\r\n const config = await this.load();\r\n return config.active_org;\r\n }\r\n\r\n async setActiveOrg(orgId: string): Promise<void> {\r\n const config = await this.load();\r\n config.active_org = orgId;\r\n await this.save(config);\r\n }\r\n\r\n async getApiBaseUrl(): Promise<string> {\r\n const config = await this.load();\r\n const host = resolveApiHost(config.api_host).replace(/\\/+$/, '');\r\n // Use the per-binary product-line prefix, not the persisted api_path —\r\n // the latter is shared across all CLIs and would route every binary to the\r\n // same product line. The injected prefix overrides any stale stored value.\r\n const path = this.apiPath.startsWith('/') ? this.apiPath : `/${this.apiPath}`;\r\n return `${host}${path}`;\r\n }\r\n\r\n async setApiHost(host: string): Promise<void> {\r\n const config = await this.load();\r\n config.api_host = resolveApiHost(host);\r\n await this.save(config);\r\n }\r\n\r\n async getApiHost(): Promise<string> {\r\n const config = await this.load();\r\n return resolveApiHost(config.api_host);\r\n }\r\n}\r\n","import { CliError } from '../errors/errors.js';\r\n\r\n/**\r\n * Exit-code mapper (cli-design §8.6 / cli-standard §5.4).\r\n *\r\n * Maps any thrown error reaching the top-level handler to one of the CLI's\r\n * non-zero exit codes. Normal completion implies `0` and never consults this.\r\n *\r\n * 1 — business / param: PARAM_* / RESOURCE_* / BILLING_* / ACCOUNT_* /\r\n * PAYMENT_ORDER_* / TOKEN_* / SERVICE_* / ride codes / CLIENT_* /\r\n * NOT_IMPLEMENTED, and unknown errors\r\n * 2 — upgrade required: UPGRADE_REQUIRED\r\n * 3 — auth-fail / invalid-key: AUTH_* / KEY_*\r\n * 4 — network / 5xx: UPSTREAM_ERROR / INTERNAL_ERROR / RATE_LIMITED\r\n * 5 — user-cancel: CLIENT_ABORTED\r\n */\r\nexport function exitCodeFor(error: unknown): 1 | 2 | 3 | 4 | 5 {\r\n if (!(error instanceof CliError)) {\r\n return 1;\r\n }\r\n\r\n const code = error.code;\r\n\r\n if (code === 'UPGRADE_REQUIRED') {\r\n return 2;\r\n }\r\n\r\n if (code === 'CLIENT_ABORTED') {\r\n return 5;\r\n }\r\n\r\n if (code.startsWith('AUTH_') || code.startsWith('KEY_')) {\r\n return 3;\r\n }\r\n\r\n if (\r\n code === 'UPSTREAM_ERROR' ||\r\n code === 'INTERNAL_ERROR' ||\r\n code === 'RATE_LIMITED'\r\n ) {\r\n return 4;\r\n }\r\n\r\n return 1;\r\n}\r\n","export type StatusPrefix = 'success' | 'error' | 'info' | 'warning' | 'loading';\r\n\r\nconst STATUS_ICONS: Record<StatusPrefix, string> = {\r\n success: '✓',\r\n error: '✗',\r\n info: 'ℹ',\r\n warning: '⚠',\r\n loading: '⠋',\r\n};\r\n\r\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\r\n\r\nexport interface Spinner {\r\n /** Update the spinner message while it's running */\r\n update(message: string): void;\r\n /** Stop the spinner and show a final status line */\r\n stop(type?: StatusPrefix, finalMessage?: string): void;\r\n}\r\n\r\n/**\r\n * Creates an animated terminal spinner that cycles through braille frames.\r\n * Call `spinner.stop()` when the async work is done.\r\n */\r\nexport function createSpinner(message: string, intervalMs = 60): Spinner {\r\n let frameIdx = 0;\r\n let currentMessage = message;\r\n\r\n const render = () => {\r\n process.stdout.write(`\\r\\x1b[K${SPINNER_FRAMES[frameIdx]} ${currentMessage}`);\r\n frameIdx = (frameIdx + 1) % SPINNER_FRAMES.length;\r\n };\r\n\r\n render();\r\n const timer = setInterval(render, intervalMs);\r\n\r\n return {\r\n update(msg: string) {\r\n currentMessage = msg;\r\n },\r\n stop(type?: StatusPrefix, finalMessage?: string) {\r\n clearInterval(timer);\r\n process.stdout.write('\\r\\x1b[K');\r\n if (type && finalMessage) {\r\n console.log(Formatter.status(type, finalMessage));\r\n }\r\n },\r\n };\r\n}\r\n\r\nexport class Formatter {\r\n /** Get display width of a string (CJK characters count as 2) */\r\n private static displayWidth(str: string): number {\r\n let width = 0;\r\n for (const char of str) {\r\n const code = char.codePointAt(0)!;\r\n // CJK Unified Ideographs and common fullwidth ranges\r\n if (\r\n (code >= 0x4e00 && code <= 0x9fff) || // CJK Unified\r\n (code >= 0x3000 && code <= 0x303f) || // CJK Punctuation\r\n (code >= 0x3400 && code <= 0x4dbf) || // CJK Extension A\r\n (code >= 0xff00 && code <= 0xffef) || // Fullwidth Forms\r\n (code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility\r\n (code >= 0x20000 && code <= 0x2a6df) // CJK Extension B\r\n ) {\r\n width += 2;\r\n } else {\r\n width += 1;\r\n }\r\n }\r\n return width;\r\n }\r\n\r\n /** Pad string to target display width (right-pad with spaces) */\r\n private static padEndDisplay(str: string, targetWidth: number): string {\r\n const currentWidth = Formatter.displayWidth(str);\r\n const padding = Math.max(0, targetWidth - currentWidth);\r\n return str + ' '.repeat(padding);\r\n }\r\n\r\n /** Pad string to target display width (left-pad with spaces) */\r\n private static padStartDisplay(str: string, targetWidth: number): string {\r\n const currentWidth = Formatter.displayWidth(str);\r\n const padding = Math.max(0, targetWidth - currentWidth);\r\n return ' '.repeat(padding) + str;\r\n }\r\n\r\n /** Table output for list commands — columns aligned by max width */\r\n static table(headers: string[], rows: string[][]): string {\r\n const colWidths = headers.map((h, i) => {\r\n const cellWidths = rows.map((r) => Formatter.displayWidth(r[i] ?? ''));\r\n return Math.max(Formatter.displayWidth(h), ...cellWidths);\r\n });\r\n\r\n const sep = ' ';\r\n\r\n const headerLine = headers.map((h, i) => Formatter.padEndDisplay(h, colWidths[i])).join(sep);\r\n const divider = colWidths.map((w) => '-'.repeat(w)).join(sep);\r\n const dataLines = rows.map((row) =>\r\n row.map((cell, i) => Formatter.padEndDisplay(cell ?? '', colWidths[i])).join(sep),\r\n );\r\n\r\n return [headerLine, divider, ...dataLines].join('\\n');\r\n }\r\n\r\n /** Key-value output for detail commands — keys left-aligned */\r\n static keyValue(entries: [string, string][]): string {\r\n const maxKeyWidth = Math.max(...entries.map(([k]) => Formatter.displayWidth(k)));\r\n return entries\r\n .map(([key, value]) => `${Formatter.padEndDisplay(key, maxKeyWidth)} ${value}`)\r\n .join('\\n');\r\n }\r\n\r\n /** Status-prefixed message */\r\n static status(type: StatusPrefix, message: string): string {\r\n return `${STATUS_ICONS[type]} ${message}`;\r\n }\r\n\r\n /** Mask sensitive info, keeping only the prefix */\r\n static maskKey(key: string, prefixLength = 8): string {\r\n if (key.length <= prefixLength) {\r\n return key;\r\n }\r\n return key.slice(0, prefixLength) + '*'.repeat(key.length - prefixLength);\r\n }\r\n\r\n /**\r\n * Format ISO 8601 timestamp to local timezone display.\r\n * Automatically uses the user's system timezone.\r\n * e.g. \"2026-05-07T03:24:53+00:00\" → \"2026-05-07 11:24:53\" (in CST)\r\n * \"2026-05-07T03:24:53+00:00\" → \"2026-05-06 20:24:53\" (in PDT)\r\n * Returns the original string if parsing fails or input is empty.\r\n */\r\n static formatTime(iso: string | null | undefined): string {\r\n if (!iso) return '';\r\n const date = new Date(iso);\r\n if (isNaN(date.getTime())) return iso;\r\n const pad = (n: number) => String(n).padStart(2, '0');\r\n const y = date.getFullYear();\r\n const m = pad(date.getMonth() + 1);\r\n const d = pad(date.getDate());\r\n const h = pad(date.getHours());\r\n const min = pad(date.getMinutes());\r\n const s = pad(date.getSeconds());\r\n const offsetMin = -date.getTimezoneOffset();\r\n const sign = offsetMin >= 0 ? '+' : '-';\r\n const absOffset = Math.abs(offsetMin);\r\n const tzH = pad(Math.floor(absOffset / 60));\r\n const tzM = pad(absOffset % 60);\r\n return `${y}-${m}-${d} ${h}:${min}:${s} (UTC${sign}${tzH}:${tzM})`;\r\n }\r\n}\r\n","import type { CommandResult } from '../types/commands.js';\r\nimport { Formatter, type StatusPrefix } from './formatter.js';\r\n\r\n/**\r\n * Central output renderer.\r\n *\r\n * Single choke point that turns a {@link CommandResult} into stdout bytes,\r\n * switching between machine-readable JSON and a human-readable table view.\r\n * This is what lets command handlers stop calling `console.log` directly:\r\n * they build a `CommandResult` and hand it here.\r\n *\r\n * Contract (cli-standard §5.1/§5.2):\r\n * - stdout carries ONLY the business payload — a single JSON value\r\n * (`--format json`) or human-readable text (`--format table`).\r\n * - logs, spinners, prompts, hints and progress lines belong on stderr and\r\n * are NEVER written here.\r\n *\r\n * Recorded deviation from cli-standard §5.1: the default format is `table`\r\n * (not `json`), and the flag values are `json | table` (not `json | text`).\r\n */\r\n\r\n/** The two supported output formats. */\r\nexport type OutputFormat = 'json' | 'table';\r\n\r\n/** Options consumed by {@link render}. */\r\nexport interface RenderOptions {\r\n format: OutputFormat;\r\n}\r\n\r\n/** The default format used when nothing valid is supplied (deliberate deviation: `table`). */\r\nconst DEFAULT_FORMAT: OutputFormat = 'table';\r\n\r\n/** Narrow an arbitrary string to a known {@link OutputFormat}. */\r\nfunction isOutputFormat(value: string): value is OutputFormat {\r\n return value === 'json' || value === 'table';\r\n}\r\n\r\n/**\r\n * Resolve the active output format.\r\n *\r\n * Precedence: `--format` flag > `AGENZO_FORMAT` env var > default `table`.\r\n * Any invalid value falls back to the default. The result is always one of\r\n * `'json' | 'table'`.\r\n *\r\n * The `--format` flag is authoritative when provided: a provided-but-invalid\r\n * flag falls back to the default rather than deferring to the environment.\r\n */\r\nexport function resolveFormat(\r\n flag?: string,\r\n env: string | undefined = process.env.AGENZO_FORMAT,\r\n): OutputFormat {\r\n // 1. --format flag is authoritative when provided.\r\n if (flag !== undefined) {\r\n return isOutputFormat(flag) ? flag : DEFAULT_FORMAT;\r\n }\r\n // 2. AGENZO_FORMAT environment value, when set to a valid format.\r\n if (env !== undefined && isOutputFormat(env)) {\r\n return env;\r\n }\r\n // 3. Default.\r\n return DEFAULT_FORMAT;\r\n}\r\n\r\n/**\r\n * Emit a successful command result to stdout in the chosen format.\r\n *\r\n * - `json`: writes `JSON.stringify(result.data, null, 2)` (the machine payload\r\n * only — never the text-mode chrome).\r\n * - `table`: writes the lazy human presenter `result.text()`.\r\n *\r\n * Only the payload reaches stdout; status/progress lines must go to stderr by\r\n * the caller. A trailing newline is appended so the output pipes cleanly into\r\n * tools like `jq`.\r\n */\r\nexport function render<T>(result: CommandResult<T>, opts: RenderOptions): void {\r\n if (opts.format === 'json') {\r\n process.stdout.write(`${JSON.stringify(result.data, null, 2)}\\n`);\r\n return;\r\n }\r\n process.stdout.write(`${result.text()}\\n`);\r\n}\r\n\r\n/**\r\n * Emit a human-facing status line (✓ / ℹ / ⚠) to stderr — but ONLY in `table`\r\n * mode. In `json` mode the output is consumed by other agents/scripts, so any\r\n * decorative status text (even on stderr) is noise that can confuse parsing;\r\n * `json` mode therefore stays completely silent here. Errors are NOT routed\r\n * through this helper — they are owned by the top-level handler in index.ts.\r\n *\r\n * This is the single choke point for command success/progress notices, so the\r\n * `json`-silence rule is enforced in one place rather than scattered across\r\n * every handler.\r\n */\r\nexport function notify(\r\n format: OutputFormat,\r\n type: StatusPrefix,\r\n message: string,\r\n): void {\r\n if (format === 'json') {\r\n return;\r\n }\r\n console.error(Formatter.status(type, message));\r\n}\r\n","/**\r\n * Shared JSON envelope renderer (cli-design §7.7.2 BACK-011).\r\n *\r\n * In `--format json` mode, every command's payload is prefixed with two\r\n * client-assembled context fields:\r\n * - `profile`: the active environment name (production / testing / custom),\r\n * derived by reverse-looking-up the api_host in BUILTIN_PROFILES.\r\n * - `endpoint`: the api **host only** (e.g. https://agent.agenzo.com) —\r\n * NEVER the internal API path (/api/admin/v1), so internal\r\n * routing is not leaked to agent consumers.\r\n *\r\n * `result.data` is expected to be an object (single-resource payloads are flat\r\n * field maps; list payloads are `{ <namedKey>: [...], page: {...} }`). The two\r\n * context fields are spread in front of it.\r\n *\r\n * In `--format table` mode this is a passthrough to the standard `render`.\r\n *\r\n * This lives in `@agenzo/cli-core` (BACK-011) so every CLI shares one\r\n * implementation rather than copying it per app.\r\n */\r\nimport type { CommandResult } from '../types/commands.js';\r\nimport { type RenderOptions, render } from './output.js';\r\nimport { ConfigManager, BUILTIN_PROFILES } from '../config/config-manager.js';\r\n\r\nexport async function renderWithContext<T>(\r\n result: CommandResult<T>,\r\n opts: RenderOptions,\r\n configManager: ConfigManager,\r\n): Promise<void> {\r\n if (opts.format !== 'json') {\r\n render(result, opts);\r\n return;\r\n }\r\n\r\n const config = await configManager.load();\r\n const host = config.api_host.replace(/\\/+$/, '');\r\n const profile =\r\n Object.entries(BUILTIN_PROFILES).find(([, v]) => v === host)?.[0] ?? 'custom';\r\n\r\n const dataObj =\r\n result.data && typeof result.data === 'object'\r\n ? (result.data as Record<string, unknown>)\r\n : { value: result.data };\r\n\r\n const payload = {\r\n profile,\r\n endpoint: host,\r\n ...dataObj,\r\n };\r\n\r\n render({ ...result, data: payload } as CommandResult<typeof payload>, opts);\r\n}\r\n","import { input, password, select } from '@inquirer/prompts';\r\n\r\ninterface PromptConfig {\r\n message: string;\r\n type?: 'input' | 'password' | 'select';\r\n choices?: { name: string; value: string }[];\r\n validate?: (input: string) => boolean | string;\r\n}\r\n\r\nexport class PromptEngine {\r\n /** Return flagValue directly if provided, otherwise prompt interactively */\r\n static async resolveInput(\r\n flagValue: string | undefined,\r\n config: PromptConfig,\r\n ): Promise<string> {\r\n if (flagValue !== undefined) {\r\n return flagValue;\r\n }\r\n\r\n if (config.type === 'password') {\r\n return password({ message: config.message, mask: '*' });\r\n }\r\n\r\n if (config.type === 'select' && config.choices) {\r\n return select({\r\n message: config.message,\r\n choices: config.choices,\r\n });\r\n }\r\n\r\n return input({\r\n message: config.message,\r\n validate: config.validate,\r\n });\r\n }\r\n}\r\n","/**\r\n * Shared `--member <id>` attribution flag (order write + list verbs).\r\n *\r\n * `member_id` is an OPTIONAL, caller-supplied end-user label. The platform\r\n * stores it and filters by it; it is never registered, validated for existence\r\n * or used as an ownership boundary (ownership stays `developer_id` +\r\n * `organization_id`, both derived server-side from the API Key). See\r\n * `doc/member-id-attribution-design.md`.\r\n *\r\n * Why one module: the same description, the same trimming rule and the same\r\n * `source: 'session'` schema entry are needed by 7 verbs across 4 nouns. Keeping\r\n * them here means the attribution semantics are stated once.\r\n *\r\n * `source: 'session'` marks the flag as supplied by the EXECUTION layer (the\r\n * orchestrator injects the authenticated end-user id), so it is hidden from the\r\n * LLM tool schema — an agent must not be able to choose whose orders it writes\r\n * or reads.\r\n */\r\nimport type { Command } from 'commander';\r\nimport type { FlagSchema } from './verb-schema.js';\r\n\r\n/** Option description — identical wording on every verb that accepts it. */\r\nexport const MEMBER_OPTION_DESCRIPTION =\r\n 'End-user member id this order is attributed to (optional, max 128 chars). '\r\n + 'On write it is stored on the order; on list it filters to that member only '\r\n + '(orders without a member_id are excluded).';\r\n\r\n/** Verb-schema entry for the `member` flag. Hidden from LLM tool schemas. */\r\nexport const MEMBER_FLAG_SCHEMA: FlagSchema = {\r\n type: 'string',\r\n required: false,\r\n source: 'session',\r\n description: MEMBER_OPTION_DESCRIPTION,\r\n constraints: '1-128 characters; any character set. Omit to keep the order unattributed.',\r\n};\r\n\r\n/** Register `--member <id>` on a command. */\r\nexport function attachMemberOption(cmd: Command): Command {\r\n return cmd.option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n}\r\n\r\n/**\r\n * Read `--member` from parsed options, trimmed. Returns `undefined` when absent\r\n * or blank so callers omit the field entirely rather than sending `\"\"` (the\r\n * platform rejects an empty/blank `member_id` with 422 — a caller that meant to\r\n * attribute an order must not silently get an unattributed one).\r\n */\r\nexport function memberIdOf(opts: Record<string, unknown>): string | undefined {\r\n const raw = opts.member;\r\n if (typeof raw !== 'string') return undefined;\r\n const trimmed = raw.trim();\r\n return trimmed.length > 0 ? trimmed : undefined;\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError } from '@agenzo/cli-core';\r\nimport type { FlagSchema } from './verb-schema';\r\n\r\n/**\r\n * 价格批注(原价 / 优惠金额)—— 四个结算入口共用的 flag 声明、注册与 body 透传。\r\n *\r\n * 语义(与 platform `app/core/price_annotation.py` 同源):**纯记录字段**。平台把它落在\r\n * 自己的 MongoDB(统一流水 `ap_upi_transactions` + 订单 `auth_snapshot`)并在响应 /\r\n * 订单详情里回显,但**绝不**发给收单网关(evo-cli / EVO HTTP 直连都看不到),也**绝不**\r\n * 参与扣款金额的推导或「实扣额 == 锁单权威价」那道核验 —— 结算金额仍只取订单锁单落库的\r\n * 权威价与令牌铸造时冻结的金额。\r\n *\r\n * 收敛到一处的理由:这两个 flag 要同时出现在 `hotel-redaug pay-order`、\r\n * `flight-flink pay-order`、`flight-flink change-pay`、`ride-elife pay-order` 上。四处各写\r\n * 一遍描述与解析,必然漂移成四种说法(`payment-token-id` 的描述已经踩过这个坑)。\r\n */\r\n\r\nconst ORIGINAL_DESCRIPTION =\r\n 'Original (pre-discount) price in integer cents. Optional, RECORD-ONLY: stored on our own ' +\r\n 'order / charge record and echoed back in the order detail, never sent to the acquiring ' +\r\n 'gateway and never used to derive or validate the amount charged (that always comes from the ' +\r\n \"order's locked authoritative price).\";\r\n\r\nconst DISCOUNT_DESCRIPTION =\r\n 'Discount amount in integer cents. Optional, RECORD-ONLY: same semantics as ' +\r\n '--original-amount-cents.';\r\n\r\n/** `verb-schema.ts` 用的 flag 声明片段(展开进各 verb 的 `flags`)。 */\r\nexport const PRICE_ANNOTATION_FLAGS: Record<string, FlagSchema> = {\r\n 'original-amount-cents': {\r\n type: 'int',\r\n required: false,\r\n description: ORIGINAL_DESCRIPTION,\r\n constraints: 'non-negative integer cents',\r\n },\r\n 'discount-amount-cents': {\r\n type: 'int',\r\n required: false,\r\n description: DISCOUNT_DESCRIPTION,\r\n constraints: 'non-negative integer cents',\r\n },\r\n};\r\n\r\n/** 给一个 commander 命令挂上两个 option(链式返回,便于接在既有 `.option()` 之后)。 */\r\nexport function withPriceAnnotationOptions(cmd: Command): Command {\r\n return cmd\r\n .option('--original-amount-cents <cents>', ORIGINAL_DESCRIPTION)\r\n .option('--discount-amount-cents <cents>', DISCOUNT_DESCRIPTION);\r\n}\r\n\r\n/**\r\n * 把批注写进请求 body(只在 flag 真的出现时写键)。\r\n *\r\n * 本地就把非整数 / 负数挡成 `PARAM_INVALID`,不让一个纯记录字段的格式错误变成 422 往返。\r\n * `0` 是合法取值(优惠 0 = 明确声明「这单没有优惠」),所以判据是 `< 0` 而非 `< 1`,\r\n * 且用 present 判断(`!== undefined`)而非真值判断 —— 真值判断会把 `0` 折叠成「没给」。\r\n */\r\nexport function applyPriceAnnotation(\r\n body: Record<string, unknown>,\r\n opts: Record<string, unknown>,\r\n): void {\r\n const mappings = [\r\n ['--original-amount-cents', 'originalAmountCents', 'original_amount_cents'],\r\n ['--discount-amount-cents', 'discountAmountCents', 'discount_amount_cents'],\r\n ] as const;\r\n\r\n for (const [flag, optKey, bodyKey] of mappings) {\r\n const raw = opts[optKey] as string | number | undefined;\r\n if (raw === undefined) continue;\r\n const cents = Number(raw);\r\n if (!Number.isInteger(cents) || cents < 0) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `Invalid ${flag} \"${raw}\". Expected a non-negative integer number of cents (e.g. 10000 for 100.00).`,\r\n );\r\n }\r\n body[bodyKey] = cents;\r\n }\r\n}\r\n","import type { ApiClient } from '@agenzo/cli-core';\r\nimport { CliError } from '@agenzo/cli-core';\r\nimport type { GetOrderResponse } from '../types/api.js';\r\n\r\n/**\r\n * NDJSON status-polling for `ride-elife get --watch` (§4.4.1.3 polling /\r\n * design Property 2). Merchant-domain logic — stays in the app per\r\n * requirement 4.4 (NOT pushed down to cli-core).\r\n *\r\n * The watch stream is a line stream: each poll result is written as ONE\r\n * independent, compact JSON line on stdout. It is deliberately NOT routed\r\n * through `renderWithContext`, so the profile/endpoint envelope is never\r\n * wrapped around the stream (an agent consumes it with a line reader).\r\n *\r\n * The polling engine is split from its I/O so it can be unit/PBT-tested with a\r\n * fake clock and shortened constants (task 6.5): `fetchStatus`, `writeLine`,\r\n * `sleep` and `now` are all injected.\r\n */\r\n\r\n/**\r\n * Terminal ride statuses (schema `polling.terminal_statuses`). Once the order\r\n * reaches one of these, `--watch` stops polling. CASE-SENSITIVE — must match\r\n * the server casing exactly.\r\n */\r\nexport const TERMINAL_STATUSES: ReadonlySet<string> = new Set([\r\n 'At destination',\r\n 'Cancelled',\r\n 'Rejected',\r\n 'Customer no show',\r\n 'Driver no show',\r\n]);\r\n\r\n/** Schema `polling.recommended_interval_seconds`. */\r\nexport const DEFAULT_WATCH_INTERVAL_SECONDS = 5;\r\n/** Safety cap so `--watch` can never poll forever. */\r\nexport const DEFAULT_WATCH_TIMEOUT_SECONDS = 600;\r\n\r\n/**\r\n * Pure terminal-state predicate (exported for direct unit/PBT testing). A\r\n * missing/undefined status is never terminal, so polling continues until a\r\n * known terminal status or the timeout.\r\n */\r\nexport function isTerminalStatus(status: string | undefined | null): boolean {\r\n return status !== undefined && status !== null && TERMINAL_STATUSES.has(status);\r\n}\r\n\r\n/** Read the case-sensitive `status` field off a poll result. */\r\nexport function statusOf(data: GetOrderResponse): string | undefined {\r\n const status = (data as { status?: unknown }).status;\r\n return typeof status === 'string' ? status : undefined;\r\n}\r\n\r\n/** The final NDJSON line emitted when polling gives up before a terminal status. */\r\nexport interface WatchTimeoutLine {\r\n watch_status: 'timeout';\r\n message: string;\r\n last_status: string | null;\r\n}\r\n\r\n/** I/O + clock seams the polling engine depends on (all injectable for tests). */\r\nexport interface WatchEngineDeps {\r\n /** Fetch one status snapshot (throws to abort the whole stream). */\r\n fetchStatus: () => Promise<GetOrderResponse>;\r\n /** Write one NDJSON record as a single compact line. */\r\n writeLine: (record: unknown) => void;\r\n /** Resolve after `ms` (real timer in prod; fake clock in tests). */\r\n sleep: (ms: number) => Promise<void>;\r\n /** Current epoch millis (real `Date.now` in prod; fake clock in tests). */\r\n now: () => number;\r\n}\r\n\r\n/** Interval / timeout budget for one watch run, in milliseconds. */\r\nexport interface WatchEngineOptions {\r\n intervalMs: number;\r\n timeoutMs: number;\r\n}\r\n\r\n/**\r\n * Poll `fetchStatus`, writing each result as an NDJSON line, until the order\r\n * reaches a terminal status or the timeout elapses. On timeout the FINAL line\r\n * is `{ watch_status: 'timeout', ... }` (requirement 3.2 / Property 2).\r\n *\r\n * Termination: every iteration either returns (terminal status) or, when the\r\n * next poll would land at/after the deadline, emits the timeout line and\r\n * returns. With a monotonically advancing clock (real time, or a fake clock\r\n * advanced by `sleep`) the deadline is always reached, so the loop is\r\n * guaranteed to terminate for any status sequence.\r\n */\r\nexport async function runWatch(\r\n deps: WatchEngineDeps,\r\n opts: WatchEngineOptions,\r\n): Promise<void> {\r\n const deadline = deps.now() + opts.timeoutMs;\r\n for (;;) {\r\n const data = await deps.fetchStatus();\r\n deps.writeLine(data);\r\n\r\n const status = statusOf(data);\r\n if (isTerminalStatus(status)) {\r\n return;\r\n }\r\n\r\n if (deps.now() + opts.intervalMs >= deadline) {\r\n const timeoutLine: WatchTimeoutLine = {\r\n watch_status: 'timeout',\r\n message: `Polling stopped after ${opts.timeoutMs / 1000}s without reaching a terminal status.`,\r\n last_status: status ?? null,\r\n };\r\n deps.writeLine(timeoutLine);\r\n return;\r\n }\r\n\r\n await deps.sleep(opts.intervalMs);\r\n }\r\n}\r\n\r\n/**\r\n * Parse a positive `--watch-*` seconds flag, falling back to a default when\r\n * absent or non-positive (mirrors the standalone reference behaviour). Returns\r\n * a value in SECONDS.\r\n */\r\nexport function resolveSeconds(value: string | undefined, fallback: number): number {\r\n if (value === undefined) return fallback;\r\n const n = Number(value);\r\n return Number.isFinite(n) && n > 0 ? n : fallback;\r\n}\r\n\r\n/** Real-timer sleep used by the production watch path. */\r\nexport const realSleep = (ms: number): Promise<void> =>\r\n new Promise((resolve) => setTimeout(resolve, ms));\r\n\r\n/** Compact single-line NDJSON writer used by the production watch path. */\r\nexport const ndjsonWriteLine = (record: unknown): void => {\r\n process.stdout.write(`${JSON.stringify(record)}\\n`);\r\n};\r\n\r\n/**\r\n * Production wiring for `ride-elife get --watch`: bind the polling engine to a\r\n * live `ApiClient` (status endpoint + api-key auth), the compact NDJSON stdout\r\n * writer, real timers and the system clock. A network/backend failure on any\r\n * poll surfaces as a `CliError` to the top-level handler, exactly like the\r\n * single-shot path.\r\n */\r\nexport async function watchRideStatus(\r\n apiClient: ApiClient,\r\n apiKey: string,\r\n orderId: string,\r\n opts: { intervalSeconds: number; timeoutSeconds: number },\r\n): Promise<void> {\r\n const path = `/ride/${encodeURIComponent(orderId)}/status`;\r\n await runWatch(\r\n {\r\n fetchStatus: async () => {\r\n const result = await apiClient.get<GetOrderResponse>(path, {\r\n type: 'api-key',\r\n key: apiKey,\r\n });\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n return result.data;\r\n },\r\n writeLine: ndjsonWriteLine,\r\n sleep: realSleep,\r\n now: () => Date.now(),\r\n },\r\n {\r\n intervalMs: opts.intervalSeconds * 1000,\r\n timeoutMs: opts.timeoutSeconds * 1000,\r\n },\r\n );\r\n}\r\n","/**\r\n * `--help --format json` verb-level schema (§4.4.1.3) — merchant domain only.\r\n *\r\n * Every ride-elife verb supports `--help --format json`, which prints a single\r\n * machine-readable JSON object describing the verb instead of commander's\r\n * default text help. This is the standard way an Agent discovers a verb's\r\n * flags, response shape, example invocation and (where relevant) error-recovery\r\n * and polling guidance locally, without a network round-trip.\r\n *\r\n * admin-cli / token-cli have no such mode, so this lives in the app (not in\r\n * cli-core) per requirement 4.4.\r\n *\r\n * Mechanism (commander v14): `attachSchemaHelp` overrides a command's\r\n * `helpInformation`. Commander resolves `--help` BEFORE later argv tokens are\r\n * applied to options, so the parsed `--format` value is not yet available when\r\n * help renders — we therefore read it straight from `process.argv`. Only an\r\n * explicit `--format json` switches to the JSON schema; bare `--help` and\r\n * `--help --format table` keep commander's default text help.\r\n */\r\nimport type { Command } from 'commander';\r\nimport { MEMBER_FLAG_SCHEMA } from './member.js';\r\nimport { PRICE_ANNOTATION_FLAGS } from './price-annotation.js';\r\nimport { TERMINAL_STATUSES, DEFAULT_WATCH_INTERVAL_SECONDS } from './ride-elife/watch.js';\r\n\r\nconst CLI_NAME = 'agenzo-merchant-cli';\r\nconst NOUN = 'ride-elife';\r\n/** Hotel noun (command group) — the `hotel-redaug/*` verbs share this. */\r\nexport const HOTEL_NOUN = 'hotel-redaug';\r\n/** Flight noun (command group) — the `flight-flink/*` verbs share this. */\r\nexport const FLIGHT_NOUN = 'flight-flink';\r\n\r\n// ============================================================\r\n// Schema shape (§4.4.1.3 verb-level schema)\r\n// ============================================================\r\n\r\n/** One flag descriptor: type / required / optional default / description / constraints. */\r\nexport interface FlagSchema {\r\n type: string;\r\n /** `true` / `false`, or the literal `'conditional'` for mode-dependent flags. */\r\n required: boolean | 'conditional';\r\n default?: unknown;\r\n description: string;\r\n constraints?: string;\r\n /**\r\n * Where the value comes from when a non-human agent drives the CLI.\r\n *\r\n * `'session'` — supplied by the execution layer from the authenticated\r\n * session (e.g. the orchestrator injects `--member` from the caller's JWT).\r\n * Consumers that build LLM tool schemas MUST hide such flags: letting a model\r\n * choose the value would let it act on another end-user's data.\r\n *\r\n * Omitted means the flag is ordinary agent/human input.\r\n */\r\n source?: 'session';\r\n}\r\n\r\n/** A complete, copy-pasteable example invocation plus what to read from the output. */\r\nexport interface ExampleSchema {\r\n command: string;\r\n output_summary: string;\r\n}\r\n\r\n/**\r\n * Polling guidance — status-query verbs (`get`, `get-checkout`) carry this block.\r\n *\r\n * `terminal_statuses` / `in_progress_statuses` are `Array<string | number>`\r\n * because hotel `get` keys off the INTEGER `order_status_code` set (`[3,4,5]` /\r\n * `[2]`), while ride `get` and hotel `get-checkout` use STRING statuses. The\r\n * widened element type keeps both valid in the same shared interface.\r\n */\r\nexport interface PollingSchema {\r\n recommended_interval_seconds: number;\r\n terminal_statuses: Array<string | number>;\r\n in_progress_statuses: Array<string | number>;\r\n field_availability?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * The verb-level schema object emitted by `--help --format json`\r\n * (§4.4.1.3): `{ cli, noun, verb, description, flags, response, example,\r\n * [error_recovery], [polling] }`. `error_recovery` / `polling` are optional and\r\n * present only where the verb warrants them.\r\n */\r\nexport interface VerbSchema {\r\n cli: string;\r\n noun: string;\r\n verb: string;\r\n description: string;\r\n flags: Record<string, FlagSchema>;\r\n /** Key response fields + type descriptions (nested objects allowed). */\r\n response: Record<string, unknown>;\r\n example: ExampleSchema;\r\n error_recovery?: Record<string, string>;\r\n polling?: PollingSchema;\r\n}\r\n\r\n// ============================================================\r\n// Emit + attach mechanism\r\n// ============================================================\r\n\r\n/**\r\n * True only when `--format json` is explicitly present in `argv`. Commander\r\n * resolves `--help` before applying later option tokens, so the parsed format\r\n * is not yet available at help-render time; we read argv directly. Bare `--help`\r\n * and `--help --format table` deliberately return false (keep text help), even\r\n * though the program defaults `--format` to json — the default is never written\r\n * into argv.\r\n */\r\nexport function wantsJsonSchema(argv: string[] = process.argv): boolean {\r\n for (let i = 0; i < argv.length; i++) {\r\n const a = argv[i];\r\n if (a === '--format=json') return true;\r\n if (a === '--format' && argv[i + 1] === 'json') return true;\r\n }\r\n return false;\r\n}\r\n\r\n/** Print a verb schema as a single pretty-printed JSON object to stdout. */\r\nexport function emitSchema(schema: VerbSchema): void {\r\n console.log(JSON.stringify(schema, null, 2));\r\n}\r\n\r\n/**\r\n * Attach `--help --format json` schema output to a command. When help is\r\n * requested with an explicit `--format json`, the schema is printed to stdout\r\n * and an empty string is returned so commander prints nothing further and exits\r\n * cleanly. Otherwise the original (text) help is rendered unchanged.\r\n */\r\nexport function attachSchemaHelp(cmd: Command, schema: VerbSchema): Command {\r\n const baseHelp = cmd.helpInformation.bind(cmd);\r\n cmd.helpInformation = (context) => {\r\n if (!wantsJsonSchema()) return baseHelp(context);\r\n emitSchema(schema);\r\n return '';\r\n };\r\n return cmd;\r\n}\r\n\r\n// ============================================================\r\n// Ride-elife verb schemas\r\n// ============================================================\r\n//\r\n// Flags / response are kept aligned with each command's ACTUAL flags and the\r\n// cli-core response types (QuoteResponse / BookResponse / GetOrderResponse /\r\n// CancelResponse / ListOrdersResponse). Notably: quote's passenger fields are\r\n// optional here (the command only sends them when set); get's pickup/dropoff\r\n// are `from_location` / `to_location` (v3 snake_case, NOT elife from/to);\r\n// amounts are decimal currency units (NOT cents).\r\n\r\n/** `ride-elife quote` schema (§4.4.1.3 quote schema). */\r\nexport const quoteSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'quote',\r\n description: 'Request fare quotes for a ride between two points',\r\n flags: {\r\n 'pickup-lat': { type: 'float', required: true, description: 'Pickup latitude', constraints: '-90 to 90' },\r\n 'pickup-lng': { type: 'float', required: true, description: 'Pickup longitude', constraints: '-180 to 180' },\r\n 'pickup-name': { type: 'string', required: true, description: 'Pickup location name' },\r\n 'dropoff-lat': { type: 'float', required: true, description: 'Dropoff latitude', constraints: '-90 to 90' },\r\n 'dropoff-lng': { type: 'float', required: true, description: 'Dropoff longitude', constraints: '-180 to 180' },\r\n 'dropoff-name': { type: 'string', required: true, description: 'Dropoff location name' },\r\n 'pickup-time': {\r\n type: 'int|string',\r\n required: true,\r\n description: \"Epoch seconds or the literal 'now'\",\r\n },\r\n 'passenger-name': { type: 'string', required: false, description: 'Lead passenger full name' },\r\n 'passenger-phone': { type: 'string', required: false, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\r\n 'passenger-count': { type: 'int', required: false, description: 'Number of passengers' },\r\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\r\n 'passenger-email': { type: 'string', required: false, description: 'Passenger email address' },\r\n 'children-count': { type: 'int', required: false, description: 'Number of children' },\r\n 'infant-count': { type: 'int', required: false, description: 'Number of infants (passenger breakdown; affects seat pricing)' },\r\n 'toddler-count': { type: 'int', required: false, description: 'Number of toddlers (passenger breakdown; affects seat pricing)' },\r\n },\r\n response: {\r\n vehicle_classes: {\r\n type: 'array',\r\n description: 'Available vehicle options with pricing',\r\n items: {\r\n vehicle_class: { type: 'string', description: 'Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\r\n 'price.amount': { type: 'float', description: 'Price in currency units (e.g. 42.50), NOT cents' },\r\n 'price.currency': { type: 'string', description: 'ISO 4217 (e.g. USD)' },\r\n 'price.quote_id': { type: 'string', description: 'Use this in `ride-elife book --quote-id`' },\r\n passenger_capacity: { type: 'int', description: 'Max passengers' },\r\n luggage_capacity: { type: 'int', description: 'Max luggage items' },\r\n },\r\n },\r\n meet_and_greet: { type: 'object|null', description: 'Meet & greet availability and price' },\r\n is_airport_transfer: { type: 'bool', description: 'Whether this is an airport transfer' },\r\n airport_direction: { type: 'string|null', description: 'pickup / dropoff / null' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife quote --pickup-lat 37.7937 --pickup-lng -122.3956 --pickup-name \"1 Market St\" --dropoff-lat 37.6213 --dropoff-lng -122.3790 --dropoff-name \"SFO Airport\" --pickup-time now',\r\n output_summary:\r\n 'Returns vehicle_classes[] with a quote_id per option. Use quote_id and vehicle_class for booking.',\r\n },\r\n error_recovery: {\r\n VEHICLE_UNAVAILABLE: 'No vehicles for this route/time. Try a different pickup-time or location. Do NOT blindly retry.',\r\n PARAM_INVALID: 'Fix the offending flag (coordinates must be numbers; required pickup/dropoff/pickup-time present), then retry.',\r\n },\r\n};\r\n\r\n/** `ride-elife book` schema (§4.4.1.3 book schema). Write op (W/Y). */\r\nexport const bookSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'book',\r\n description: 'Book a ride using a quote_id returned by a previous quote call',\r\n flags: {\r\n 'quote-id': { type: 'string', required: true, description: 'Quote id from quote response (vehicle_classes[].price.quote_id)' },\r\n 'vehicle-class': { type: 'string', required: true, description: 'Vehicle class: Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\r\n 'price-amount': { type: 'float', required: true, description: 'Fare in decimal currency units (NOT cents), from the quote' },\r\n 'price-currency': { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code' },\r\n 'payment-order-id': {\r\n type: 'string',\r\n required: 'conditional',\r\n description: 'Required when billing_mode=pay_per_call (a PAID payment order). Forbidden when billing_mode=monthly_settlement',\r\n },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Bound payment method id to charge (pay_per_call only). Opaque id from `token payment-methods list`; ignored for monthly_settlement',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'DEPRECATED — use `ride-elife create-order` + `pay-order` for network-token direct charge. A single-step book carrying a network token hits Charge_Service strict order↔token binding and is rejected server-side with a retriable=false guidance error. Kept only for backward compatibility; monthly_settlement / EVO / no-credential booking still work via book',\r\n },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'passenger-name': { type: 'string', required: true, description: 'Passenger full name' },\r\n 'passenger-phone': { type: 'string', required: true, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\r\n 'passenger-email': { type: 'string', required: true, description: 'Passenger email (required by eLife for booking)' },\r\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\r\n 'special-requests': { type: 'string', required: false, description: 'Free-text special requests or notes' },\r\n 'pickup-lat': { type: 'float', required: false, description: 'Pickup latitude (must match the quote)', constraints: '-90 to 90' },\r\n 'pickup-lng': { type: 'float', required: false, description: 'Pickup longitude (must match the quote)', constraints: '-180 to 180' },\r\n 'pickup-name': { type: 'string', required: false, description: 'Pickup location name (must match the quote)' },\r\n 'dropoff-lat': { type: 'float', required: false, description: 'Dropoff latitude (must match the quote)', constraints: '-90 to 90' },\r\n 'dropoff-lng': { type: 'float', required: false, description: 'Dropoff longitude (must match the quote)', constraints: '-180 to 180' },\r\n 'dropoff-name': { type: 'string', required: false, description: 'Dropoff location name (must match the quote)' },\r\n 'pickup-time': { type: 'int|string', required: false, description: \"Epoch seconds or 'now' (must match the quote)\" },\r\n 'meet-and-greet': { type: 'bool', required: false, default: false, description: 'Enable meet & greet service' },\r\n 'meet-and-greet-price': { type: 'float', required: false, description: 'Meet & greet surcharge from the quote (meet_and_greet.price.amount)' },\r\n 'welcome-sign': { type: 'string', required: false, description: 'Welcome sign text (meet & greet)' },\r\n 'child-seat-count': { type: 'int', required: false, description: 'Number of child seats needed', constraints: '0 to 5' },\r\n 'infant-seat-count': { type: 'int', required: false, description: 'Number of infant seats needed', constraints: '0 to 5' },\r\n 'toddler-seat-count': { type: 'int', required: false, description: 'Number of toddler seats needed', constraints: '0 to 5' },\r\n 'arrival-flight-no': { type: 'string', required: false, description: 'Arrival flight number (airport pickup)' },\r\n 'arrival-airline': { type: 'string', required: false, description: 'Arrival airline name' },\r\n 'departure-flight-no': { type: 'string', required: false, description: 'Departure flight number (airport dropoff)' },\r\n 'departure-airline': { type: 'string', required: false, description: 'Departure airline name' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Ride identifier — use for `ride-elife get` / `ride-elife cancel`' },\r\n order_id: { type: 'string|int', description: 'Internal order id for reconciliation' },\r\n status: { type: 'string', description: 'Ride status (case-sensitive server casing)' },\r\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride; false = realtime' },\r\n order_type: { type: 'string', description: \"'realtime' or 'airport'\" },\r\n price: { type: 'object', description: '{ amount, currency, quote_id }' },\r\n payment_status: { type: 'string', description: 'PAID (pay_per_call) or ON_ACCOUNT (monthly_settlement)' },\r\n billing_entry_id: { type: 'string|absent', description: 'Only in monthly_settlement mode' },\r\n payment_order_id: { type: 'string|absent', description: 'Only in pay_per_call mode (echoes the request)' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife book --quote-id qte_01HZXD --vehicle-class Sedan --price-amount 42.50 --passenger-name \"Alice\" --passenger-phone +14155551234 --idempotency-key book-123',\r\n output_summary: 'Returns ride_id. Use ride_id in `ride-elife get` to poll status.',\r\n },\r\n error_recovery: {\r\n QUOTE_EXPIRED: \"Re-invoke 'quote' for a fresh quote_id, then retry 'book' with the SAME --idempotency-key.\",\r\n BILLING_MODE_MISMATCH: 'Check Developer.billing_mode. pay_per_call requires --payment-order-id; monthly_settlement forbids it.',\r\n PAYMENT_ORDER_NOT_PAID: 'Wait for the payment order status=PAID, then retry with the SAME --idempotency-key.',\r\n PAYMENT_ORDER_ALREADY_CONSUMED: 'Create a new payment order, then retry with the new payment-order-id and a NEW --idempotency-key.',\r\n ACCOUNT_INSUFFICIENT_BALANCE: 'Top up the settlement account (offline) or pick a cheaper vehicle_class, then retry.',\r\n BOOKING_FAILED: 'elife rejected after settlement. The message contains a ref: for manual reconciliation. Do NOT auto-retry.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/**\r\n * `ride-elife create-order` schema (ride-network-token-direct-charge R11.1).\r\n * Write op (W/Y). Lock-only first step of the two-step network-token flow:\r\n * locks the fare + returns the authoritative `order_ref`, and does NOT charge\r\n * or call eLife. Carries the SAME trip/quote/passenger/surcharge context as\r\n * `book` MINUS every payment credential — funding is deferred to `pay-order`.\r\n */\r\nexport const rideCreateOrderSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'create-order',\r\n description:\r\n 'Lock a ride fare without charging (status AWAITING_PAYMENT). Returns the authoritative order_ref to bind as the network token external_transaction_id, then settle with pay-order. No payment credentials here — funding happens in pay-order',\r\n flags: {\r\n 'quote-id': { type: 'string', required: true, description: 'Quote id from quote response (vehicle_classes[].price.quote_id)' },\r\n 'vehicle-class': { type: 'string', required: true, description: 'Vehicle class: Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\r\n 'price-amount': { type: 'float', required: true, description: 'Fare in decimal currency units (NOT cents), from the quote' },\r\n 'price-currency': { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'passenger-name': { type: 'string', required: true, description: 'Passenger full name' },\r\n 'passenger-phone': { type: 'string', required: true, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\r\n 'passenger-email': { type: 'string', required: true, description: 'Passenger email (persisted at lock; eLife needs it when pay-order creates the ride)' },\r\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\r\n 'special-requests': { type: 'string', required: false, description: 'Free-text special requests or notes' },\r\n 'pickup-lat': { type: 'float', required: false, description: 'Pickup latitude (must match the quote)', constraints: '-90 to 90' },\r\n 'pickup-lng': { type: 'float', required: false, description: 'Pickup longitude (must match the quote)', constraints: '-180 to 180' },\r\n 'pickup-name': { type: 'string', required: false, description: 'Pickup location name (must match the quote)' },\r\n 'dropoff-lat': { type: 'float', required: false, description: 'Dropoff latitude (must match the quote)', constraints: '-90 to 90' },\r\n 'dropoff-lng': { type: 'float', required: false, description: 'Dropoff longitude (must match the quote)', constraints: '-180 to 180' },\r\n 'dropoff-name': { type: 'string', required: false, description: 'Dropoff location name (must match the quote)' },\r\n 'pickup-time': { type: 'int|string', required: false, description: \"Epoch seconds or 'now' (must match the quote)\" },\r\n 'meet-and-greet': { type: 'bool', required: false, default: false, description: 'Enable meet & greet service' },\r\n 'meet-and-greet-price': { type: 'float', required: false, description: 'Meet & greet surcharge from the quote (meet_and_greet.price.amount)' },\r\n 'welcome-sign': { type: 'string', required: false, description: 'Welcome sign text (meet & greet)' },\r\n 'child-seat-count': { type: 'int', required: false, description: 'Number of child seats needed', constraints: '0 to 5' },\r\n 'infant-seat-count': { type: 'int', required: false, description: 'Number of infant seats needed', constraints: '0 to 5' },\r\n 'toddler-seat-count': { type: 'int', required: false, description: 'Number of toddler seats needed', constraints: '0 to 5' },\r\n 'arrival-flight-no': { type: 'string', required: false, description: 'Arrival flight number (airport pickup)' },\r\n 'arrival-airline': { type: 'string', required: false, description: 'Arrival airline name' },\r\n 'departure-flight-no': { type: 'string', required: false, description: 'Departure flight number (airport dropoff)' },\r\n 'departure-airline': { type: 'string', required: false, description: 'Departure airline name' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Authoritative order_ref (rio_…, = order document _id). Bind it as the network token external_transaction_id and pass it to pay-order' },\r\n status: { type: 'string', description: 'AWAITING_PAYMENT after a successful lock' },\r\n payment_status: { type: 'string', description: 'PENDING after lock (funds untouched)' },\r\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride; false = realtime' },\r\n order_type: { type: 'string', description: \"'realtime' or 'airport'\" },\r\n price: { type: 'object', description: '{ amount, currency, quote_id } — the authoritative amount + currency the token must match' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife create-order --quote-id qte_01HZXD --vehicle-class Sedan --price-amount 42.50 --passenger-name \"Alice\" --passenger-phone +14155551234 --passenger-email alice@example.com --idempotency-key ride-create-123',\r\n output_summary:\r\n 'Returns order_id (the order_ref). Bind it as the token external_transaction_id, mint the token for price.amount, then settle with `ride-elife pay-order --order-id <order_ref>`.',\r\n },\r\n error_recovery: {\r\n QUOTE_EXPIRED: \"Re-invoke 'quote' for a fresh quote_id, then retry 'create-order' with the SAME --idempotency-key.\",\r\n VEHICLE_CLASS_MISMATCH: 'The vehicle-class does not match the quote. Re-quote and pass the exact vehicle_class back.',\r\n PRICE_MISMATCH: 'The submitted total does not equal the authoritative fare. Re-quote and pass price-amount from the fresh quote.',\r\n IDEMPOTENCY_CONFLICT: 'Same --idempotency-key reused with different order params. Use a fresh idempotency-key.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/**\r\n * `ride-elife pay-order` schema (ride-network-token-direct-charge\r\n * R11.2/R11.4/R11.5). Write op (W/Y). Settlement second step of the two-step\r\n * network-token flow: charges the locked AWAITING_PAYMENT order and creates the\r\n * ride upstream, pushing it to PAID / SETTLED. Funds move HERE, not in\r\n * create-order. Exactly one of --payment-token-id / --payment-method-id is\r\n * required (mutually exclusive) — both missing or both present is rejected\r\n * locally as PARAM_INVALID before any request is sent.\r\n */\r\nexport const ridePayOrderSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'pay-order',\r\n description:\r\n 'Settle a locked ride order created by create-order. Charging happens in this step (create-order only locks the fare and moves no money). Provide EXACTLY ONE of --payment-token-id (network-token direct charge — the main path; charge(order_id=order_ref) triggers strict order↔token binding) or --payment-method-id (EVO bound-card fallback); both missing or both present is rejected as PARAM_INVALID before any request. The amount/currency are NOT accepted here — the platform settles at the order-locked authoritative amount and the token minted amount. On success the order becomes status=PAID / payment_status=SETTLED',\r\n flags: {\r\n 'order-id': {\r\n type: 'string',\r\n required: true,\r\n description: 'The authoritative order_ref (rio_…) from create-order.response.order_id to settle',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: 'conditional',\r\n description:\r\n 'Network-token id (UnionPay/Visa) for the direct-charge main path. Bind order_ref as its external_transaction_id first. Exactly one of --payment-token-id / --payment-method-id is required (mutually exclusive)',\r\n },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: 'conditional',\r\n description:\r\n 'Bound-card id to charge via EVO preauth+capture (fallback path). Exactly one of --payment-token-id / --payment-method-id is required (mutually exclusive)',\r\n },\r\n 'authorized-merchant-trans-id': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Resume a 3DS challenge: merchant trans id of an already-authorised EVO preauth returned by a prior AUTHENTICATION_REQUIRED response',\r\n },\r\n 'evo-explicit': {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description:\r\n '[方案 B/R16] Explicit opt-in to settle this pay_per_call ride via the EVO bound-card fallback rail. Set true ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side. Ignored for monthly_settlement and on the payment-token-id direct-charge path.',\r\n },\r\n authenticate: {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description:\r\n 'Opt-in to require cardholder 3DS on the network-token direct charge (payment-token-id, EVO/Mastercard). On step-up the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume via authorized-charge-no. Default off = frictionless. Ignored on the EVO preauth path and for UnionPay/Visa.',\r\n },\r\n 'return-url': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Optional 3DS/passkey return URL for the network-token authenticate path; falls back to the platform EVO_3DS_RETURN_URL.',\r\n },\r\n 'authorized-charge-no': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Resume a network-token 3DS challenge: charge_no from a prior AUTHENTICATION_REQUIRED response (settled via resume_token). Relaxes the exactly-one-credential rule (continuation, not a fresh charge).',\r\n },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n ...PRICE_ANNOTATION_FLAGS,\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Authoritative order_ref (rio_…, = order document _id) that was settled' },\r\n ride_id: { type: 'string|int', description: 'eLife upstream ride id, assigned once create_ride succeeds — use for `ride-elife get`' },\r\n status: { type: 'string', description: 'PAID after a successful settlement' },\r\n payment_status: { type: 'string', description: 'SETTLED after a successful network-token direct charge' },\r\n payment_channel: { type: 'string', description: \"'upi_agent' for the network-token direct-charge path\" },\r\n price: { type: 'object', description: '{ amount, currency, quote_id } — the authoritative amount the token matched' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife pay-order --order-id rio_01HZXD --payment-token-id ntk_01J2ABC --idempotency-key ride-pay-123',\r\n output_summary:\r\n 'Settles the order via network-token direct charge and creates the ride. Returns order_id + ride_id; the order becomes status=PAID / payment_status=SETTLED. Poll `ride-elife get --order-id <ride_id>` for driver dispatch.',\r\n },\r\n error_recovery: {\r\n PARAM_INVALID:\r\n 'Provide EXACTLY ONE of --payment-token-id or --payment-method-id (both missing or both present is invalid), and a non-empty --order-id.',\r\n TOKEN_ORDER_MISMATCH:\r\n \"The token's external_transaction_id is not this order_ref. Mint a token bound to THIS order_ref (external_transaction_id = order_ref) and retry; no funds moved.\",\r\n RESOURCE_STATE_INVALID:\r\n 'The order is not in AWAITING_PAYMENT (it may already be PAID or CANCELLED). Check status via get; do NOT retry pay-order.',\r\n RIDE_NOT_FOUND: 'No order for this --order-id. Verify it is the order_ref returned by create-order. Do NOT retry.',\r\n QUOTE_EXPIRED:\r\n \"The quote expired before settlement. Re-quote; if the authoritative price is unchanged retry pay-order with the SAME order_ref + SAME token and a NEW --idempotency-key, otherwise create a new order.\",\r\n BOOKING_FAILED:\r\n 'eLife create_ride failed after a successful charge; the charge was reversed and the order stays AWAITING_PAYMENT. Retry with a NEW --idempotency-key.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/** `ride-elife get` schema (§4.4.1.3 get schema). Read-only, supports `--watch`. */\r\nexport const rideGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'get',\r\n description: 'Retrieve a ride order status by id; with --watch, poll until a terminal status',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'The numeric ride_id (e.g. 4112961) — use the `ride_id` field from book/list-orders responses, NOT the rio_... order_id' },\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll until a terminal status, emitting one NDJSON line per update' },\r\n 'watch-interval': { type: 'int', required: false, default: DEFAULT_WATCH_INTERVAL_SECONDS, description: 'Seconds between polls when --watch is set' },\r\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll before giving up' },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Ride identifier' },\r\n status: { type: 'string', description: 'Pending / Accepted / On my way / Waiting / On board / At destination / Rejected / Cancelled / Customer no show / Driver no show' },\r\n source: { type: 'string', description: \"'local_cache' when served from the local fallback; 'mock' in sandbox\" },\r\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride' },\r\n from_location: { type: 'object', description: 'Pickup { lat, lng, name, address } (v3 snake_case, NOT elife from/to)' },\r\n to_location: { type: 'object', description: 'Dropoff { lat, lng, name, address }' },\r\n pickup_time: { type: 'int|string', description: 'Pickup time' },\r\n vehicle_class: { type: 'string|null', description: 'Vehicle class' },\r\n price: { type: 'object', description: '{ amount, currency, quote_id }' },\r\n final_amount: { type: 'float|null', description: 'Final settled fare (realtime, after final-fare settlement)' },\r\n final_settlement_status: { type: 'string', description: 'pending / settled / no_adjustment / settlement_pending / not_applicable' },\r\n driver: { type: 'object|null', description: '{ name, phone_number } — available after a driver is assigned' },\r\n vehicle: { type: 'object|null', description: '{ make, model, color, license_plate, image_url } — available after a driver is assigned' },\r\n created_at: { type: 'string', description: 'Order creation time' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife get --order-id EL-20260527-1023456',\r\n output_summary:\r\n 'Returns current status and driver/vehicle info. Terminal statuses: At destination, Cancelled, Rejected, Customer no show, Driver no show.',\r\n },\r\n polling: {\r\n recommended_interval_seconds: DEFAULT_WATCH_INTERVAL_SECONDS,\r\n terminal_statuses: [...TERMINAL_STATUSES],\r\n in_progress_statuses: ['Pending', 'Accepted', 'On my way', 'Waiting', 'On board'],\r\n field_availability: {\r\n driver: \"Populated from status 'Accepted' onwards (after a driver is dispatched). Null in 'Pending'.\",\r\n vehicle: \"Populated from status 'Accepted' onwards. Null in 'Pending'.\",\r\n },\r\n },\r\n error_recovery: {\r\n VEHICLE_UNAVAILABLE: 'Order not found. Verify --order-id is the ride_id from book. Do NOT retry.',\r\n BOOKING_FAILED: 'Transient elife error. Retry once after 5s.',\r\n },\r\n};\r\n\r\n/** `ride-elife cancel` schema (§4.4.1.3 cancel schema). Write op (W/Y). */\r\nexport const cancelSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'cancel',\r\n description: 'Cancel a ride order by id (a cancellation fee may apply depending on ride status)',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'The numeric ride_id (e.g. 4112961) to cancel — use the `ride_id` field from book/list-orders responses, NOT the rio_... order_id' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Cancelled ride id' },\r\n ride_stat: { type: 'string', description: \"Status after cancellation (typically 'Cancelled')\" },\r\n cancellation: {\r\n type: 'object|null',\r\n description: 'Cancellation details',\r\n properties: {\r\n cancellation_fee: { type: 'float', description: 'Fee charged for cancellation' },\r\n reversal_amount: { type: 'float', description: 'Amount reversed/refunded' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code' },\r\n },\r\n },\r\n refund_amount: { type: 'float', description: 'Amount credited back to the settlement balance (paid − cancellation_fee)' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife cancel --order-id EL-20260527-1023456 --idempotency-key cancel-456',\r\n output_summary: 'Returns cancellation fee and refund amount.',\r\n },\r\n error_recovery: {\r\n CANCELLATION_NOT_ALLOWED: 'The ride is in a non-cancellable state. Do NOT retry; query status with `ride-elife get`.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/**\r\n * `ride-elife update` schema (elife-capability-parity). Write op (W/Y).\r\n *\r\n * Flag names MUST stay identical to `verbs.update.flags` in ride-elife.json —\r\n * `scripts/check_ride_elife_schema.py` Property 11 diffs the two sets.\r\n *\r\n * No fare flags here, deliberately. The platform holds a pre-authorization and a\r\n * ledger entry made at the booked amount, and nothing on the update path re-checks\r\n * the fare the way book does (VEHICLE_CLASS_MISMATCH against the monthly quote, the\r\n * surcharge check against Quote_Cache). Exposing quote-id / vehicle-class / price-*\r\n * would let an agent produce an order where upstream charges the new fare and the\r\n * platform still has the old one. Cancel and book again to change the fare.\r\n */\r\nexport const rideUpdateSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'update',\r\n description:\r\n 'Modify an existing ride booking: trip details (time / route / flight info) and/or passenger details. Fare changes are rejected — cancel and book again instead',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'The numeric ride_id (e.g. 4112961) to modify — use the `ride_id` field from book/list-orders responses, NOT the rio_... order_id' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n },\r\n 'pickup-lat': { type: 'float', required: false, description: 'New pickup latitude', constraints: '-90 to 90' },\r\n 'pickup-lng': { type: 'float', required: false, description: 'New pickup longitude', constraints: '-180 to 180' },\r\n 'pickup-name': { type: 'string', required: false, description: 'New pickup location name' },\r\n 'dropoff-lat': { type: 'float', required: false, description: 'New dropoff latitude', constraints: '-90 to 90' },\r\n 'dropoff-lng': { type: 'float', required: false, description: 'New dropoff longitude', constraints: '-180 to 180' },\r\n 'dropoff-name': { type: 'string', required: false, description: 'New dropoff location name' },\r\n 'pickup-time': { type: 'int|string', required: false, description: \"New pickup time: epoch seconds or 'now'\" },\r\n 'welcome-sign': { type: 'string', required: false, description: 'New welcome sign text (meet & greet)' },\r\n 'arrival-flight-no': { type: 'string', required: false, description: 'New arrival flight number' },\r\n 'arrival-airline': { type: 'string', required: false, description: 'New arrival airline name' },\r\n 'departure-flight-no': { type: 'string', required: false, description: 'New departure flight number' },\r\n 'departure-airline': { type: 'string', required: false, description: 'New departure airline name' },\r\n 'service-area-id': { type: 'string', required: false, description: 'Service area id, when the upstream requires re-scoping the ride' },\r\n 'passenger-name': { type: 'string', required: false, description: 'New passenger full name (passing any passenger-* flag triggers a passenger update)' },\r\n 'passenger-phone': { type: 'string', required: false, description: 'New passenger phone in E.164 format (e.g. +14155551234)' },\r\n 'passenger-email': { type: 'string', required: false, description: 'New passenger email' },\r\n 'luggage-count': { type: 'int', required: false, description: 'New luggage count' },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Modified ride id' },\r\n status: { type: 'string', description: \"Result status, 'updated' when the modification was applied\" },\r\n ride_updated: { type: 'bool', description: 'true when trip-side fields were sent upstream' },\r\n passenger_updated: { type: 'bool', description: 'true when passenger fields were sent upstream' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli ride-elife update --order-id 4112961 --pickup-time 1780000000 --idempotency-key update-789',\r\n output_summary: 'Returns which sides were applied (ride_updated / passenger_updated).',\r\n },\r\n error_recovery: {\r\n PARAM_INVALID: 'No modifiable field was supplied. Pass at least one trip field or one passenger-* flag.',\r\n RIDE_NOT_FOUND: 'The ride does not exist or belongs to another developer. Verify --order-id is the ride_id from book.',\r\n CANCELLATION_NOT_ALLOWED: 'The ride is past the modifiable window. Query with `ride-elife get`; cancel and re-book if the user needs a different trip.',\r\n UPSTREAM_ERROR: 'Partial update: one side applied upstream, the other failed (see data.partial_update). The upstream has NO rollback — re-issue update for the failed side ONLY, then confirm with `ride-elife get`.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n },\r\n};\r\n\r\n/**\r\n * `ride-elife trip-status` schema (elife-capability-parity). Read-only.\r\n *\r\n * Flag names MUST stay identical to `verbs.trip-status.flags` in ride-elife.json.\r\n */\r\nexport const rideTripStatusSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'trip-status',\r\n description: 'Query the status and driver location points of a single leg of a multi-leg ride',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'The numeric ride_id (e.g. 4112961) — use the `ride_id` field from book/list-orders responses' },\r\n 'trip-no': { type: 'int', required: false, default: 1, description: '1-based leg index; defaults to the first leg' },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Ride identifier' },\r\n trip_no: { type: 'int', description: 'Leg number this status refers to' },\r\n status: { type: 'string', description: 'Leg status, same vocabulary as `ride-elife get`' },\r\n points: {\r\n type: 'array|null',\r\n description: 'Driver location points for this leg',\r\n items: { lat: { type: 'float' }, lng: { type: 'float' }, utc_timestamp: { type: 'int' } },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife trip-status --order-id 4112961 --trip-no 2',\r\n output_summary: 'Returns the leg status plus its driver location points.',\r\n },\r\n polling: {\r\n recommended_interval_seconds: DEFAULT_WATCH_INTERVAL_SECONDS,\r\n terminal_statuses: [...TERMINAL_STATUSES],\r\n in_progress_statuses: ['Pending', 'Accepted', 'On my way', 'Waiting', 'On board'],\r\n field_availability: {\r\n points: 'Populated only after the driver starts moving on this leg; empty or null before that.',\r\n },\r\n },\r\n error_recovery: {\r\n RIDE_NOT_FOUND: 'The ride or the requested leg does not exist. Confirm the ride has multiple legs via `ride-elife get` first.',\r\n UPSTREAM_ERROR: 'Upstream Trip Status errored. Legs only exist after a driver is dispatched — use get.response.next_trip_no and only query once the ride has started. As of 2026-08 the sandbox returns 502 here for rides with no dispatched legs regardless of --trip-no; fall back to `ride-elife get`.',\r\n BOOKING_FAILED: 'Transient upstream error. Retry once after 5s, or fall back to `ride-elife get` for whole-ride status.',\r\n },\r\n};\r\n\r\n// ── ride-elife callback-* (status-event forwarding to the caller's endpoint) ──\r\n\r\nconst RIDE_ORDER_ID_FLAG: FlagSchema = {\r\n type: 'string',\r\n required: true,\r\n description: 'The numeric ride_id returned by book (NOT the rio_... order_id)',\r\n};\r\nconst CALLBACK_IDEMPOTENCY_FLAG: FlagSchema = {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\r\n};\r\nconst CALLBACK_SUBSCRIPTION_FLAGS: Record<string, FlagSchema> = {\r\n 'callback-url': { type: 'string', required: true, description: 'https URL that receives status events; internal addresses are rejected by the platform' },\r\n adapter: { type: 'string', required: false, default: 'techtanium_v1', description: 'Outbound event shape' },\r\n 'signature-mode': { type: 'string', required: false, default: 'off', description: 'off / optional / required' },\r\n 'callback-api-key': { type: 'string', required: false, description: 'API key sent to your endpoint; omit to keep the stored one (never echoed back)' },\r\n 'rotate-secret': { type: 'bool', required: false, default: false, description: 'Issue a new signing secret; the old one stops verifying' },\r\n 'idempotency-key': CALLBACK_IDEMPOTENCY_FLAG,\r\n};\r\nconst CALLBACK_SUBSCRIPTION_RESPONSE = {\r\n callback_url: { type: 'string', description: 'Registered destination' },\r\n adapter: { type: 'string', description: 'Outbound event shape' },\r\n signature_mode: { type: 'string', description: 'off / optional / required' },\r\n status: { type: 'string', description: 'Registration status' },\r\n callback_secret: { type: 'string', description: 'Signing secret — present ONLY in the set response that issued it; store it, it cannot be read back' },\r\n};\r\nconst CALLBACK_ERRORS = {\r\n RIDE_NOT_FOUND: 'The ride is not yours or does not exist; check the ride_id from book/list-orders.',\r\n PARAM_INVALID: 'Fix the flag named in the message (https URL, signature-mode, ranges) and retry.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\r\n};\r\n\r\n/** `ride-elife callback-set` schema. Write op: per-ride callback destination. */\r\nexport const rideCallbackSetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-set',\r\n description: \"Register (or update) where one ride's status events are forwarded; takes priority over the default\",\r\n flags: { 'order-id': RIDE_ORDER_ID_FLAG, ...CALLBACK_SUBSCRIPTION_FLAGS },\r\n response: { ride_id: { type: 'string|int', description: 'Ride id' }, order_id: { type: 'string', description: 'rio_... order id' }, ...CALLBACK_SUBSCRIPTION_RESPONSE },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife callback-set --order-id 4112961 --callback-url https://example.com/ride-events --idempotency-key cb-1',\r\n output_summary: 'Returns the registration; the first registration also returns callback_secret once.',\r\n },\r\n error_recovery: CALLBACK_ERRORS,\r\n};\r\n\r\n/** `ride-elife callback-get` schema. Read-only. */\r\nexport const rideCallbackGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-get',\r\n description: \"Show one ride's callback registration (the signing secret is never returned)\",\r\n flags: { 'order-id': RIDE_ORDER_ID_FLAG },\r\n response: { ride_id: { type: 'string|int', description: 'Ride id' }, order_id: { type: 'string', description: 'rio_... order id' }, ...CALLBACK_SUBSCRIPTION_RESPONSE },\r\n example: { command: 'agenzo-merchant-cli ride-elife callback-get --order-id 4112961', output_summary: 'Returns the registration without the secret.' },\r\n error_recovery: { RIDE_NOT_FOUND: CALLBACK_ERRORS.RIDE_NOT_FOUND },\r\n};\r\n\r\n/** `ride-elife callback-default-set` schema. Write op: developer-wide fallback. */\r\nexport const rideCallbackDefaultSetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-default-set',\r\n description: 'Register (or update) the developer-wide fallback used by rides that have no callback of their own',\r\n flags: CALLBACK_SUBSCRIPTION_FLAGS,\r\n response: { developer_id: { type: 'string', description: 'Owner of the default' }, ...CALLBACK_SUBSCRIPTION_RESPONSE },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife callback-default-set --callback-url https://example.com/ride-events --idempotency-key cbd-1',\r\n output_summary: 'Configure once so events for rides booked later are never dropped.',\r\n },\r\n error_recovery: { PARAM_INVALID: CALLBACK_ERRORS.PARAM_INVALID, PARAM_IDEMPOTENCY_KEY_REQUIRED: CALLBACK_ERRORS.PARAM_IDEMPOTENCY_KEY_REQUIRED },\r\n};\r\n\r\n/** `ride-elife callback-default-get` schema. Read-only. */\r\nexport const rideCallbackDefaultGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-default-get',\r\n description: 'Show the developer-wide fallback callback (the signing secret is never returned)',\r\n flags: {},\r\n response: { developer_id: { type: 'string', description: 'Owner of the default' }, ...CALLBACK_SUBSCRIPTION_RESPONSE },\r\n example: { command: 'agenzo-merchant-cli ride-elife callback-default-get', output_summary: 'Returns the default without the secret.' },\r\n};\r\n\r\n/** `ride-elife callback-deliveries` schema. Read-only. */\r\nexport const rideCallbackDeliveriesSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-deliveries',\r\n description: \"List one ride's callback forwarding records (pending / delivered / dead)\",\r\n flags: {\r\n 'order-id': RIDE_ORDER_ID_FLAG,\r\n limit: { type: 'int', required: false, default: 50, description: 'Page size 1-100' },\r\n offset: { type: 'int', required: false, default: 0, description: 'Records to skip' },\r\n },\r\n response: {\r\n ride_id: { type: 'string|int', description: 'Ride id' },\r\n limit: { type: 'int', description: 'Page size used' },\r\n offset: { type: 'int', description: 'Offset used' },\r\n count: { type: 'int', description: 'Records in this page' },\r\n deliveries: { type: 'array', description: 'Forwarding records: event_id, status, attempts, last_error, timestamps' },\r\n },\r\n example: { command: 'agenzo-merchant-cli ride-elife callback-deliveries --order-id 4112961', output_summary: 'Shows what was forwarded and where it stalled.' },\r\n error_recovery: { RIDE_NOT_FOUND: CALLBACK_ERRORS.RIDE_NOT_FOUND, PARAM_INVALID: CALLBACK_ERRORS.PARAM_INVALID },\r\n};\r\n\r\n/** `ride-elife callback-replay` schema. Write op: requeue dead/failed records. */\r\nexport const rideCallbackReplaySchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'callback-replay',\r\n description: \"Requeue one ride's dead (or failed) callback records; delivered records are never re-sent\",\r\n flags: {\r\n 'order-id': RIDE_ORDER_ID_FLAG,\r\n 'event-id': { type: 'string', required: false, description: 'Requeue only this record (default: all dead records)' },\r\n 'include-failed': { type: 'bool', required: false, default: false, description: 'Also requeue pending records that already failed' },\r\n 'reset-attempts': { type: 'bool', required: false, default: false, description: 'Reset the retry counter of requeued records' },\r\n 'idempotency-key': CALLBACK_IDEMPOTENCY_FLAG,\r\n },\r\n response: {\r\n ride_id: { type: 'string', description: 'Ride id' },\r\n requeued: { type: 'int', description: 'Number of records set back to pending' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife callback-replay --order-id 4112961 --idempotency-key rp-1',\r\n output_summary: 'Requeues dead records; the delivery worker re-sends them on its next pass.',\r\n },\r\n error_recovery: CALLBACK_ERRORS,\r\n};\r\n\r\n/** `ride-elife list-orders` schema (§4.4.1.3 list-orders schema). Read-only. */\r\nexport const listOrdersSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: NOUN,\r\n verb: 'list-orders',\r\n description: 'List previously placed ride orders with optional filters and pagination',\r\n flags: {\r\n status: { type: 'string', required: false, description: 'Filter by ride status (case-sensitive server casing)' },\r\n 'order-type': { type: 'string', required: false, description: 'Filter by order type (e.g. realtime / airport)' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n page: { type: 'int', required: false, default: 1, description: 'Page number', constraints: '>= 1' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page', constraints: '>= 1' },\r\n },\r\n response: {\r\n orders: {\r\n type: 'array',\r\n description: 'List of ride orders (slim list-item shape)',\r\n items: {\r\n order_id: { type: 'string', description: 'Internal order id' },\r\n member_id: { type: 'string|null', description: 'End-user this order is attributed to; null when unattributed' },\r\n ride_id: { type: 'string', description: 'Ride id (same as ride_id from book)' },\r\n status: { type: 'string', description: 'Current ride status' },\r\n vehicle_class: { type: 'string', description: 'Vehicle class' },\r\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport, false = realtime' },\r\n scheduled_at: { type: 'string', description: 'ISO 8601 datetime; empty for realtime orders' },\r\n price_amount: { type: 'float|null', description: 'Price in decimal currency units (NOT cents)' },\r\n final_amount: { type: 'float|null', description: 'Final settled amount' },\r\n price_currency: { type: 'string', description: 'ISO 4217 currency code' },\r\n payment_status: { type: 'string', description: 'Payment status' },\r\n final_settlement_status: { type: 'string', description: 'pending / settled / no_adjustment / settlement_pending / not_applicable' },\r\n cancellation_fee: { type: 'float|null', description: 'Cancellation fee for cancelled orders; null otherwise' },\r\n provider: { type: 'string', description: 'Service provider (elife)' },\r\n created_at: { type: 'string|null', description: 'Order creation time (ISO 8601)' },\r\n updated_at: { type: 'string|null', description: 'Last update time (ISO 8601)' },\r\n },\r\n },\r\n total: { type: 'int', description: 'Total matching orders' },\r\n page: { type: 'int', description: 'Current page' },\r\n page_size: { type: 'int', description: 'Items per page' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli ride-elife list-orders --status Pending --page 1 --page-size 10',\r\n output_summary: 'Returns a paginated list of ride orders with status and amount info.',\r\n },\r\n error_recovery: {\r\n INTERNAL_ERROR: 'Transient backend error. Retry once after a short delay.',\r\n PARAM_INVALID: 'Ensure --page / --page-size are positive integers, then retry.',\r\n },\r\n};\r\n\r\n// ============================================================\r\n// Hotel-redaug verb schemas\r\n// ============================================================\r\n//\r\n// Flags / response are kept aligned with each command's ACTUAL flags\r\n// (requirements 2.1 / 3.1 / 4.1 / 5.1 / 6.1 / 7.1 / 8.1 / 9.1) and the live\r\n// response types in `types/hotel.ts` (NOT the capability schema where they\r\n// diverge). Three deliberate reconciliations vs the capability schema:\r\n// - `order_status` is the std STRING on the wire; `get` also carries the\r\n// integer `order_status_code` (2/3/4/5). There is NO `order_status_std`.\r\n// - `cancel` models both the confirmed and accepted-but-pending shapes.\r\n// - `checkout` returns `{ order_id, task_order_code, apply_status,\r\n// checkout_status }`.\r\n// Amounts are decimal currency units paired with a currency code (never minor\r\n// units). `error_recovery` guidance is taken from the capability schema's\r\n// `error_recovery[code].agent_action`, keyed on the REAL wire codes\r\n// (`HOTEL_ORDER_NOT_FOUND` / `CHECKOUT_TASK_NOT_FOUND`, not the agent-facing\r\n// `ORDER_NOT_FOUND` / `TASK_NOT_FOUND` aliases).\r\n//\r\n// `--api-key`, `--yes` and `--format` are cross-cutting flags resolved by the\r\n// program/top-level handler; like the ride-elife schemas, they are intentionally\r\n// omitted from the per-verb `flags` block (which declares only domain flags).\r\n\r\n/** `hotel-redaug search` schema. Read-only, supports both location branches. */\r\nexport const hotelSearchSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'search',\r\n description:\r\n 'Search hotels near a coordinate OR within a destination for the given stay dates. Two location branches: --destination-id (from find-destination) XOR --lat/--lng (geocoded by the Agent backend). Exactly one branch must be supplied',\r\n flags: {\r\n 'destination-id': { type: 'string', required: 'conditional', description: 'Destination ID from find-destination (alternative to --lat/--lng)', constraints: 'Exactly one location branch: --destination-id XOR (--lat + --lng)' },\r\n lat: { type: 'float', required: 'conditional', description: 'Latitude of the search center (geocoded by the Agent backend, not by the CLI)', constraints: '-90 to 90; requires --lng; mutually exclusive with --destination-id' },\r\n lng: { type: 'float', required: 'conditional', description: 'Longitude of the search center (geocoded by the Agent backend, not by the CLI)', constraints: '-180 to 180; requires --lat; mutually exclusive with --destination-id' },\r\n distance: { type: 'int', required: false, default: 20, description: 'Search radius in kilometers', constraints: 'Agent infers from phrasing — small (2-5) for \"right next to a spot\", larger (15-30) for a whole city. Do NOT ask the user for a number' },\r\n 'check-in': { type: 'string', required: true, description: 'Check-in date', constraints: 'YYYY-MM-DD, today or later' },\r\n 'check-out': { type: 'string', required: true, description: 'Check-out date', constraints: 'YYYY-MM-DD, strictly after check-in' },\r\n adults: { type: 'int', required: false, default: 2, description: 'Number of adults', constraints: '1-9 per room' },\r\n children: { type: 'int', required: false, default: 0, description: 'Number of children' },\r\n 'room-num': { type: 'int', required: false, default: 1, description: 'Number of rooms requested' },\r\n star: { type: 'int', required: false, description: 'Minimum hotel star rating filter', constraints: 'Enum 3 / 4 / 5' },\r\n keyword: { type: 'string', required: false, description: 'Optional hotel name keyword to narrow results' },\r\n 'price-min': { type: 'float', required: false, description: 'Minimum price filter' },\r\n 'price-max': { type: 'float', required: false, description: 'Maximum price filter' },\r\n 'sort-by': { type: 'string', required: false, description: 'Sort field' },\r\n page: { type: 'int', required: false, default: 1, description: 'Page number', constraints: '>= 1' },\r\n 'page-size': { type: 'int', required: false, default: 10, description: 'Results per page', constraints: '>= 1' },\r\n 'hotel-facility-codes': { type: 'string', required: false, description: 'Hotel facility codes (comma-separated or JSON array, from hotel-filters)' },\r\n 'room-facility-codes': { type: 'string', required: false, description: 'Room facility codes (comma-separated or JSON array, from hotel-filters)' },\r\n 'hotel-brand-codes': { type: 'string', required: false, description: 'Hotel brand codes (comma-separated or JSON array, from hotel-filters)' },\r\n 'plate-codes': { type: 'string', required: false, description: 'Plate codes (comma-separated or JSON array, from hotel-filters)' },\r\n 'hotel-label-ids': { type: 'string', required: false, description: 'Hotel label IDs (comma-separated or JSON array, from hotel-filters)' },\r\n 'hotel-sub-category-ids': { type: 'string', required: false, description: 'Hotel sub-category IDs (comma-separated or JSON array, from hotel-filters)' },\r\n },\r\n response: {\r\n hotels: {\r\n type: 'array',\r\n description: 'Matching hotels for the location and dates. Empty when nothing was found (rendered as a successful empty result, not an error).',\r\n items: {\r\n hotel_id: { type: 'string|int', description: 'Opaque hotel identifier. Pass verbatim to quote --hotel-id. Do NOT interpret.' },\r\n hotel_name: { type: 'string', description: 'Hotel name.' },\r\n star: { type: 'int|null', description: 'Star rating.' },\r\n address: { type: 'string|null', description: 'Hotel address.' },\r\n distance_km: { type: 'float|null', description: 'Approximate distance from the search center, in km.' },\r\n city_name: { type: 'string|null', description: 'City name.' },\r\n district_name: { type: 'string|null', description: 'District name.' },\r\n business_name: { type: 'string|null', description: 'Business area name.' },\r\n score: { type: 'float|null', description: 'Hotel score/rating.' },\r\n main_image: { type: 'string|null', description: 'Main hotel image URL.' },\r\n lowest_price: {\r\n type: 'object|null',\r\n description: 'Indicative nightly starting price (not the bookable total — get the real price from quote).',\r\n properties: {\r\n amount: { type: 'float', description: 'Starting price in DECIMAL units (NOT cents).' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code.' },\r\n },\r\n },\r\n },\r\n },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli hotel-redaug search --destination-id D12345 --check-in 2026-07-04 --check-out 2026-07-05 --adults 2',\r\n output_summary: 'Returns hotels[] for the location. Pick one and use hotels[].hotel_id in hotel-redaug quote. Alternatively use --lat/--lng instead of --destination-id.',\r\n },\r\n error_recovery: {\r\n NO_AVAILABILITY: 'No hotels near this coordinate for these dates. Widen --distance, try different dates, or have the Agent backend geocode a nearby area. As a last resort try another category=hotel service (see cross_service_recovery).',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff. Otherwise surface to user.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug quote` schema. Read-only. */\r\nexport const hotelQuoteSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'quote',\r\n description:\r\n 'Get real-time room types and bookable rates for one hotel and stay. Returns rates each carrying an opaque product_token and per-night price_items that must be passed verbatim to create-order. Run immediately before create-order — availability and prices change in real time',\r\n flags: {\r\n 'hotel-id': { type: 'string', required: true, description: 'Hotel chosen from search results (search.response.hotels[].hotel_id)' },\r\n 'check-in': { type: 'string', required: true, description: 'Check-in date (match search)', constraints: 'YYYY-MM-DD' },\r\n 'check-out': { type: 'string', required: true, description: 'Check-out date (match search)', constraints: 'YYYY-MM-DD, strictly after check-in' },\r\n adults: { type: 'int', required: false, default: 2, description: 'Adults per room (match search)' },\r\n children: { type: 'int', required: false, default: 0, description: 'Children per room (match search)' },\r\n 'room-num': { type: 'int', required: false, default: 1, description: 'Number of rooms (match search)' },\r\n nationality: { type: 'string', required: false, default: 'CN', description: 'Guest nationality (ISO country code). Affects rate eligibility for some hotels' },\r\n },\r\n response: {\r\n rates: {\r\n type: 'array',\r\n description: 'Bookable room+rate options. Empty when the hotel has no rooms for these dates (treat as NO_AVAILABILITY: re-quote another hotel or change dates).',\r\n items: {\r\n product_token: { type: 'string', description: 'Opaque token packing room/rate/supply identifiers. Pass verbatim to create-order --product-token. Do NOT interpret or reuse across quotes.' },\r\n room_name: { type: 'string', description: 'Room type name.' },\r\n rate_plan_name: { type: 'string|null', description: \"Rate plan name (e.g. 'Breakfast included, free cancellation').\" },\r\n breakfast: { type: 'int|null', description: 'Breakfast enum for the rate (-1=bed breakfast, 0=no breakfast, 1+=N breakfasts). Display only.' },\r\n free_cancellation: { type: 'bool|null', description: 'Whether this rate is currently in a free-cancellation window. Prefer when the user wants flexibility.' },\r\n total_price: {\r\n type: 'object',\r\n description: 'Total bookable price for the whole stay and room count.',\r\n properties: {\r\n amount: { type: 'float', description: 'Total price in DECIMAL units. Pass verbatim to create-order --total-amount.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code. Pass to create-order --currency.' },\r\n },\r\n },\r\n price_items: {\r\n type: 'array',\r\n description: 'Per-night price breakdown. Pass this array verbatim to create-order --price-items.',\r\n items: {\r\n sale_date: { type: 'string', description: 'Night date YYYY-MM-DD.' },\r\n sale_price: { type: 'float', description: 'Price for that night in DECIMAL units.' },\r\n breakfast_num: { type: 'int', description: 'Breakfast enum for that night (-1=bed breakfast, 0=no breakfast, 1+=N). Copy verbatim into create-order; never alter.' },\r\n },\r\n },\r\n },\r\n },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli hotel-redaug quote --hotel-id 10583772 --check-in 2026-08-20 --check-out 2026-08-21 --adults 2',\r\n output_summary: 'Returns rates[]. Use rates[].product_token, total_price.amount/currency and price_items[] in hotel-redaug create-order.',\r\n },\r\n error_recovery: {\r\n NO_AVAILABILITY: 'This hotel has no bookable rooms for these dates (upstream roomItems empty). Re-quote a different hotel from the search result, or re-search with other dates. Do NOT retry the same hotel/dates.',\r\n PRICE_CHANGED: 'Rates shifted since search. Use the prices returned here; do not reuse search lowest_price. No action other than informing the user if materially higher.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug create-order` schema. Write op (W/Y) — lock inventory, no charge. */\r\nexport const hotelCreateOrderSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'create-order',\r\n description:\r\n 'Create a hotel order WITHOUT charging any account (re-check availability + createOrder upstream), using a product_token and price_items from a recent quote. The order enters AWAITING_PAYMENT — no money is moved until pay-order. check-in/check-out, guest counts, total-amount and price-items must match the quote',\r\n flags: {\r\n 'product-token': { type: 'string', required: true, description: 'Chosen rate token from quote (quote.response.rates[].product_token). Pass verbatim' },\r\n 'total-amount': { type: 'float', required: true, description: 'Total price for the stay (quote.response.rates[].total_price.amount)', constraints: 'DECIMAL units (NOT cents), 0.01–999999999.99. Must equal the chosen rate total_price.amount' },\r\n currency: { type: 'string', required: true, description: 'ISO 4217 currency code from the chosen rate (quote.response.rates[].total_price.currency)', constraints: 'Exactly 3 uppercase letters' },\r\n 'price-items': { type: 'string', required: true, description: 'Per-night price breakdown from quote, copied verbatim (including breakfast_num)', constraints: 'JSON array of {sale_date, sale_price, breakfast_num}; copy breakfast_num verbatim from quote (-1/0/1+ are distinct breakfast products, never alter); else PARAM_INVALID' },\r\n 'check-in': { type: 'string', required: true, description: 'Check-in date (match quote)', constraints: 'YYYY-MM-DD' },\r\n 'check-out': { type: 'string', required: true, description: 'Check-out date (match quote)', constraints: 'YYYY-MM-DD, strictly after check-in' },\r\n 'room-num': { type: 'int', required: false, default: 1, description: 'Number of rooms (match quote)' },\r\n adults: { type: 'int', required: false, default: 2, description: 'Adults per room (match quote)', constraints: '1-20' },\r\n children: { type: 'int', required: false, default: 0, description: 'Children per room (match quote)', constraints: '0-10' },\r\n nationality: { type: 'string', required: false, default: 'CN', description: 'Guest nationality (match quote)' },\r\n 'guest-name': { type: 'string', required: true, description: 'Primary guest name', constraints: 'Use the name as the user gives it. If a supplier returns NAME_FORMAT_INVALID, re-collect in Latin letters and retry' },\r\n 'room-guests': { type: 'string', required: false, description: \"Per-room primary guests, listed in room order, for booking several rooms under different names. Omit it and every room reuses guest-name (backward compatible); guest-name stays required either way\", constraints: 'JSON array of {guest_name (non-empty string)}; room_index is optional and filled in from the array position (1-based, validated against room-num by the platform) — pass it explicitly only to override; else PARAM_INVALID' },\r\n 'contact-name': { type: 'string', required: true, description: 'Booking contact name (may equal guest-name)' },\r\n 'contact-phone': { type: 'string', required: true, description: 'Booking contact phone number', constraints: 'Digits; collect country code separately in --contact-country-code' },\r\n 'contact-country-code': { type: 'string', required: false, default: '86', description: \"Phone country calling code without '+'\" },\r\n 'contact-email': { type: 'string', required: false, description: 'Booking contact email' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'arrive-time': { type: 'string', required: false, description: 'Expected arrival time', constraints: 'HH:mm, hotel local time' },\r\n 'special-requests': { type: 'string', required: false, description: 'Free-text special requests (non-binding)' },\r\n tips: { type: 'string', required: false, description: \"FCG 客户自测点5 提示信息: the chosen quote rate's tips (tips[].tipsDetails[]) as a JSON array [{title,text}], captured at booking. Stored on the order for the order-detail page only; platform-local, not sent upstream\", constraints: 'JSON array of {title (string, optional), text (string, optional)}; else PARAM_INVALID' },\r\n cancellation: {\r\n type: 'string',\r\n required: false,\r\n description: 'Cancellation policy snapshot copied from the selected quote rate and stored on the order.',\r\n constraints: 'JSON object; else PARAM_INVALID',\r\n },\r\n 'hotel-timezone': {\r\n type: 'string',\r\n required: false,\r\n description: \"Hotel timezone from quote (for example 'UTC+8'), used to evaluate cancellation deadlines.\",\r\n },\r\n 'bed-type': {\r\n type: 'string',\r\n required: false,\r\n description: \"Product bed-type code from the chosen quote rate's beds[].code (e.g. 'L000000' King / '1000000' Queen). Forwarded verbatim to upstream createOrder bedType; upstream recommends passing the product-dimension bed type at booking.\",\r\n },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Optional bound-card id (pay_per_call / EVO path). When set, the platform settles this order by pre-authorizing + capturing on that specific bound card; omit to let billing_mode decide.',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'UPI Agent Pay only: payment token id from an already-completed UnionPay network-token capture (funds already charged). When set, the platform skips EVO preauth/capture and only locks the order.',\r\n },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Derive from business intent (e.g. hash(user_id + product_token + check_in)) and reuse the SAME key when retrying the same order creation',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Our order reference (coOrderCode). Use as --order-id in pay-order / get / cancel.' },\r\n fc_order_code: { type: 'string', description: 'Supplier order reference. Needed as --fc-order-code in cancel and checkout.' },\r\n total_amount: { type: 'float', description: 'Amount to be paid in pay-order (DECIMAL units). The order is locked in AWAITING_PAYMENT — no charge has been made.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code for the payment.' },\r\n },\r\n example: {\r\n command:\r\n `agenzo-merchant-cli hotel-redaug create-order --product-token <tok> --total-amount 10.00 --currency CNY --price-items '[{\"sale_date\":\"2026-08-20\",\"sale_price\":10.00,\"breakfast_num\":0}]' --check-in 2026-08-20 --check-out 2026-08-21 --adults 2 --guest-name \"Zhang San\" --contact-name \"Zhang San\" --contact-phone 13800138000 --idempotency-key create-h1n2`,\r\n output_summary: 'Returns {order_id, fc_order_code, total_amount, currency}. The order is AWAITING_PAYMENT (no charge). Use order_id as --order-id in pay-order to settle.',\r\n },\r\n error_recovery: {\r\n NO_AVAILABILITY: 'Availability vanished between quote and create-order. Re-quote the same hotel; if still empty, quote another hotel or change dates. Use a NEW idempotency-key for the new product_token.',\r\n PRICE_CHANGED: 'The price/price_items no longer match upstream. Re-quote to get fresh total_price and price_items, confirm the new price with the user, then create-order with the new values and a NEW idempotency-key.',\r\n NAME_FORMAT_INVALID: 'The supplier requires the guest name in a specific format (commonly Latin first/last name for international properties). Re-collect guest-name in Latin letters and retry with the SAME idempotency-key.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Add a unique --idempotency-key derived from business intent and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'The same idempotency-key was used with different parameters. Retry with the original parameters, or generate a NEW key for the new parameters.',\r\n UPSTREAM_ERROR: 'Transient upstream error during checkBooking or createOrder. Retry once after ~2s backoff with the SAME idempotency-key.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug pay-order` schema. Write op (W/Y) — settle a created order. */\r\nexport const hotelPayOrderSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'pay-order',\r\n description:\r\n 'Settle an existing AWAITING_PAYMENT order created by create-order. Charging happens in this step — platform create-order only locks inventory/price and moves no money (lock-then-pay). Optional payment credentials (--payment-method-id / --payment-token-id / --authorized-merchant-trans-id) are forwarded to the pay body; omit them to let the platform settle by billing_mode (monthly_settlement deducts credit; pay_per_call selects the developer default card / EVO preauth). Token wins over method id server-side. On EVO cardholder authentication the response is AUTHENTICATION_REQUIRED with a three_ds_url + merchant_trans_id; resume by re-calling pay-order with --authorized-merchant-trans-id. On success the order becomes PAID. Supports --watch to poll on PAYMENT_NOT_COMPLETED until PAID',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Order to settle (create-order.response.order_id).' },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Optional bound-card id to charge (pay_per_call / EVO preauth). Ignored for monthly_settlement and when payment-token-id is set.',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Optional network-token id (UnionPay/Visa). When set the platform settles via network-token direct charge instead of EVO preauth+capture. Wins over payment-method-id.',\r\n },\r\n 'authorized-merchant-trans-id': {\r\n type: 'string',\r\n required: false,\r\n description: 'Resume a 3DS challenge: merchant trans id of an already-authorised preauth returned by a prior AUTHENTICATION_REQUIRED response. Reuses that authorization instead of creating a new one (pay_per_call only).',\r\n },\r\n 'evo-explicit': {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description: '[方案 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set true ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side. Ignored for monthly_settlement and on the payment-token-id direct-charge path.',\r\n },\r\n authenticate: {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description: 'Opt-in to require cardholder 3DS on the network-token direct charge (payment-token-id, EVO/Mastercard). On step-up the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume via authorized-charge-no. Default off = frictionless. Ignored on the EVO preauth path and for UnionPay/Visa.',\r\n },\r\n 'return-url': {\r\n type: 'string',\r\n required: false,\r\n description: 'Optional 3DS/passkey return URL for the network-token authenticate path; falls back to the platform EVO_3DS_RETURN_URL.',\r\n },\r\n 'authorized-charge-no': {\r\n type: 'string',\r\n required: false,\r\n description: 'Resume a network-token 3DS challenge: charge_no from a prior AUTHENTICATION_REQUIRED response (settled via resume_token), then triggers upstream payOrder on success (pay_per_call only).',\r\n },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Derive from business intent (e.g. hash(order_id + attempt)) and reuse the SAME key when retrying the same payment',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n ...PRICE_ANNOTATION_FLAGS,\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll automatically on PAYMENT_NOT_COMPLETED until PAID or timeout. Each iteration emits one NDJSON line' },\r\n 'watch-interval': { type: 'int', required: false, default: 5, description: 'Seconds between poll attempts in --watch mode' },\r\n 'watch-timeout': { type: 'int', required: false, default: 300, description: 'Total seconds before giving up in --watch mode' },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Order reference.' },\r\n settlement_path: { type: 'string', description: \"Which billing path was used: 'monthly_settlement' or 'pay_per_call' (same tokens as billing_mode).\" },\r\n amount: { type: 'float', description: 'Settled amount in DECIMAL units.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code of the settlement.' },\r\n pay_status: { type: 'int', description: 'Upstream pay status (1 = paid). The order internal status is now PAID.' },\r\n settled_at: { type: 'string', description: 'ISO 8601 settlement timestamp. On idempotent replay, the original first settled_at is returned unchanged.' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli hotel-redaug pay-order --order-id hho_01KWC63Z5CD6CKBM33Q7SC2ZDT --idempotency-key pay-h1n2',\r\n output_summary: 'Settlement path is chosen server-side by billing_mode. monthly_settlement: deducts from the credit account, confirms with the supplier. Returns {order_id, settlement_path:\"monthly_settlement\", amount, currency, pay_status:1, settled_at}. Order becomes PAID. For pay_per_call the user must have already paid via EVO using the order_id as the merchantTransID; the same command settles it (settlement_path:\"pay_per_call\").',\r\n },\r\n error_recovery: {\r\n PAYMENT_NOT_COMPLETED: 'pay_per_call only: EVO has not yet confirmed the payment for this order_id. Retry with the SAME idempotency-key after a delay, or use --watch to poll automatically until PAID.',\r\n PAYMENT_NOT_FOUND: 'No EVO transaction found for this order_id. Confirm the user paid via EVO using the order_id as the merchantTransID; do NOT retry blindly.',\r\n PAYMENT_AMOUNT_MISMATCH: 'The EVO-confirmed amount/currency does not match the order. The user must pay the exact order amount in the exact currency under the order_id. Do NOT retry until corrected.',\r\n PAYMENT_QUERY_FAILED: 'EVO gateway query failed (transport/timeout). Retry once after ~5s with the SAME idempotency-key.',\r\n BILLING_MODE_MISMATCH: 'The order billing_mode is not a recognized settlement mode (only monthly_settlement and pay_per_call are valid). Check the developer billing_mode; do NOT retry blindly.',\r\n INVALID_ORDER_STATE: 'The order is not in AWAITING_PAYMENT (it may already be PAID or CANCELLED). Check status via get; do NOT retry pay-order.',\r\n ORDER_NOT_FOUND: 'No order for this --order-id. Verify it is the order_id returned by create-order. Do NOT retry.',\r\n ACCOUNT_INSUFFICIENT_BALANCE: 'Settlement credit is insufficient (check via admin-cli accounts get). Direct the user to top up offline.',\r\n ACCOUNT_NOT_FOUND: 'Developer has no settlement account. Direct the user to complete contract signing.',\r\n ACCOUNT_SUSPENDED: 'The settlement account is suspended. Direct the user to contact support; do NOT retry.',\r\n PAYORDER_FAILED: 'Upstream payOrder failed after a successful deduction; the deduction was reversed and the order stays AWAITING_PAYMENT. Retry with the SAME idempotency-key after a delay.',\r\n PAYORDER_FAILED_AFTER_PAYMENT: 'EVO payment confirmed but upstream payOrder failed. The order is recoverable (the EVO payment under the order_id is preserved). Contact support for reconciliation; do NOT retry automatically.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Add a unique --idempotency-key and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'Same idempotency-key used with different parameters. Use the original parameters, or generate a NEW key.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug get` schema. Read-only, supports `--watch`. Long-running. */\r\nexport const hotelGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'get',\r\n description:\r\n 'Query a hotel order status by id; with --watch, poll until a terminal status. Confirmation from the property is asynchronous, so order_status is usually PROCESSING (2) immediately after book — poll until CONFIRMED (3)',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Our order reference (coOrderCode) returned by book (book.response.order_id)' },\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll until a terminal status, emitting one NDJSON line per update' },\r\n 'watch-interval': { type: 'int', required: false, default: 5, description: 'Seconds between polls when --watch is set' },\r\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll before giving up' },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Our order reference.' },\r\n fc_order_code: { type: 'string', description: 'Supplier order reference.' },\r\n order_status: { type: 'string', description: 'Std STRING: PROCESSING | CONFIRMED | CANCELLED | COMPLETED | INIT. There is no order_status_std field.' },\r\n order_status_code: { type: 'int', description: '2 = Processing, 3 = Confirmed, 4 = Cancelled, 5 = Completed. Provider path only; absent on the local-cache fallback.' },\r\n channel_state: { type: 'string|null', description: \"Channel-level state (e.g. 'paid' = settled).\" },\r\n hotel_confirm_no: { type: 'string|null', description: 'Property confirmation number. Populated once order_status reaches CONFIRMED (3); null while PROCESSING (2).' },\r\n hotel_name: { type: 'string|null', description: 'Hotel name.' },\r\n room_name: { type: 'string|null', description: 'Booked room type.' },\r\n check_in: { type: 'string|null', description: 'Check-in date YYYY-MM-DD.' },\r\n check_out: { type: 'string|null', description: 'Check-out date YYYY-MM-DD.' },\r\n total_amount: { type: 'float|null', description: 'Total amount in DECIMAL units.' },\r\n source: { type: 'string', description: \"'provider' (live upstream, carries order_status_code) or 'local_cache' (fallback, string status only).\" },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug get --order-id E2E1750000000',\r\n output_summary: 'Returns order_status (string) + order_status_code (int). Poll every 5s until CONFIRMED (3); hotel_confirm_no appears once confirmed.',\r\n },\r\n polling: {\r\n recommended_interval_seconds: 5,\r\n terminal_statuses: [3, 4, 5],\r\n in_progress_statuses: [2],\r\n field_availability: {\r\n hotel_confirm_no: 'Populated only after order_status reaches CONFIRMED (3). Null while PROCESSING (2).',\r\n },\r\n },\r\n error_recovery: {\r\n HOTEL_ORDER_NOT_FOUND: 'No order for this --order-id. Verify it is the order_id returned by book. Do NOT retry.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after 5s; if still failing, surface to user.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug cancel` schema. Write op (W/Y) — acknowledgement is not proof. */\r\nexport const hotelCancelSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'cancel',\r\n description:\r\n 'Cancel an entire hotel order within the cancellation policy (a cancellation fee may apply). Returns synchronously, but a successful call is acceptance only, NOT proof: poll get until order_status=CANCELLED (4). For partial-night or out-of-policy cancellation, use checkout instead',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Our order reference (coOrderCode) to cancel (book.response.order_id)' },\r\n 'fc-order-code': { type: 'string', required: true, description: 'Supplier order reference (book.response.fc_order_code)' },\r\n reason: { type: 'string', required: false, description: 'Cancellation reason' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Reuse the SAME key when retrying the same cancellation',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Cancelled order reference.' },\r\n order_status: { type: 'string', description: \"Status after the cancel request. Acceptance is NOT proof — poll get until 'CANCELLED' (order_status_code 4).\" },\r\n cancellation: {\r\n type: 'object|null',\r\n description: 'Confirmed-cancellation details (confirmed shape).',\r\n properties: {\r\n cancellation_fee: { type: 'float', description: 'Fee charged for cancellation, in DECIMAL units.' },\r\n reversal_amount: { type: 'float', description: 'Amount reversed/refunded, in DECIMAL units.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code.' },\r\n },\r\n },\r\n cancellation_fee: { type: 'float|null', description: 'Fee charged for cancellation (confirmed shape), in DECIMAL units.' },\r\n refund_amount: { type: 'float', description: 'Amount credited back to the settlement balance (paid - cancellation_fee), in DECIMAL units.' },\r\n cancel_status: { type: 'string|absent', description: \"'cancel_pending' when accepted upstream but not yet observed as CANCELLED (accepted-but-pending shape).\" },\r\n cancel_result: { type: 'unknown|absent', description: 'Upstream cancel acknowledgement (pending shape). NOT proof of cancellation — confirm via get.' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli hotel-redaug cancel --order-id E2E1750000000 --fc-order-code FC1750000000 --idempotency-key cancel-h1n2',\r\n output_summary: 'Returns the cancellation acknowledgement and any fee/refund. Then poll get until order_status=CANCELLED (4) to confirm.',\r\n },\r\n error_recovery: {\r\n CANCELLATION_NOT_ALLOWED: 'The order is outside its free/allowed cancellation window or already terminal. Do NOT retry cancel. If the user still wants out (e.g. drop some nights or request a waiver), use checkout instead.',\r\n ALREADY_CANCELLED: 'Order is already cancelled (order_status=4). Treat as success; confirm via get.',\r\n HOTEL_ORDER_NOT_FOUND: 'Verify --order-id / --fc-order-code from the book response. Do NOT retry.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after 5s with the SAME idempotency-key, then poll get to check whether the cancellation actually took effect.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Add a unique --idempotency-key derived from business intent and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'The same idempotency-key was used with different parameters. Retry with the original parameters, or generate a NEW key for the new parameters.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug checkout` schema. Write op (W/Y) — async application. */\r\nexport const hotelCheckoutSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'checkout',\r\n description:\r\n 'Request a partial check-out or an out-of-policy cancellation (drop some nights, or cancel after the free window so the property must approve). This is an APPLICATION: it returns a task_order_code synchronously, then the supplier decides asynchronously — poll get-checkout. Use cancel for a simple whole-order in-policy cancellation',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Our order reference (coOrderCode) for the URL path (book.response.order_id)' },\r\n 'fc-order-code': { type: 'string', required: true, description: 'Supplier order reference of the booking to change (book.response.fc_order_code)' },\r\n reason: { type: 'string', required: true, description: 'Why the partial check-out / out-of-policy cancellation is requested' },\r\n 'checkout-rooms': {\r\n type: 'string',\r\n required: true,\r\n description: 'Which booked rooms to check out of, taken from the book response (book.response.rooms[]). room_index and guest_name come verbatim from book — do NOT ask the user for them',\r\n constraints: 'JSON array of {room_index, guest_name, cancel_check_in_date}; else PARAM_INVALID. cancel_check_in_date is the check-in date of the night(s) being dropped (YYYY-MM-DD)',\r\n },\r\n 'refund-type': { type: 'int', required: false, default: 1, description: 'Requested refund handling (upstream refund-type code; default to the standard refund flow when unsure)' },\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description: 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Reuse the SAME key when retrying the same application',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n },\r\n response: {\r\n order_id: { type: 'string', description: 'Our order reference (echoes the path order_id).' },\r\n task_order_code: { type: 'string', description: 'Check-out application id. Poll get-checkout --task-order-code to track approval and refund.' },\r\n apply_status: { type: 'string|null', description: 'Initial application status (e.g. submitted / pending).' },\r\n checkout_status: { type: 'string|absent', description: \"'checkout_pending' — async; poll get-checkout for the outcome.\" },\r\n },\r\n example: {\r\n command:\r\n `agenzo-merchant-cli hotel-redaug checkout --order-id E2E1750000000 --fc-order-code FC1750000000 --reason \"guest leaving early\" --checkout-rooms '[{\"room_index\":\"1\",\"guest_name\":\"San Zhang\",\"cancel_check_in_date\":\"2026-07-05\"}]' --idempotency-key checkout-h1n2`,\r\n output_summary: 'Returns task_order_code. Poll hotel-redaug get-checkout --task-order-code <code> until the application is approved/rejected/refunded.',\r\n },\r\n error_recovery: {\r\n CHECKOUT_NOT_ALLOWED: 'The order state does not permit a check-out application (e.g. not yet confirmed, or already completed). Surface to user; do NOT retry.',\r\n HOTEL_ORDER_NOT_FOUND: 'Verify --order-id / --fc-order-code from the book response. Do NOT retry.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after 5s with the SAME idempotency-key.',\r\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Add a unique --idempotency-key derived from business intent and retry.',\r\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'The same idempotency-key was used with different parameters. Retry with the original parameters, or generate a NEW key for the new parameters.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug get-checkout` schema. Read-only, supports `--watch`. Long-running. */\r\nexport const hotelGetCheckoutSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'get-checkout',\r\n description:\r\n 'Poll the status and refund outcome of a check-out application created by checkout. The supplier decides asynchronously; with --watch, keep polling until a terminal refund_status',\r\n flags: {\r\n 'task-order-code': { type: 'string', required: true, description: 'Check-out application id from checkout (checkout.response.task_order_code)' },\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll until a terminal status, emitting one NDJSON line per update' },\r\n 'watch-interval': { type: 'int', required: false, default: 10, description: 'Seconds between polls when --watch is set' },\r\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll before giving up' },\r\n },\r\n response: {\r\n task_order_code: { type: 'string', description: 'Check-out application id.' },\r\n refund_status: { type: 'string', description: 'Application/refund status: pending | approved | rejected | refunded.' },\r\n refund: {\r\n type: 'object|null',\r\n description: 'Final refund once approved. Populated only once refund_status is approved or refunded.',\r\n properties: {\r\n amount: { type: 'float', description: 'Refunded amount in DECIMAL units.' },\r\n currency: { type: 'string', description: 'ISO 4217 currency code.' },\r\n },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug get-checkout --task-order-code TASK1750000000',\r\n output_summary: 'Returns refund_status. Poll every 10s until approved/rejected/refunded; refund appears once approved.',\r\n },\r\n polling: {\r\n recommended_interval_seconds: 10,\r\n terminal_statuses: ['approved', 'rejected', 'refunded'],\r\n in_progress_statuses: ['pending'],\r\n field_availability: {\r\n refund: 'Populated only once refund_status is approved or refunded.',\r\n },\r\n },\r\n error_recovery: {\r\n CHECKOUT_TASK_NOT_FOUND: 'Verify --task-order-code from the checkout response. Do NOT retry.',\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after 10s.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug list-orders` schema. Read-only. */\r\nexport const hotelListOrdersSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'list-orders',\r\n description: 'List the developer\\'s hotel orders with optional status filtering and pagination',\r\n flags: {\r\n status: { type: 'string', required: false, description: 'Filter by order status (e.g. PROCESSING / CONFIRMED / CANCELLED / COMPLETED). Omitted entirely when absent (all statuses)' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n page: { type: 'int', required: false, default: 1, description: 'Page number', constraints: '>= 1' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page', constraints: '>= 1 (platform caps at 100 server-side)' },\r\n },\r\n response: {\r\n orders: {\r\n type: 'array',\r\n description: 'List of hotel orders (slim list-item shape).',\r\n items: {\r\n order_id: { type: 'string', description: 'Our order reference.' },\r\n member_id: { type: 'string|null', description: 'End-user this order is attributed to; null when unattributed' },\r\n fc_order_code: { type: 'string', description: 'Supplier order reference.' },\r\n status: { type: 'string', description: 'Current order status (string).' },\r\n provider: { type: 'string', description: \"Service provider ('redaug').\" },\r\n check_in: { type: 'string|null', description: 'Check-in date YYYY-MM-DD.' },\r\n check_out: { type: 'string|null', description: 'Check-out date YYYY-MM-DD.' },\r\n room_num: { type: 'int|null', description: 'Number of rooms booked.' },\r\n price_amount: { type: 'float|null', description: 'Total price in DECIMAL units (NOT cents).' },\r\n price_currency: { type: 'string', description: 'ISO 4217 currency code.' },\r\n payment_status: { type: 'string', description: \"Payment status (e.g. 'ON_ACCOUNT').\" },\r\n hotel_confirm_no: { type: 'string|null', description: 'Property confirmation number (once confirmed).' },\r\n cancellation_fee: { type: 'float|null', description: 'Cancellation fee for cancelled orders; null otherwise.' },\r\n refund_amount: { type: 'float|null', description: 'Amount refunded on cancellation/checkout; null otherwise.' },\r\n created_at: { type: 'string', description: 'Order creation time (ISO 8601).' },\r\n updated_at: { type: 'string', description: 'Last update time (ISO 8601).' },\r\n },\r\n },\r\n total: { type: 'int', description: 'Total matching orders.' },\r\n page: { type: 'int', description: 'Current page.' },\r\n page_size: { type: 'int', description: 'Items per page.' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug list-orders --status CONFIRMED --page 1 --page-size 10',\r\n output_summary: 'Returns a paginated list of hotel orders with status, dates and amount info.',\r\n },\r\n error_recovery: {\r\n INTERNAL_ERROR: 'Transient backend error. Retry once after a short delay.',\r\n PARAM_INVALID: 'Ensure --page / --page-size are positive integers, then retry.',\r\n },\r\n};\r\n\r\n// ============================================================\r\n// Hotel-redaug Addendum A verb schemas (4 new read-only verbs)\r\n// ============================================================\r\n\r\n/** `hotel-redaug find-destination` schema. Read-only. */\r\nexport const hotelFindDestinationSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'find-destination',\r\n description:\r\n 'Search for a destination by keyword (city, landmark, airport, etc.). Returns a list of destinations whose destination_id can be passed to search --destination-id or hotel-filters --destination-id',\r\n flags: {\r\n keyword: { type: 'string', required: true, description: 'Destination search keyword (city name, landmark, airport code, etc.)' },\r\n 'data-type': { type: 'string', required: false, description: 'Optional data type filter to narrow result categories' },\r\n },\r\n response: {\r\n destinations: {\r\n type: 'array',\r\n description: 'Matching destinations. Empty when nothing matches the keyword (rendered as a successful empty result, not an error).',\r\n items: {\r\n destination_id: { type: 'string|null', description: 'Opaque destination identifier. Pass to search --destination-id or hotel-filters --destination-id.' },\r\n type: { type: 'string|int|null', description: 'Destination type (city, landmark, airport, etc.).' },\r\n name: { type: 'string|null', description: 'Destination name.' },\r\n city_name: { type: 'string|null', description: 'City name.' },\r\n city_code: { type: 'string|null', description: 'City code.' },\r\n country_name: { type: 'string|null', description: 'Country name.' },\r\n lat: { type: 'float|null', description: 'Latitude (can also be used with search --lat).' },\r\n lng: { type: 'float|null', description: 'Longitude (can also be used with search --lng).' },\r\n },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug find-destination --keyword \"Shanghai\"',\r\n output_summary: 'Returns destinations[]. Use destinations[].destination_id in search --destination-id or hotel-filters --destination-id.',\r\n },\r\n error_recovery: {\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n PARAM_INVALID: 'Ensure --keyword is non-empty, then retry.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug hotel-filters` schema. Read-only. */\r\nexport const hotelFiltersSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'hotel-filters',\r\n description:\r\n 'Get available filter options (stars, brands, groups, labels, sub-categories, hotel/room facilities) for a location. Each item\\'s code maps directly to the corresponding search filter flag (e.g. hotel_facilities[].code → search --hotel-facility-codes)',\r\n flags: {\r\n 'destination-id': { type: 'string', required: 'conditional', description: 'Destination ID (alternative to --lat/--lng)', constraints: 'Exactly one location branch: --destination-id XOR (--lat + --lng)' },\r\n lat: { type: 'float', required: 'conditional', description: 'Latitude (-90 to 90, requires --lng)', constraints: '-90 to 90; mutually exclusive with --destination-id' },\r\n lng: { type: 'float', required: 'conditional', description: 'Longitude (-180 to 180, requires --lat)', constraints: '-180 to 180; mutually exclusive with --destination-id' },\r\n distance: { type: 'int', required: false, default: 20, description: 'Search radius in kilometers' },\r\n },\r\n response: {\r\n stars: { type: 'array', description: 'Star rating options [{code, name, count}]. code → search --star.' },\r\n brands: { type: 'array', description: 'Hotel brand options [{code, name, count}]. code → search --hotel-brand-codes.' },\r\n groups: { type: 'array', description: 'Hotel group options [{code, name, count}].' },\r\n labels: { type: 'array', description: 'Hotel label options [{code, name, count}]. code → search --hotel-label-ids.' },\r\n sub_categories: { type: 'array', description: 'Hotel sub-category options [{code, name, count}]. code → search --hotel-sub-category-ids.' },\r\n hotel_facilities: { type: 'array', description: 'Hotel facility options [{code, name, count, type}]. code → search --hotel-facility-codes.' },\r\n room_facilities: { type: 'array', description: 'Room facility options [{code, name, count, type}]. code → search --room-facility-codes.' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug hotel-filters --destination-id D12345',\r\n output_summary: 'Returns filter groups. Use the code values in search filter flags (e.g. search --hotel-facility-codes code1,code2).',\r\n },\r\n error_recovery: {\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n PARAM_INVALID: 'Supply exactly one location branch (--destination-id OR --lat/--lng). Coordinates must be within valid ranges.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug list-cities` schema. Read-only. */\r\nexport const hotelListCitiesSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'list-cities',\r\n description:\r\n 'List cities available for hotel booking in a given country. Each city provides a destination_id (for search --destination-id) and/or lat/lng coordinates (for search --lat/--lng)',\r\n flags: {\r\n country: { type: 'string', required: true, description: 'ISO country code (e.g. CN, US, TH)' },\r\n },\r\n response: {\r\n cities: {\r\n type: 'array',\r\n description: 'Cities for the country. Empty when no cities are available (rendered as success, not an error).',\r\n items: {\r\n city_code: { type: 'string', description: 'City code.' },\r\n city_name: { type: 'string', description: 'City name.' },\r\n destination_id: { type: 'string|null', description: 'Destination ID for this city. Pass to search --destination-id.' },\r\n province_code: { type: 'string|null', description: 'Province code.' },\r\n province_name: { type: 'string|null', description: 'Province name.' },\r\n country_code: { type: 'string|null', description: 'Country code.' },\r\n country_name: { type: 'string|null', description: 'Country name.' },\r\n lat: { type: 'float|null', description: 'Latitude (can be used with search --lat).' },\r\n lng: { type: 'float|null', description: 'Longitude (can be used with search --lng).' },\r\n time_zone: { type: 'string|null', description: 'Time zone identifier.' },\r\n popularity_score: { type: 'float|null', description: 'Popularity score for sorting/ranking.' },\r\n },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug list-cities --country CN',\r\n output_summary: 'Returns cities[]. Use cities[].destination_id in search --destination-id, or cities[].lat/lng in search --lat/--lng.',\r\n },\r\n error_recovery: {\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n PARAM_INVALID: 'Ensure --country is a non-empty ISO country code, then retry.',\r\n },\r\n};\r\n\r\n/** `hotel-redaug hotel-detail` schema. Read-only. */\r\nexport const hotelDetailSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: HOTEL_NOUN,\r\n verb: 'hotel-detail',\r\n description:\r\n \"Get detailed information about a specific hotel including facilities, images, location, check-in/check-out times. Use to show the user hotel details before quoting/booking. hotel_id is stable but hotel_name/room_name may change upstream without notice. special_instructions (when requested via --settings hotelTextPolicies) MUST be shown to the user — the upstream data provider does not accept liability for booking issues caused by it not being displayed.\",\r\n flags: {\r\n 'hotel-id': { type: 'string', required: true, description: 'Hotel ID from search results (search.response.hotels[].hotel_id)' },\r\n 'with-images': { type: 'bool', required: false, default: true, description: 'Include hotel images in the response (set false to reduce payload)' },\r\n settings: {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Optional on-demand upstream fields, comma-separated or JSON array — request only what you need: hotelFacilityNew, breakfast, importantNotices, parking, chargingParking, hotelCertificates, comment, hotelMeetingInfos, hotelVideoInfos, hotelTextPolicies (includes special_instructions), hotelStructuredPolicies.childPolicy, hotelStructuredPolicies.extraBedPolicy, hotelStructuredPolicies.petPolicy. Omitted codes are NOT returned by upstream (an upstream requirement, not a display choice). Pass hotelTextPolicies to get special_instructions.',\r\n },\r\n },\r\n response: {\r\n hotel_id: { type: 'string|int', description: 'Hotel identifier.' },\r\n hotel_name: { type: 'string|null', description: 'Hotel name.' },\r\n hotel_eng_name: { type: 'string|null', description: 'English hotel name.' },\r\n star: { type: 'int|null', description: 'Star rating.' },\r\n address: { type: 'string|null', description: 'Hotel address.' },\r\n intro: { type: 'string|null', description: 'Hotel introduction/description.' },\r\n appearance_image: { type: 'string|null', description: 'Main appearance image URL.' },\r\n telephone: { type: 'string|null', description: 'Hotel telephone number.' },\r\n country_name: { type: 'string|null', description: 'Country name.' },\r\n province_name: { type: 'string|null', description: 'Province name.' },\r\n city_name: { type: 'string|null', description: 'City name.' },\r\n district_name: { type: 'string|null', description: 'District name.' },\r\n business_name: { type: 'string|null', description: 'Business area name.' },\r\n lat: { type: 'float|null', description: 'Latitude.' },\r\n lng: { type: 'float|null', description: 'Longitude.' },\r\n check_in_time: { type: 'string|null', description: 'Hotel check-in time.' },\r\n check_out_time: { type: 'string|null', description: 'Hotel check-out time.' },\r\n room_num: { type: 'int|null', description: 'Number of rooms available.' },\r\n facilities: {\r\n type: 'array',\r\n description: 'Hotel facilities list.',\r\n items: {\r\n name: { type: 'string', description: 'Facility name.' },\r\n type: { type: 'string|null', description: 'Facility type/category.' },\r\n },\r\n },\r\n images: {\r\n type: 'array',\r\n description: 'Hotel-level images. Empty array when --with-images false.',\r\n items: {\r\n url: { type: 'string', description: 'Image URL.' },\r\n is_main: { type: 'bool', description: 'Whether this is the main image.' },\r\n type: { type: 'int|null', description: 'Image type/category.' },\r\n },\r\n },\r\n rooms: {\r\n type: 'array',\r\n description: \"Room types with STATIC info only (area/floor/beds/max occupancy/images) — NOT live rates. room_id is the SAME id space as quote's roomItems[].roomId, so relate a room here to its live rate/price/product_token by matching room_id to quote's rates. ALWAYS use quote for price/availability/product_token; this verb never has them. Present this alongside quote's rate options so the user sees what the room actually looks like (area, beds, photos) before picking a rate, not just the one-line room_name from quote.\",\r\n items: {\r\n room_id: { type: 'int|string|null', description: \"Room type id. Matches quote's roomItems[].roomId — use to relate this room's detail to a specific quoted rate.\" },\r\n room_name: { type: 'string|null', description: 'Room type name.' },\r\n area_sqm: { type: 'string|null', description: 'Room area (upstream unit, commonly square meters), as a string.' },\r\n floor: { type: 'string|null', description: 'Floor(s) this room type is on (may be a range, e.g. \"10-15\").' },\r\n max_person: { type: 'int|null', description: 'Max total occupancy.' },\r\n max_adults: { type: 'int|null', description: 'Max adults.' },\r\n max_child: { type: 'int|null', description: 'Max children.' },\r\n allow_smoking: { type: 'bool|null', description: 'Whether smoking is allowed in this room type.' },\r\n beds: {\r\n type: 'array',\r\n description: 'Bed configuration for the room area.',\r\n items: {\r\n name: { type: 'string|null', description: 'Bed type name (e.g. \"King Bed\").' },\r\n width: { type: 'string|null', description: 'Bed width, upstream unit.' },\r\n num: { type: 'string|null', description: 'Number of this bed type.' },\r\n },\r\n },\r\n living_room_beds: {\r\n type: 'array',\r\n description: 'Bed configuration for a separate living-room area, when the room type has one. Same shape as beds.',\r\n items: {\r\n name: { type: 'string|null', description: 'Bed type name.' },\r\n width: { type: 'string|null', description: 'Bed width, upstream unit.' },\r\n num: { type: 'string|null', description: 'Number of this bed type.' },\r\n },\r\n },\r\n images: {\r\n type: 'array',\r\n description: 'Photos of this specific room type. Empty when --with-images false, or when upstream has none for this room.',\r\n items: {\r\n url: { type: 'string', description: 'Image URL.' },\r\n is_main: { type: 'bool', description: 'Whether this is the main image for the room.' },\r\n type: { type: 'int|null', description: 'Image type/category.' },\r\n },\r\n },\r\n },\r\n },\r\n comment: {\r\n type: 'array',\r\n description: \"Guest review scores per channel. Empty unless --settings included 'comment'.\",\r\n items: {\r\n channel: { type: 'string|null', description: 'Review source channel (e.g. EPS).' },\r\n average_score: { type: 'float|null', description: 'Average review score for that channel.' },\r\n },\r\n },\r\n hotel_certificates: {\r\n type: 'array',\r\n description: \"Hotel business certificates/qualifications, when the property has any. Empty unless --settings included 'hotelCertificates' (and the property may simply have none).\",\r\n items: {\r\n unify_code: { type: 'string|null', description: 'Unified business registration code.' },\r\n certification_name: { type: 'string|null', description: 'Certificate name.' },\r\n file_url: { type: 'string|null', description: 'Certificate image URL.' },\r\n },\r\n },\r\n hotel_text_policies: {\r\n type: 'array',\r\n description: \"Free-text hotel policies keyed by code (hotelPolicy/instructions/specialInstructions/mandatoryFees/optionalFees/cleanAndSafety/importantNotices/ageLimit/checkInCheckOut). Empty unless --settings included 'hotelTextPolicies'. special_instructions below is also pulled from this same data, surfaced separately because it MUST be shown to the user.\",\r\n items: {\r\n code: { type: 'string|null', description: 'Policy code, e.g. \"specialInstructions\".' },\r\n code_name: { type: 'string|null', description: 'Display name of the policy code (e.g. \"特别入住说明\").' },\r\n text: { type: 'string|null', description: 'Policy text (may contain HTML list markup from upstream).' },\r\n },\r\n },\r\n hotel_structured_policies: {\r\n type: 'object|null',\r\n description: \"Structured child/extra-bed/pet policies (raw upstream shape, snake_cased). null unless --settings included the relevant hotelStructuredPolicies.* code(s).\",\r\n properties: {\r\n child_policy: { type: 'object|null', description: 'Child stay/breakfast policy.' },\r\n extra_bed_policy: { type: 'object|null', description: 'Extra-bed charge policy by age range.' },\r\n pet_policy: { type: 'object|null', description: 'Pet/service-animal policy.' },\r\n },\r\n },\r\n special_instructions: {\r\n type: 'string|null',\r\n description: \"IMPORTANT: the property's 'special check-in instructions' (upstream code specialInstructions, distinct from the general 'instructions' code). The Agent/caller MUST surface this to the user in the booking UI when present — the upstream data provider does not accept liability for booking problems caused by this not being displayed. Only populated when --settings included 'hotelTextPolicies'; null otherwise (does not mean the hotel has none — it means it wasn't requested).\",\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli hotel-redaug hotel-detail --hotel-id 10583772',\r\n output_summary: \"Returns full hotel details including facilities, hotel images, AND rooms[] (per-room-type static info + photos). Use to present both the hotel and its room types before quoting — rooms[].room_id matches quote's roomItems[].roomId so the two can be shown together.\",\r\n },\r\n error_recovery: {\r\n UPSTREAM_ERROR: 'Transient upstream error. Retry once after ~2s backoff.',\r\n PARAM_INVALID: 'Ensure --hotel-id is a non-empty string, then retry.',\r\n HOTEL_NOT_FOUND: 'The hotel is no longer available from the supplier (no matching hotel node in the upstream response). Do not retry with the same hotel_id — drop it from any local cache/mapping and re-search.',\r\n },\r\n};\r\n\r\n// ============================================================\r\n// Unified cross-provider orders verb schemas (\"orders\" noun)\r\n// ============================================================\r\n//\r\n// `orders` is the read-only index spanning ride, hotel, flight, and future\r\n// providers. Use it for generic order history and common filters; use a\r\n// domain-specific list command only when provider-specific columns are needed.\r\n\r\nexport const ORDERS_NOUN = 'orders';\r\n\r\n/** `orders list` schema — cross-provider order list (`GET /orders`). Read-only. */\r\nexport const unifiedOrdersListSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: ORDERS_NOUN,\r\n verb: 'list',\r\n description:\r\n 'List orders across ALL providers (ride + hotel + flight) with common filters and offset/cursor pagination. Use domain-specific list-orders only for provider-specific fields.',\r\n flags: {\r\n 'order-type': { type: 'string', required: false, description: 'Legacy single order type: ride | hotel | flight' },\r\n 'order-types': { type: 'string', required: false, description: 'Comma-separated order types: ride,hotel,flight' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n status: { type: 'string', required: false, description: 'Legacy single normalized status: PENDING | CONFIRMED | COMPLETED | CANCELLED | FAILED' },\r\n statuses: { type: 'string', required: false, description: 'Comma-separated normalized statuses' },\r\n 'created-from': { type: 'string', required: false, description: 'ISO 8601 created-at lower bound (inclusive)' },\r\n 'created-to': { type: 'string', required: false, description: 'ISO 8601 created-at upper bound (exclusive)' },\r\n cursor: { type: 'string', required: false, description: 'Opaque cursor returned by the previous page' },\r\n page: { type: 'int', required: false, default: 1, description: 'Legacy 1-based page number', constraints: '>= 1' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page', constraints: '1-100' },\r\n },\r\n response: {\r\n orders: {\r\n type: 'array',\r\n description: 'Slim cross-provider index items. Call `orders get` for business-specific detail.',\r\n items: {\r\n order_id: { type: 'string', description: 'Order id (rio_..., hho_..., or ffo_...). Pass to `orders get`.' },\r\n member_id: { type: 'string|null', description: 'Attributed end-user id; null when unattributed' },\r\n order_type: { type: 'string', description: 'ride | hotel | flight' },\r\n status: { type: 'string', description: 'Original provider-domain status for display' },\r\n unified_status: { type: 'string', description: 'PENDING | CONFIRMED | COMPLETED | CANCELLED | FAILED' },\r\n amount: { type: 'float|null', description: 'Order amount in decimal currency units' },\r\n currency: { type: 'string|null', description: 'ISO 4217 currency code' },\r\n created_at: { type: 'string|null', description: 'ISO 8601 datetime' },\r\n updated_at: { type: 'string|null', description: 'ISO 8601 datetime' },\r\n },\r\n },\r\n total: { type: 'int', description: 'Total matching orders across all providers' },\r\n page: { type: 'int', description: 'Legacy current page' },\r\n page_size: { type: 'int', description: 'Items per page' },\r\n next_cursor: { type: 'string|null', description: 'Opaque cursor for the next page; null at the end' },\r\n has_more: { type: 'bool', description: 'Whether another page is available' },\r\n applied_filters: { type: 'object', description: 'Normalized filters applied by the platform' },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli orders list --order-types flight,hotel --created-from 2026-07-01T00:00:00Z --page-size 20',\r\n output_summary: 'Returns ride, hotel, and flight orders with stable pagination metadata.',\r\n },\r\n error_recovery: {\r\n INVALID_REQUEST: 'Fix invalid type/status/date/cursor filters and retry.',\r\n INTERNAL_ERROR: 'Transient backend error. Retry once after a short delay.',\r\n PARAM_INVALID: 'Fix conflicting or invalid CLI options, then retry.',\r\n },\r\n};\r\n\r\n/** `orders get` schema — cross-provider order detail (`GET /orders/{id}`). Read-only. */\r\nexport const unifiedOrdersGetSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: ORDERS_NOUN,\r\n verb: 'get',\r\n description:\r\n 'Get a ride, hotel, or flight order detail by id. The platform resolves order_id to the owning domain and returns that domain detail shape.',\r\n flags: {\r\n 'order-id': { type: 'string', required: true, description: 'Order id from `orders list` (rio_..., hho_..., or ffo_...)' },\r\n },\r\n response: {\r\n '(varies by order_type)': {\r\n type: 'object',\r\n description:\r\n 'Delegated ride, hotel, or flight detail. Treat the result as an opaque domain object and surface the returned fields.',\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli orders get --order-id ffo_01K...',\r\n output_summary: \"Returns the order's provider-domain detail.\",\r\n },\r\n error_recovery: {\r\n ORDER_NOT_FOUND: 'The order_id does not exist or does not belong to this developer/org. Verify the id from `orders list`.',\r\n INTERNAL_ERROR: \"The order's provider detail lookup is temporarily unavailable. Retry once after a short delay.\",\r\n },\r\n};\r\n\r\n/**\r\n * `orders pay-batch` schema — 行程聚合支付:以**一份支付凭证**对一批订单\r\n * (`order_ids[]`,可混合 `hho_`/`ffo_`/`rio_` 三域)一次结算合计总额。Write op (W/Y)。\r\n *\r\n * 这是逻辑写工具名 `orders__aggregate__pay-batch` 的物理落点(`POST /orders/pay-batch`):\r\n * 编排层 trip-aggregate schema 的 `pay-orders` write verb 经 `UniversalGateway` 调用它,\r\n * **只在唯一一次二次确认门通过后执行、绝不暴露给 LLM**。金额取各订单锁单落库的权威价、由\r\n * 后端求和——**调用方不传各订单金额**。凭证按双轨二选一或都不带(月结 / 平台默认选卡):\r\n * 轨 A `--payment-token-id`(以合计总额created、`external_transaction_id` 绑定到本次\r\n * payment_group 的网络令牌,银联/Visa 一次 passkey);轨 B `--payment-method-id`(EVO\r\n * 绑卡一次 3DS)。声明风格对齐既有写 verb(`hotel-redaug pay-order` / `ride-elife pay-order`)。\r\n */\r\nexport const ordersPayBatchSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: ORDERS_NOUN,\r\n verb: 'pay-batch',\r\n description:\r\n 'Settle a batch of orders (may mix ride/hotel/flight — hho_/ffo_/rio_) in ONE aggregate payment via a single payment credential. Physical landing point of the logical write tool orders__aggregate__pay-batch, invoked by the trip-aggregate pay-orders write verb through UniversalGateway (executed only after the single confirmation gate; never exposed to the LLM). Amounts are NOT passed here — the platform sums each order\\'s locked authoritative price. Provide the aggregate total via one rail: --payment-token-id (轨A: network-token minted for the aggregate total, external_transaction_id bound to this payment_group — one UnionPay/Visa passkey) OR --payment-method-id (轨B: EVO bound card — one 3DS challenge); both may be omitted (monthly_settlement / platform default card). On EVO cardholder authentication the response is AUTHENTICATION_REQUIRED with a three_ds_url + merchant_trans_id; finish it out-of-band, then an idempotent replay settles. On success the batch becomes settled / partially_settled (upstream-confirmation-failed orders are refunded). Supports --watch to poll until a terminal batch status.',\r\n flags: {\r\n 'order-ids': {\r\n type: 'string',\r\n required: true,\r\n description:\r\n 'Ordered order ids to settle together — comma-separated (hho_1,ffo_2,rio_3) or a JSON array ([\"hho_1\",\"ffo_2\"]). May mix hho_/ffo_/rio_ domains. Amounts come from each order\\'s locked authoritative price (NOT passed here).',\r\n },\r\n 'payment-token-id': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n '[轨A] Network-token id (UnionPay/Visa) minted for the aggregate total with external_transaction_id bound to this payment_group (direct-charge main path). Mutually exclusive with --payment-method-id; both may be omitted for monthly_settlement / platform default.',\r\n },\r\n 'payment-method-id': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n '[轨B] EVO bound-card id to settle the aggregate total via one 3DS challenge (explicit/fallback rail). Mutually exclusive with --payment-token-id.',\r\n },\r\n 'evo-explicit': {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description:\r\n '[轨B 硬门槛] Explicit opt-in to settle via the EVO bound-card rail. Set true ONLY when the user explicitly chose EVO; forwarded to the body as evo_explicit=true. Omit on the payment-token-id direct-charge path.',\r\n },\r\n 'payment-group-id': {\r\n type: 'string',\r\n required: false,\r\n description:\r\n 'Optional caller-pre-generated payment group id; omit to let the platform generate one. The whole batch is associated with this group for cross-provider reconciliation.',\r\n },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'idempotency-key': {\r\n type: 'string',\r\n required: true,\r\n description:\r\n 'Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. The SAME key + the SAME ordered order_ids replays as the same batch (dedup re-check, no double charge); any change to order_ids yields a new batch.',\r\n constraints: '1-128 chars [A-Za-z0-9_-]',\r\n },\r\n watch: {\r\n type: 'bool',\r\n required: false,\r\n default: false,\r\n description:\r\n 'Poll until a terminal batch status (settled / partially_settled / failed) or timeout, emitting one NDJSON line per poll. Non-terminal states (authorizing/capturing, AUTHENTICATION_REQUIRED) keep polling — after the user finishes 3DS out-of-band, the next idempotent replay settles.',\r\n },\r\n // watch 默认值与 pay-batch.ts 的 DEFAULT_PAY_BATCH_WATCH_* 常量一致;此处内联字面量\r\n // 以避免 verb-schema.ts ↔ pay-batch.ts 循环依赖(pay-batch.ts 反向依赖本模块的 schema)。\r\n 'watch-interval': {\r\n type: 'int',\r\n required: false,\r\n default: 5,\r\n description: 'Seconds between polls when --watch is set',\r\n },\r\n 'watch-timeout': {\r\n type: 'int',\r\n required: false,\r\n default: 300,\r\n description: 'Max seconds to poll before giving up',\r\n },\r\n },\r\n response: {\r\n payment_group_id: { type: 'string', description: 'The payment group this batch settled under (echoes --payment-group-id when supplied, else server-generated).' },\r\n status: { type: 'string', description: 'settled | partially_settled | failed | AUTHENTICATION_REQUIRED (3DS challenge body).' },\r\n currency: { type: 'string', description: 'ISO 4217 currency of the aggregate settlement (all orders share one currency).' },\r\n total_amount: { type: 'float', description: \"Aggregate total in DECIMAL units = sum of each order's authoritative price (computed by the platform, NOT sent by the caller).\" },\r\n orders: {\r\n type: 'array',\r\n description: 'Per-order final result after upstream confirmation.',\r\n items: {\r\n order_id: { type: 'string', description: 'hho_/ffo_/rio_ order id.' },\r\n status: { type: 'string', description: 'confirmed | refunded | failed.' },\r\n amount: { type: 'float', description: \"That order's authoritative amount.\" },\r\n refunded_amount: { type: 'float', description: 'Amount refunded when upstream confirmation failed for this order.' },\r\n },\r\n },\r\n three_ds_url: { type: 'string', description: '[AUTHENTICATION_REQUIRED only] EVO 3DS challenge URL — complete out-of-band, then replay to settle.' },\r\n merchant_trans_id: { type: 'string', description: '[AUTHENTICATION_REQUIRED only] merchant trans id of the batch preauth.' },\r\n amount: { type: 'float', description: '[AUTHENTICATION_REQUIRED only] challenge amount = aggregate total.' },\r\n },\r\n example: {\r\n command:\r\n 'agenzo-merchant-cli orders pay-batch --order-ids hho_01K...,ffo_01K...,rio_01K... --payment-token-id ntk_01J2ABC --idempotency-key trip-pay-1',\r\n output_summary:\r\n 'Settles all listed orders in one charge (banks/EVO see one transaction). Returns {payment_group_id, status, total_amount, currency, orders[]}. Use --watch to poll until settled / partially_settled / failed; upstream-confirmation-failed orders are refunded.',\r\n },\r\n error_recovery: {\r\n PARAM_INVALID: 'Fix --order-ids (a non-empty comma-separated list or JSON array of order ids) and ensure --idempotency-key is present, then retry.',\r\n ORDER_NOT_PAYABLE: 'One of the order_ids is not in AWAITING_PAYMENT (the error names the specific order_id). Remove/replace it and retry with a NEW idempotency-key.',\r\n CURRENCY_MISMATCH: 'The batch mixes currencies — orders in one pay-batch must share a single currency. Split by currency and settle each group separately.',\r\n TOKEN_ORDER_MISMATCH: 'The token external_transaction_id is not bound to this payment_group. Mint a token for the aggregate total bound to THIS payment_group_id and retry; no funds moved.',\r\n AUTHENTICATION_REQUIRED: 'EVO requires cardholder 3DS: open three_ds_url, finish authentication, then replay pay-batch with the SAME idempotency-key (or use --watch to poll automatically).',\r\n },\r\n};\r\n\r\n/** `orders get-payment-group` schema. Read-only status of one pay-batch settlement. */\r\nexport const ordersGetPaymentGroupSchema: VerbSchema = {\r\n cli: CLI_NAME,\r\n noun: ORDERS_NOUN,\r\n verb: 'get-payment-group',\r\n description: 'Get the status of an aggregate settlement created by `orders pay-batch` (read-only; never re-sends the payment)',\r\n flags: {\r\n 'payment-group-id': { type: 'string', required: true, description: 'payment_group_id returned by `orders pay-batch` (1-64 chars)' },\r\n },\r\n response: {\r\n payment_group_id: { type: 'string', description: 'The payment group' },\r\n status: { type: 'string', description: 'settled | partially_settled | failed | uncertain' },\r\n currency: { type: 'string', description: 'ISO 4217 currency of the aggregate settlement' },\r\n total_amount: { type: 'float', description: 'Aggregate total in DECIMAL units' },\r\n per_order: {\r\n type: 'array',\r\n description: 'Per-order outcome, same shape as pay-batch',\r\n items: {\r\n order_id: { type: 'string', description: 'Order id' },\r\n domain: { type: 'string', description: 'hotel | flight | ride' },\r\n status: { type: 'string', description: 'confirmed | refunded | failed' },\r\n amount: { type: 'float', description: 'Authoritative order amount (decimal)' },\r\n refunded_amount: { type: 'float', description: 'Amount refunded when upstream confirmation failed' },\r\n },\r\n },\r\n },\r\n example: {\r\n command: 'agenzo-merchant-cli orders get-payment-group --payment-group-id pg_...',\r\n output_summary: 'Returns the batch status and per-order results; use it instead of replaying pay-batch to check progress.',\r\n },\r\n error_recovery: {\r\n PARAM_INVALID: 'Pass the payment_group_id exactly as pay-batch returned it (1-64 chars).',\r\n },\r\n};\r\n\r\n// ============================================================\r\n// flight-flink verb schemas (§4.4.1.3) — one per verb.\r\n// Amounts are integers (upstream convention). gender/id_type are STRINGS.\r\n// ============================================================\r\n\r\n/** Build a compact flight VerbSchema (keeps the 18 entries readable). */\r\nfunction flightSchema(\r\n verb: string,\r\n description: string,\r\n flags: Record<string, FlagSchema>,\r\n response: Record<string, unknown>,\r\n example: ExampleSchema,\r\n extra: Partial<Pick<VerbSchema, 'error_recovery' | 'polling'>> = {},\r\n): VerbSchema {\r\n return { cli: CLI_NAME, noun: FLIGHT_NOUN, verb, description, flags, response, example, ...extra };\r\n}\r\n\r\nexport const flightFindAirportSchema = flightSchema(\r\n 'find-airport',\r\n 'Resolve free-text into city/airport candidates (city hits carry children airports).',\r\n { keyword: { type: 'string', required: true, description: 'Free-text place/airport/city name.' } },\r\n { airports: { type: 'array', description: 'City/airport candidates with IATA codes.' } },\r\n { command: 'agenzo-merchant-cli flight-flink find-airport --keyword beijing', output_summary: 'Returns candidate city/airport IATA codes.' },\r\n);\r\n\r\nexport const flightListAirportsSchema = flightSchema(\r\n 'list-airports',\r\n 'Paged airport dictionary (requires page + page-size).',\r\n {\r\n page: { type: 'int', required: false, default: 1, description: '1-based page.' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page (1-100).' },\r\n keyword: { type: 'string', required: false, description: 'Optional name filter.' },\r\n },\r\n { airports: { type: 'array', description: 'Airport records.' } },\r\n { command: 'agenzo-merchant-cli flight-flink list-airports --page 1 --page-size 20', output_summary: 'Paged airport dictionary.' },\r\n);\r\n\r\nexport const flightListAirlinesSchema = flightSchema(\r\n 'list-airlines',\r\n 'Paged airline dictionary (requires page + page-size).',\r\n {\r\n page: { type: 'int', required: false, default: 1, description: '1-based page.' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page (1-100).' },\r\n keyword: { type: 'string', required: false, description: 'Optional name filter.' },\r\n },\r\n { airlines: { type: 'array', description: 'Airline records.' } },\r\n { command: 'agenzo-merchant-cli flight-flink list-airlines --page 1 --page-size 20', output_summary: 'Paged airline dictionary.' },\r\n);\r\n\r\nexport const flightListNationalitiesSchema = flightSchema(\r\n 'list-nationalities',\r\n 'Nationality list (no params).',\r\n {},\r\n { nationalities: { type: 'array', description: 'Nationality codes/names.' } },\r\n { command: 'agenzo-merchant-cli flight-flink list-nationalities', output_summary: 'Nationality list.' },\r\n);\r\n\r\nexport const flightSearchSchema = flightSchema(\r\n 'search',\r\n 'Search flights (one-way/round-trip/multi-city). journeys always carries all legs; for round-trip/multi-city relay the CHOSEN candidate\\'s next_journey_ids into --journey-id until is_final_leg is true — only then do offers carry a real priceKey (product_token).',\r\n {\r\n 'trip-type': { type: 'int', required: true, description: '1=one-way, 2=round-trip, 3=multi-city.' },\r\n journeys: { type: 'json', required: true, description: 'JSON array of {date, origin, destination, origin_type?, destination_type?}. origin/destination are IATA 3-letter codes; *_type 1=city, 2=airport. Carries ALL legs on every call, including relay calls.' },\r\n 'cabin-class': { type: 'string', required: false, default: 'economy', description: 'economy | premium_economy | business | first.' },\r\n 'adult-num': { type: 'int', required: false, default: 1, description: 'Adults (1-9).' },\r\n 'child-num': { type: 'int', required: false, default: 0, description: 'Children (0-9).' },\r\n 'infant-num': { type: 'int', required: false, default: 0, description: 'Infants (0-9).' },\r\n airline: { type: 'string', required: false, description: 'Airline 2-letter code filter.' },\r\n 'transfer-number': { type: 'int', required: false, default: 0, description: '0=any,1=direct,2=1 stop,3=2 stops.' },\r\n 'journey-id': { type: 'json', required: false, description: 'Relay key: copy offers[].next_journey_ids VERBATIM from the candidate the user chose in the previous search. Omit on the first search. Do not build it from the top-level journey_ids, and never send more ids than there are legs (rejected).' },\r\n },\r\n {\r\n offers: { type: 'array', description: 'Candidates for the current leg. Each has next_journey_ids (relay key), journey_id, segment_ids, paired_segment_ids, total_sale_price (WHOLE-TRIP total), currency, cabin_class, baggage/refund/change_rules, and product_token when price_key_ready.' },\r\n price_key_ready: { type: 'bool', description: 'True only when all legs are selected (final search).' },\r\n current_leg: { type: 'int', description: 'Which leg this result is choosing (1-based).' },\r\n total_legs: { type: 'int', description: 'Total legs in the trip.' },\r\n is_final_leg: { type: 'bool', description: 'True when these offers can be bookable. False means relay another round with the chosen candidate\\'s next_journey_ids.' },\r\n journey_ids: { type: 'array', description: 'DEPRECATED for relay: flattened across all candidates, so it cannot tell you which id belongs to which. Relay offers[].next_journey_ids instead.' },\r\n },\r\n { command: \"agenzo-merchant-cli flight-flink search --trip-type 1 --journeys '[{\\\"date\\\":\\\"2026-08-01\\\",\\\"origin\\\":\\\"PEK\\\",\\\"destination\\\":\\\"SHA\\\"}]'\", output_summary: 'Returns offers[]; use a product_token where price_key_ready is true, then verify. Round-trip: the first search has is_final_leg=false and no product_token — relay the chosen candidate\\'s next_journey_ids to get bookable offers.' },\r\n);\r\n\r\nexport const flightMoreOffersSchema = flightSchema(\r\n 'more-offers',\r\n 'More fare offers for a priceKey (carried by product_token).',\r\n { 'product-token': { type: 'string', required: true, description: 'Opaque token from search.' } },\r\n {\r\n offers: { type: 'array', description: 'Additional fare candidates for the same flight (same shape as search offers[]); all are bookable.' },\r\n current_leg: { type: 'int', description: 'Always 1 — alternative fares for one chosen flight, not a relay round.' },\r\n total_legs: { type: 'int', description: 'Always 1.' },\r\n is_final_leg: { type: 'bool', description: 'Always true.' },\r\n },\r\n { command: 'agenzo-merchant-cli flight-flink more-offers --product-token pt_...', output_summary: 'Additional fare offers.' },\r\n);\r\n\r\nexport const flightVerifySchema = flightSchema(\r\n 'verify',\r\n 'Pre-booking price verification. Returns the authoritative product_token and a price_changed flag; pass the returned token to create-order. With --previous-total-price set, supplier 1002/1950 no longer dead-ends: the platform re-searches the SAME flight from the token and returns the refreshed fare; if that flight can no longer be found it fails with OFFER_UNAVAILABLE (pick another flight).',\r\n {\r\n 'product-token': { type: 'string', required: true, description: 'Opaque token from search.' },\r\n 'previous-total-price': { type: 'int', required: false, description: 'Total price of the selected offer; enables the one-shot re-search refresh on supplier 1002/1950. Omit to keep the legacy behavior (error surfaces as-is).' },\r\n 'cabin-class': { type: 'string', required: false, description: 'Cabin class to re-search with when refreshing (economy | premium_economy | business | first). Omitted falls back to economy.' },\r\n 'adult-num': { type: 'int', required: false, description: 'Adults to re-search with when refreshing (1-9).' },\r\n 'child-num': { type: 'int', required: false, description: 'Children to re-search with when refreshing (0-9).' },\r\n 'infant-num': { type: 'int', required: false, description: 'Infants to re-search with when refreshing (0-9).' },\r\n },\r\n {\r\n product_token: { type: 'string', description: 'Authoritative token to pass to create-order.' },\r\n total_price: { type: 'int', description: 'Verified total price (integer).' },\r\n currency: { type: 'string', description: 'Currency code.' },\r\n price_changed: { type: 'bool', description: 'True if the price changed since search; re-confirm with the user.' },\r\n previous_total_price: { type: 'int', description: 'The selected offer’s price at pick time; present when the request carried previous-total-price. If it differs from total_price the fare was refreshed by a re-search (show the user the old → new price).' },\r\n journeys: { type: 'array', description: 'The COMPLETE itinerary being priced — every leg, not just the last one relayed. Use it to show the full trip on a confirmation screen.' },\r\n },\r\n { command: 'agenzo-merchant-cli flight-flink verify --product-token pt_...', output_summary: 'Returns the authoritative product_token + price_changed.' },\r\n);\r\n\r\nexport const flightCreateOrderSchema = flightSchema(\r\n 'create-order',\r\n 'Create a flight order without charging (locks the fare, status AWAITING_PAYMENT). Forward the verify product_token and its total/currency verbatim.',\r\n {\r\n 'product-token': { type: 'string', required: true, description: 'Authoritative token from verify.' },\r\n 'total-amount': { type: 'string', required: true, description: 'Verified total price (decimal units).' },\r\n currency: { type: 'string', required: true, description: 'ISO 4217 currency code.' },\r\n 'trip-type': { type: 'int', required: false, default: 1, description: '1/2/3.' },\r\n 'contact-name': { type: 'string', required: true, description: 'Contact name.' },\r\n 'contact-region': { type: 'string', required: true, description: 'Contact phone country code (no +).' },\r\n 'contact-phone': { type: 'string', required: true, description: 'Contact phone.' },\r\n 'contact-email': { type: 'string', required: true, description: 'Contact email.' },\r\n passengers: { type: 'json', required: true, description: 'JSON array of passengers. gender/id_type are STRINGS (\"1\"/\"2\"). child/infant require adult_passenger_name. A saved traveller can be passed as just {\"traveller_token\":\"tvp_...\",\"type\":\"adult\"} (from token-cli travellers list); the server fills in the ID details.' },\r\n 'save-travellers': { type: 'bool', required: false, description: 'Save the fully filled passengers of this order as frequent travellers. Set only when the user explicitly asked to save them.' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n 'idempotency-key': { type: 'string', required: true, description: 'Forwarded verbatim as the Idempotency-Key header.' },\r\n },\r\n {\r\n order_no: { type: 'string', description: 'Our order reference (ffo_...).' },\r\n upstream_order_no: { type: 'string', description: 'Supplier order number.' },\r\n status: { type: 'string', description: 'AWAITING_PAYMENT after a successful create.' },\r\n total_amount: { type: 'float', description: 'Total amount.' },\r\n currency: { type: 'string', description: 'Currency code.' },\r\n },\r\n { command: \"agenzo-merchant-cli flight-flink create-order --product-token pt_... --total-amount 1200 --currency CNY --contact-name 'ZHANG SAN' --contact-region 86 --contact-phone 138... --contact-email a@b.com --passengers '[...]' --idempotency-key k1\", output_summary: 'Returns order_no; then pay-order to ticket.' },\r\n {\r\n error_recovery: {\r\n PRICE_CHANGED: 'Price changed since verify. Re-run verify and confirm the new price with the user before retrying.',\r\n ORDER_CREATE_FAILED: 'Upstream create failed; funds released. Safe to retry with the same idempotency-key.',\r\n IDEMPOTENCY_CONFLICT: 'Same key reused with different params. Use a fresh idempotency-key.',\r\n },\r\n },\r\n);\r\n\r\nexport const flightPayOrderSchema = flightSchema(\r\n 'pay-order',\r\n 'Charge the order and trigger upstream ticketing. AWAITING_PAYMENT → PAID. Funds move HERE, not in create-order.',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference from create-order.' },\r\n 'payment-method-id': { type: 'string', required: false, description: 'Optional bound-card id to charge (pay_per_call only; omit to use the default card).' },\r\n 'payment-token-id': { type: 'string', required: false, description: 'Optional network-token id; settles via direct charge instead of EVO preauth.' },\r\n 'authorized-merchant-trans-id': { type: 'string', required: false, description: 'Resume an EVO-card 3DS challenge with an already-authorised preauth trans id.' },\r\n authenticate: { type: 'bool', required: false, default: false, description: 'Opt-in to require cardholder 3DS on the network-token direct charge (payment-token-id, EVO/Mastercard). On step-up the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume via authorized-charge-no. Default off = frictionless.' },\r\n 'return-url': { type: 'string', required: false, description: 'Optional 3DS/passkey return URL for the network-token authenticate path; falls back to the platform EVO_3DS_RETURN_URL.' },\r\n 'authorized-charge-no': { type: 'string', required: false, description: 'Resume a network-token 3DS challenge: charge_no from a prior AUTHENTICATION_REQUIRED response (settled via resume_token), then triggers ticketing on success.' },\r\n 'evo-explicit': { type: 'bool', required: false, default: false, description: '[方案 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set true ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Forwarded verbatim as the Idempotency-Key header.' },\r\n ...PRICE_ANNOTATION_FLAGS,\r\n },\r\n { order_no: { type: 'string', description: 'Our order reference.' }, status: { type: 'string', description: 'PAID on success; AUTHENTICATION_REQUIRED when the card needs 3DS.' } },\r\n { command: 'agenzo-merchant-cli flight-flink pay-order --order-no ffo_... --idempotency-key k2', output_summary: 'Order becomes PAID; poll get-order until TICKETED.' },\r\n);\r\n\r\nexport const flightGetOrderSchema = flightSchema(\r\n 'get-order',\r\n 'Query flight order status by --order-no. Ticketing is asynchronous — poll until TICKETED.',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n watch: { type: 'bool', required: false, default: false, description: 'Poll until terminal, one NDJSON line per update.' },\r\n 'watch-interval': { type: 'int', required: false, default: 5, description: 'Seconds between polls.' },\r\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll.' },\r\n },\r\n {\r\n order_no: { type: 'string', description: 'Our order reference.' },\r\n status: { type: 'string', description: 'AWAITING_PAYMENT | PAID | TICKETING | TICKETED | CANCELLED | FAILED.' },\r\n ticket_infos: { type: 'array', description: 'Ticket numbers once TICKETED.' },\r\n },\r\n { command: 'agenzo-merchant-cli flight-flink get-order --order-no ffo_...', output_summary: 'Returns status; poll until TICKETED.' },\r\n {\r\n polling: {\r\n recommended_interval_seconds: 5,\r\n terminal_statuses: ['TICKETED', 'CANCELLED', 'FAILED'],\r\n in_progress_statuses: ['AWAITING_PAYMENT', 'PAID', 'TICKETING'],\r\n },\r\n },\r\n);\r\n\r\nexport const flightCancelOrderSchema = flightSchema(\r\n 'cancel-order',\r\n 'Cancel an un-ticketed order by --order-no (with refund). A ticketed order is rejected upstream.',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n reason: { type: 'string', required: false, description: 'Optional cancellation reason.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Forwarded verbatim as the Idempotency-Key header.' },\r\n },\r\n { order_no: { type: 'string', description: 'Our order reference.' }, status: { type: 'string', description: 'CANCELLED on success.' }, refund_amount: { type: 'float|null', description: 'Refunded amount.' } },\r\n { command: 'agenzo-merchant-cli flight-flink cancel-order --order-no ffo_... --idempotency-key k3', output_summary: 'Order becomes CANCELLED; refund issued.' },\r\n);\r\n\r\nexport const flightListOrdersSchema = flightSchema(\r\n 'list-orders',\r\n \"List the developer's flight orders (local read, no upstream call).\",\r\n {\r\n status: { type: 'string', required: false, description: 'Optional status filter.' },\r\n member: MEMBER_FLAG_SCHEMA,\r\n page: { type: 'int', required: false, default: 1, description: '1-based page.' },\r\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page (1-100).' },\r\n },\r\n { orders: { type: 'array', description: 'Flight order summaries; each item carries member_id (null when unattributed).' }, total: { type: 'int', description: 'Total count.' } },\r\n { command: 'agenzo-merchant-cli flight-flink list-orders', output_summary: 'Paged flight orders.' },\r\n);\r\n\r\nexport const flightChangeSearchSchema = flightSchema(\r\n 'change-search',\r\n 'Search rebook-eligible flights for an order.',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n date: { type: 'string', required: true, description: 'Target change date YYYY-MM-DD.' },\r\n passenger: { type: 'string', required: true, description: 'passengerCode.' },\r\n 'segment-id': { type: 'string', required: true, description: 'Comma-separated segment ids.' },\r\n 'cabin-class': { type: 'string', required: false, default: 'economy', description: 'Cabin class.' },\r\n },\r\n { flights: { type: 'array', description: 'Rebook-eligible flights.' } },\r\n { command: 'agenzo-merchant-cli flight-flink change-search --order-no ffo_... --date 2026-08-05 --passenger P1 --segment-id S1', output_summary: 'Rebook options.' },\r\n);\r\n\r\nexport const flightChangeApplySchema = flightSchema(\r\n 'change-apply',\r\n 'Submit a change request. Returns change_order_no, status 0 (pending review).',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n passenger: { type: 'string', required: true, description: 'passengerCode.' },\r\n 'segment-id': { type: 'string', required: true, description: 'Comma-separated segment ids.' },\r\n 'product-token': { type: 'string', required: true, description: 'Change priceKey token.' },\r\n 'contact-name': { type: 'string', required: true, description: 'Contact name.' },\r\n 'contact-region': { type: 'string', required: true, description: 'Contact region.' },\r\n 'contact-phone': { type: 'string', required: true, description: 'Contact phone.' },\r\n 'contact-email': { type: 'string', required: true, description: 'Contact email.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n },\r\n { change_order_no: { type: 'string', description: 'Change order number.' }, status: { type: 'int', description: '0 = pending review.' } },\r\n { command: 'agenzo-merchant-cli flight-flink change-apply --order-no ffo_... --passenger P1 --segment-id S1 --product-token pt_... --contact-name X --contact-region 86 --contact-phone 138 --contact-email a@b.com --idempotency-key k4', output_summary: 'Returns change_order_no; pay-order type=1 to confirm.' },\r\n);\r\n\r\nexport const flightChangeDetailSchema = flightSchema(\r\n 'change-detail',\r\n 'Change request detail by --change-order-no.',\r\n { 'change-order-no': { type: 'string', required: true, description: 'Change order number.' } },\r\n { status: { type: 'int', description: 'Change status.' } },\r\n { command: 'agenzo-merchant-cli flight-flink change-detail --change-order-no C1', output_summary: 'Change request detail.' },\r\n);\r\n\r\nexport const flightChangeCancelSchema = flightSchema(\r\n 'change-cancel',\r\n 'Cancel a change request (immediate terminal).',\r\n {\r\n 'change-order-no': { type: 'string', required: true, description: 'Change order number.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n },\r\n { status: { type: 'int', description: 'Terminal 5 (cancelled).' } },\r\n { command: 'agenzo-merchant-cli flight-flink change-cancel --change-order-no C1 --idempotency-key k5', output_summary: 'Change request cancelled.' },\r\n);\r\n\r\nexport const flightChangePaySchema = flightSchema(\r\n 'change-pay',\r\n 'Pay a change request fee (charges like a normal order) and trigger change ticketing. flink pay type=1.',\r\n {\r\n 'change-order-no': { type: 'string', required: true, description: 'Change order number.' },\r\n 'order-no': { type: 'string', required: true, description: 'Original order reference (ownership check).' },\r\n amount: { type: 'float', required: true, description: 'Change fee total (change-detail price_total, decimal units).' },\r\n currency: { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code.' },\r\n 'payment-method-id': { type: 'string', required: false, description: 'Optional bound-card id (EVO path).' },\r\n 'payment-token-id': { type: 'string', required: false, description: 'Optional UPI network-token id (unionpay charge path).' },\r\n 'authorized-merchant-trans-id': { type: 'string', required: false, description: 'Resume a 3DS challenge with the merchant trans id of the already-authorised preauth; the platform reuses and captures it instead of authorizing again.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n ...PRICE_ANNOTATION_FLAGS,\r\n },\r\n {\r\n change_order_no: { type: 'string', description: 'Change order number.' },\r\n status: { type: 'string', description: 'PROCESSING after payment.' },\r\n payment_status: { type: 'string', description: 'SETTLED on success. Absent when the card needs 3DS — the response then carries a challenge object instead (status AUTHENTICATION_REQUIRED, three_ds_url, merchant_trans_id) and nothing has been charged yet.' },\r\n },\r\n { command: 'agenzo-merchant-cli flight-flink change-pay --change-order-no C1 --order-no ffo_... --amount 120 --currency USD --idempotency-key k6', output_summary: 'Change fee charged; change ticketing triggered.' },\r\n);\r\n\r\nexport const flightRefundApplySchema = flightSchema(\r\n 'refund-apply',\r\n 'Submit a refund request. Returns refund_order_no, status 0 (pending review).',\r\n {\r\n 'order-no': { type: 'string', required: true, description: 'Our order reference.' },\r\n passenger: { type: 'string', required: true, description: 'passengerCode.' },\r\n 'segment-id': { type: 'string', required: true, description: 'Comma-separated segment ids.' },\r\n 'reason-type': { type: 'int', required: true, description: 'Refund reason type code.' },\r\n reason: { type: 'string', required: false, description: 'Free-text reason.' },\r\n 'contact-name': { type: 'string', required: true, description: 'Contact name.' },\r\n 'contact-region': { type: 'string', required: true, description: 'Contact region.' },\r\n 'contact-phone': { type: 'string', required: true, description: 'Contact phone.' },\r\n 'contact-email': { type: 'string', required: true, description: 'Contact email.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n },\r\n { refund_order_no: { type: 'string', description: 'Refund order number.' }, status: { type: 'int', description: '0 = pending review.' } },\r\n { command: 'agenzo-merchant-cli flight-flink refund-apply --order-no ffo_... --passenger P1 --segment-id S1 --reason-type 1 --contact-name X --contact-region 86 --contact-phone 138 --contact-email a@b.com --idempotency-key k6', output_summary: 'Returns refund_order_no; refund-confirm 1 to confirm.' },\r\n);\r\n\r\nexport const flightRefundDetailSchema = flightSchema(\r\n 'refund-detail',\r\n 'Refund request detail by --refund-order-no.',\r\n { 'refund-order-no': { type: 'string', required: true, description: 'Refund order number.' } },\r\n { status: { type: 'int', description: 'Refund status.' } },\r\n { command: 'agenzo-merchant-cli flight-flink refund-detail --refund-order-no R1', output_summary: 'Refund request detail.' },\r\n);\r\n\r\nexport const flightRefundConfirmSchema = flightSchema(\r\n 'refund-confirm',\r\n 'Confirm (\"1\") or cancel (\"2\") a refund. Cancel takes effect immediately to terminal 5.',\r\n {\r\n 'refund-order-no': { type: 'string', required: true, description: 'Refund order number.' },\r\n confirm: { type: 'string', required: true, description: '\"1\" confirm / \"2\" cancel.' },\r\n 'idempotency-key': { type: 'string', required: true, description: 'Idempotency-Key header.' },\r\n },\r\n { status: { type: 'int', description: 'Refund status after the action.' } },\r\n { command: 'agenzo-merchant-cli flight-flink refund-confirm --refund-order-no R1 --confirm 1 --idempotency-key k7', output_summary: 'Refund confirmed or cancelled.' },\r\n);\r\n\r\n// ============================================================\r\n// data-aisa verb schemas (AIsa read-only information lookup) — 4 verbs\r\n// ============================================================\r\n//\r\n// Pay-per-call READ-ONLY lookups: there is no write verb here, so no verb\r\n// carries `--yes`, `--watch` or a required `--idempotency-key`. Flag names are\r\n// declared in HYPHEN form (`operation-id` / `idempotency-key`) because the\r\n// orchestrator builds `--<flag>` from the very same names; response fields keep\r\n// the upstream index's own casing (`operationId`) so a relayed id stays\r\n// byte-identical across the chain.\r\n\r\n/** Data noun (command group) — the `data-aisa/*` verbs share this. */\r\nexport const DATA_NOUN = 'data-aisa';\r\n\r\n/**\r\n * Build a data-aisa VerbSchema. Same job as `flightSchema` (inject cli + noun,\r\n * keep the four entries readable), but the sections are passed as a LABELLED\r\n * object rather than positionally: the cross-repo flag-name check reads\r\n * `flags:` / `response:` straight out of this file's text, and positional\r\n * arguments give it nothing to key off.\r\n */\r\nfunction dataSchema(\r\n spec: Omit<VerbSchema, 'cli' | 'noun'>,\r\n): VerbSchema {\r\n return { cli: CLI_NAME, noun: DATA_NOUN, ...spec };\r\n}\r\n\r\nexport const dataListCategoriesSchema = dataSchema({\r\n verb: 'list-categories',\r\n description: 'List the data categories and how many capabilities each one holds. Free: answered from the bundled index, no upstream call.',\r\n flags: {\r\n // No flags of its own — authentication rides on the global --api-key.\r\n },\r\n response: {\r\n categories: { type: 'array', description: 'Categories ordered by size; each item is {category, endpoints}.' },\r\n },\r\n example: { command: 'agenzo-merchant-cli data-aisa list-categories', output_summary: 'The data categories with a capability count each — use it to answer \"what can you look up\".' },\r\n});\r\n\r\nexport const dataSearchSchema = dataSchema({\r\n verb: 'search',\r\n description: 'Find a data capability by keyword. Free: answered from the bundled index, no upstream call. Returns operationId + method + path + tags + summary + price_usd for each hit.',\r\n flags: {\r\n keyword: { type: 'string', required: false, constraints: 'Space- or comma-separated tokens, matched against operationId / path / summary / tags. Omitted returns the first `limit` capabilities as examples.', description: \"What to look for, e.g. 'crypto price' or 'reddit'.\" },\r\n limit: { type: 'int', required: false, default: 15, constraints: '1..50; defaults to 15.', description: 'How many hits to return.' },\r\n },\r\n response: {\r\n results: { type: 'array', description: 'Matching capabilities; each item is {operationId, method, path, tags, summary, price_usd}. Relay operationId VERBATIM into describe / query.' },\r\n },\r\n example: { command: \"agenzo-merchant-cli data-aisa search --keyword 'crypto price' --limit 5\", output_summary: 'Hits with operationId + price_usd; describe the chosen one before running it.' },\r\n});\r\n\r\nexport const dataDescribeSchema = dataSchema({\r\n verb: 'describe',\r\n description: \"Read one capability's parameter spec, usage hint and unit price before calling it. Free: answered from the bundled index, no upstream call.\",\r\n flags: {\r\n 'operation-id': { type: 'string', required: true, constraints: 'An operationId returned by search, verbatim.', description: 'Which capability to describe.' },\r\n },\r\n response: {\r\n operationId: { type: 'string', description: 'The capability id — pass it unchanged to query.' },\r\n method: { type: 'string', description: 'Upstream HTTP method of the capability.' },\r\n path: { type: 'string', description: 'Upstream path of the capability.' },\r\n params: { type: 'array', description: 'Declared parameters; each item is {name, in, required, type, desc}. `desc` may be an empty string.' },\r\n required: { type: 'array', description: 'Names of the required parameters.' },\r\n usage: { type: 'string', description: 'Human-readable call guidance: which params are required, where each one sits, how to assemble --params.' },\r\n price_usd: { type: 'number|null', description: 'Unit price of one query call, in USD.' },\r\n tags: { type: 'array', description: 'Categories this capability belongs to.' },\r\n cost_tier: { type: 'string|null', description: 'Coarse price band of this capability.' },\r\n },\r\n example: { command: 'agenzo-merchant-cli data-aisa describe --operation-id get_coingecko_simple_price', output_summary: 'Parameter spec + unit price; build --params from params[].name, then query.' },\r\n});\r\n\r\nexport const dataQuerySchema = dataSchema({\r\n verb: 'query',\r\n description: 'Run one capability and return its data. Charged per call. READ-ONLY: it fetches data and nothing else.',\r\n flags: {\r\n 'operation-id': { type: 'string', required: true, constraints: 'An operationId returned by search, verbatim.', description: 'Which capability to run.' },\r\n params: { type: 'object', required: false, constraints: 'A JSON object keyed by the parameter names from describe. Passed through as a whole; unknown keys are dropped.', description: \"The capability's parameters.\" },\r\n 'idempotency-key': { type: 'string', required: false, constraints: 'Optional. [A-Za-z0-9_-]{1,128}. When absent the request is still sent (no prompt, nothing generated) and de-duplication falls back to the result cache.', description: 'Caller-supplied de-duplication key, forwarded verbatim as the Idempotency-Key header.' },\r\n },\r\n response: {\r\n data: { type: 'object', description: 'The capability response, verbatim.' },\r\n cost_usd: { type: 'number', description: 'What this call cost, in USD.' },\r\n },\r\n example: { command: 'agenzo-merchant-cli data-aisa query --operation-id get_coingecko_simple_price --params \\'{\"ids\":\"bitcoin\",\"vs_currencies\":\"usd\"}\\'', output_summary: 'Returns data (upstream payload, verbatim) plus cost_usd for this call.' },\r\n});\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { QuoteResponse, VehicleClass } from '../types/api.js';\r\nimport { attachSchemaHelp, quoteSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 2.1 / design §4.4.1.3) — a catalog code (exit 1), never\r\n * `PARAM_REQUIRED` (not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Number-ify a coordinate / numeric flag. Non-finite input maps to\r\n * `PARAM_INVALID`. Coordinates are sent as numbers, never strings (§4.4.1.3).\r\n */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the quote as a table for `--format table`. Each vehicle class is one\r\n * row; amounts are decimal currency units (NOT cents) — printed verbatim.\r\n */\r\nfunction formatQuote(data: QuoteResponse): string {\r\n const classes: VehicleClass[] = data.vehicle_classes ?? [];\r\n if (classes.length === 0) {\r\n return Formatter.status('info', 'No vehicle classes available for this route');\r\n }\r\n\r\n const headers = ['Vehicle Class', 'Price', 'Currency', 'Quote ID', 'Pax', 'Luggage'];\r\n const rows = classes.map((vc) => [\r\n String(vc.vehicle_class ?? '-'),\r\n String(vc.price?.amount ?? '-'),\r\n String(vc.price?.currency ?? '-'),\r\n String(vc.price?.quote_id ?? '-'),\r\n String(vc.passenger_capacity ?? '-'),\r\n String(vc.luggage_capacity ?? '-'),\r\n ]);\r\n\r\n const lines: [string, string][] = [\r\n ['Airport transfer', String(data.is_airport_transfer ?? false)],\r\n ];\r\n if (data.airport_direction) {\r\n lines.push(['Airport direction', String(data.airport_direction)]);\r\n }\r\n if (data.meet_and_greet) {\r\n const mg = data.meet_and_greet;\r\n const mgPrice = mg.price ? ` (${mg.price.amount} ${mg.price.currency})` : '';\r\n lines.push(['Meet & greet', `${mg.available ? 'available' : 'unavailable'}${mgPrice}`]);\r\n }\r\n\r\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(lines)}`;\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife quote` — request fare quotes between two points (§4.4.1.3).\r\n *\r\n * Read-only (no idempotency key). Builds the `/ride/quote` body from flags\r\n * (coordinates number-ified, missing required → `PARAM_INVALID`), POSTs with\r\n * the `X-Api-Key` auth, and renders `QuoteResponse` via `renderWithContext`\r\n * (json carries the profile/endpoint envelope). The progress line is emitted\r\n * through `notify` so it goes to stderr and stays silent in json mode.\r\n */\r\nexport function registerQuoteCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('quote')\r\n .description('Request fare quotes for a ride between two points')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--pickup-lat <lat>', 'Pickup latitude')\r\n .option('--pickup-lng <lng>', 'Pickup longitude')\r\n .option('--pickup-name <name>', 'Pickup location name')\r\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\r\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\r\n .option('--dropoff-name <name>', 'Dropoff location name')\r\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\r\n .option('--passenger-name <name>', 'Lead passenger full name')\r\n .option('--passenger-phone <phone>', 'Passenger phone (E.164)')\r\n .option('--passenger-count <n>', 'Passenger count')\r\n .option('--luggage-count <n>', 'Luggage count')\r\n .option('--passenger-email <email>', 'Passenger email')\r\n .option('--children-count <n>', 'Children count')\r\n .option('--infant-count <n>', 'Infant count (passenger breakdown)')\r\n .option('--toddler-count <n>', 'Toddler count (passenger breakdown)');\r\n\r\n attachSchemaHelp(cmd, quoteSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. Coordinates are number-ified; pickup_time accepts the\r\n // literal \"now\" or epoch seconds. Missing required fields throw\r\n // PARAM_INVALID before any request is sent.\r\n const body: Record<string, unknown> = {\r\n pickup: {\r\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\r\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\r\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\r\n },\r\n dropoff: {\r\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\r\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\r\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\r\n },\r\n pickup_time:\r\n opts.pickupTime === 'now'\r\n ? 'now'\r\n : num(opts.pickupTime as string | undefined, 'pickup-time'),\r\n };\r\n\r\n // Optional passenger / luggage / children fields — included only when set.\r\n if (opts.passengerName) body.passenger_name = opts.passengerName as string;\r\n if (opts.passengerPhone) body.passenger_phone = opts.passengerPhone as string;\r\n if (opts.passengerCount !== undefined) {\r\n body.passenger_count = num(opts.passengerCount as string, 'passenger-count');\r\n }\r\n if (opts.luggageCount !== undefined) {\r\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\r\n }\r\n if (opts.childrenCount !== undefined) {\r\n body.children_count = num(opts.childrenCount as string, 'children-count');\r\n }\r\n if (opts.infantCount !== undefined) {\r\n body.infant_count = num(opts.infantCount as string, 'infant-count');\r\n }\r\n if (opts.toddlerCount !== undefined) {\r\n body.toddler_count = num(opts.toddlerCount as string, 'toddler-count');\r\n }\r\n if (opts.passengerEmail !== undefined) {\r\n body.passenger_email = opts.passengerEmail as string;\r\n }\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching quotes...');\r\n\r\n const result = await deps.apiClient.post<QuoteResponse>(\r\n '/ride/quote',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<QuoteResponse> = {\r\n data,\r\n text: () => formatQuote(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { BookResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, bookSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 2.2 / design §4.4.1.3) — a catalog code (exit 1), mirroring the\r\n * sibling `quote` command's convention.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Validate a passenger phone as E.164 shape (edge fail-fast). The authoritative\r\n * region-aware validity check (libphonenumber) runs server-side; this catches\r\n * obviously malformed input before a request is sent. Accepts spaces/dashes,\r\n * normalizes them away, and requires a leading \"+\" country code.\r\n */\r\nfunction phone(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n const cleaned = raw.replace(/[\\s-]/g, '');\r\n if (!/^\\+[1-9]\\d{7,14}$/.test(cleaned)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `--${flag} must be a valid international phone number, e.g. +14155552671.`,\r\n );\r\n }\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Number-ify a seat count and enforce the 0–5 range (design §4.4.1.3 book\r\n * schema). Out-of-range values map to `PARAM_INVALID`.\r\n */\r\nfunction seatCount(value: string, flag: string): number {\r\n const n = num(value, flag);\r\n if (!Number.isInteger(n) || n < 0 || n > 5) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer between 0 and 5.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render a booked ride as a key/value block for `--format table`. Amounts are\r\n * decimal currency units (NOT cents) — printed verbatim.\r\n */\r\nfunction formatBook(data: BookResponse): string {\r\n const lines: [string, string][] = [\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ['Scheduled', String(data.is_scheduled ?? false)],\r\n ['Order type', String(data.order_type ?? '-')],\r\n ];\r\n if (data.price) {\r\n lines.push(['Price', `${data.price.amount} ${data.price.currency}`]);\r\n if (data.price.quote_id) lines.push(['Quote ID', String(data.price.quote_id)]);\r\n }\r\n lines.push(['Payment status', String(data.payment_status ?? '-')]);\r\n // Mode-dependent: monthly_settlement returns billing_entry_id, pay_per_call\r\n // echoes back payment_order_id.\r\n if (data.billing_entry_id) lines.push(['Billing entry', String(data.billing_entry_id)]);\r\n if (data.payment_order_id) lines.push(['Payment order', String(data.payment_order_id)]);\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife book` — book a ride against a previously returned quote\r\n * (§4.4.1.3 book schema + §4.4.2.1). Write op (W/Y).\r\n *\r\n * Funding is decided server-side by the developer's `billing_mode`:\r\n * - monthly_settlement: no payment handle; fare is deducted from the\r\n * settlement account (payment_status=ON_ACCOUNT).\r\n * - pay_per_call: pass `--payment-order-id` (a PAID order from payment-cli),\r\n * and/or `--payment-method-id` to charge a specific already-bound card.\r\n * `--payment-method-id` is an opaque bound-card id (the same handle\r\n * `hotel-redaug create-order` / `flight-flink create-order` accept) — the CLI\r\n * still never accepts raw card data (PAN/CVV) in any form.\r\n *\r\n * `POST /ride/book` with `X-Api-Key` auth + the `Idempotency-Key` header (key\r\n * forwarded verbatim, never in the body). `--yes` skips the confirm; a missing\r\n * `--idempotency-key` under `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED`\r\n * before any request is sent. Renders `BookResponse` via `renderWithContext`\r\n * (json carries the profile/endpoint envelope); the progress line goes to\r\n * stderr via `notify` and stays silent in json mode.\r\n */\r\nexport function registerBookCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('book')\r\n .description('Book a ride using a quote_id returned by quote')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--quote-id <id>', 'Quote id from `ride-elife quote`')\r\n .option('--vehicle-class <class>', 'Chosen vehicle class')\r\n .option('--price-amount <amount>', 'Fare in decimal currency units (not cents)')\r\n .option('--price-currency <currency>', 'Currency code (default USD)')\r\n .option('--payment-order-id <id>', 'Paid payment order id (pay_per_call mode only)')\r\n .option(\r\n '--payment-method-id <id>',\r\n 'Bound payment method id to charge (pay_per_call mode only)',\r\n )\r\n .option(\r\n '--payment-token-id <id>',\r\n 'DEPRECATED — use `ride-elife create-order` + `pay-order` for network-token direct charge. ' +\r\n 'A single-step book carrying a network token hits Charge_Service strict order↔token ' +\r\n 'binding and is rejected server-side with a retriable=false guidance error. Kept only for ' +\r\n 'backward compatibility; monthly_settlement / EVO / no-credential booking still work via book.',\r\n )\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'EVO merchant transaction id of an already-authorised preauth (3DS challenge resume). ' +\r\n 'When set, the server reuses that authorization instead of creating a new one, ' +\r\n 'avoiding a second hold on the card (pay_per_call mode only).',\r\n )\r\n .option('--passenger-name <name>', 'Passenger full name')\r\n .option('--passenger-phone <phone>', 'Passenger phone')\r\n .option('--passenger-email <email>', 'Passenger email')\r\n .option('--luggage-count <n>', 'Luggage count')\r\n .option('--special-requests <text>', 'Free-text special requests')\r\n .option('--pickup-lat <lat>', 'Pickup latitude')\r\n .option('--pickup-lng <lng>', 'Pickup longitude')\r\n .option('--pickup-name <name>', 'Pickup location name')\r\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\r\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\r\n .option('--dropoff-name <name>', 'Dropoff location name')\r\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\r\n .option('--meet-and-greet', 'Enable meet & greet service')\r\n .option('--meet-and-greet-price <amount>', 'Meet & greet surcharge')\r\n .option('--welcome-sign <text>', 'Welcome sign text')\r\n .option('--child-seat-count <n>', 'Number of child seats needed (0-5)')\r\n .option('--infant-seat-count <n>', 'Number of infant seats needed (0-5)')\r\n .option('--toddler-seat-count <n>', 'Number of toddler seats needed (0-5)')\r\n .option('--arrival-flight-no <no>', 'Arrival flight number')\r\n .option('--arrival-airline <airline>', 'Arrival airline')\r\n .option('--departure-flight-no <no>', 'Departure flight number')\r\n .option('--departure-airline <airline>', 'Departure airline')\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, bookSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. Required fields throw PARAM_INVALID before any\r\n // request is sent (mirrors the sibling `quote` command). The body carries NO\r\n // raw card data; payment handles are limited to the opaque\r\n // payment_order_id / payment_method_id ids below.\r\n const quoteId = need(opts.quoteId as string | undefined, 'quote-id');\r\n const body: Record<string, unknown> = {\r\n quote_id: quoteId,\r\n vehicle_class: need(opts.vehicleClass as string | undefined, 'vehicle-class'),\r\n price_amount: num(opts.priceAmount as string | undefined, 'price-amount'),\r\n price_currency: (opts.priceCurrency as string | undefined) ?? 'USD',\r\n passenger_name: need(opts.passengerName as string | undefined, 'passenger-name'),\r\n passenger_phone: phone(opts.passengerPhone as string | undefined, 'passenger-phone'),\r\n };\r\n\r\n // Optional payment handles for pay_per_call. `payment_method_id` is an opaque\r\n // bound-card id; raw card data is never accepted nor forwarded.\r\n // monthly_settlement omits both entirely.\r\n if (opts.paymentOrderId) body.payment_order_id = opts.paymentOrderId as string;\r\n if (opts.paymentMethodId) body.payment_method_id = opts.paymentMethodId as string;\r\n // 【已废弃】network-token 直扣请改走两步主路径:create-order 锁单取 order_ref → pay-order 直扣。\r\n // 这里仍原样透传 payment_token_id 以保持向后兼容;服务端会对单步 book 携带令牌的请求返回\r\n // retriable=false 的引导错误(指向 create-order + pay-order),不扣款、不建行程、不落单。\r\n if (opts.paymentTokenId) body.payment_token_id = opts.paymentTokenId as string;\r\n // 3DS 挑战续单凭证:持卡人完成认证后带回该交易号,服务端复用那笔已授权的预授权,\r\n // 不再新发起一次(否则又拿到新挑战页且重复冻结资金)。\r\n if (opts.authorizedMerchantTransId) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 归因标签(可选):非空才写入,缺省保持无归属。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n if (opts.passengerEmail) body.passenger_email = opts.passengerEmail as string;\r\n if (opts.luggageCount !== undefined) {\r\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\r\n }\r\n if (opts.specialRequests) body.special_requests = opts.specialRequests as string;\r\n\r\n // Pickup / dropoff / pickup_time are included only when supplied (they must\r\n // match the originating quote). Coordinates are number-ified.\r\n if (opts.pickupLat || opts.pickupLng || opts.pickupName) {\r\n body.pickup = {\r\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\r\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\r\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\r\n };\r\n }\r\n if (opts.dropoffLat || opts.dropoffLng || opts.dropoffName) {\r\n body.dropoff = {\r\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\r\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\r\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\r\n };\r\n }\r\n if (opts.pickupTime) {\r\n body.pickup_time =\r\n opts.pickupTime === 'now' ? 'now' : num(opts.pickupTime as string, 'pickup-time');\r\n }\r\n\r\n if (opts.meetAndGreet) body.meet_and_greet = true;\r\n if (opts.meetAndGreetPrice !== undefined) {\r\n body.meet_and_greet_price = num(opts.meetAndGreetPrice as string, 'meet-and-greet-price');\r\n }\r\n if (opts.welcomeSign) body.welcome_sign = opts.welcomeSign as string;\r\n if (opts.childSeatCount !== undefined) {\r\n body.child_seat_count = seatCount(opts.childSeatCount as string, 'child-seat-count');\r\n }\r\n if (opts.infantSeatCount !== undefined) {\r\n body.infant_seat_count = seatCount(opts.infantSeatCount as string, 'infant-seat-count');\r\n }\r\n if (opts.toddlerSeatCount !== undefined) {\r\n body.toddler_seat_count = seatCount(opts.toddlerSeatCount as string, 'toddler-seat-count');\r\n }\r\n if (opts.arrivalFlightNo || opts.arrivalAirline) {\r\n body.arrival_flight = {\r\n flight_no: opts.arrivalFlightNo as string | undefined,\r\n airline: opts.arrivalAirline as string | undefined,\r\n };\r\n }\r\n if (opts.departureFlightNo || opts.departureAirline) {\r\n body.departure_flight = {\r\n flight_no: opts.departureFlightNo as string | undefined,\r\n airline: opts.departureAirline as string | undefined,\r\n };\r\n }\r\n\r\n // Confirm before the write unless --yes. The warning/prompt go to stderr;\r\n // declining maps to CLIENT_ABORTED (exit 5) via the top-level envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Book ride with quote ${quoteId}?`,\r\n default: true,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Booking cancelled by user.');\r\n }\r\n }\r\n\r\n // Idempotency key (requirement 5.3): resolved before the request. Under\r\n // --yes a missing key is a hard error and no request is sent. The key is\r\n // sent as a header, never in the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife book',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Booking ride...');\r\n\r\n const result = await deps.apiClient.post<BookResponse>(\r\n '/ride/book',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<BookResponse> = {\r\n data,\r\n text: () => formatBook(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","/**\r\n * Idempotency key resolution for write commands (`ride-elife book` / `cancel`)\r\n * — requirement 5.3 / §6.1, design Property 3.\r\n *\r\n * The error type is reused from `@agenzo/cli-core` (`IdempotencyKeyRequiredError`\r\n * → `PARAM_IDEMPOTENCY_KEY_REQUIRED`) so the merchant CLI does not re-define it.\r\n * The resolve/normalize logic stays in the app because it is merchant-domain\r\n * policy (per requirement 4.4): the §6.1 key format `[A-Za-z0-9_-]{1,128}`, the\r\n * `--yes`-missing hard error vs. interactive prompt branch, and the rule that\r\n * the key is forwarded verbatim as the `Idempotency-Key` HTTP header and is\r\n * never placed in the request body.\r\n *\r\n * The CLI NEVER auto-generates a key: under `--yes` a missing key is a hard\r\n * error thrown before any request is sent; otherwise the caller is prompted.\r\n */\r\nimport {\r\n CliError,\r\n IdempotencyKeyRequiredError,\r\n PromptEngine,\r\n} from '@agenzo/cli-core';\r\n\r\n/**\r\n * §6.1 idempotency key format: 1–128 characters drawn from `[A-Za-z0-9_-]`.\r\n */\r\nexport const IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;\r\n\r\n/** Human-readable rule reused in validation messages and prompt feedback. */\r\nexport const IDEMPOTENCY_KEY_RULE = 'Use 1-128 characters from [A-Za-z0-9_-].';\r\n\r\n/**\r\n * Validate + normalize a caller-supplied idempotency key. A malformed key maps\r\n * to `PARAM_INVALID` (catalog code, exit 1) — never silently corrected and\r\n * never auto-generated.\r\n */\r\nexport function normalizeIdempotencyKey(key: string): string {\r\n const trimmed = key.trim();\r\n if (!IDEMPOTENCY_KEY_PATTERN.test(trimmed)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `Invalid idempotency key: \"${key}\". ${IDEMPOTENCY_KEY_RULE}`,\r\n );\r\n }\r\n return trimmed;\r\n}\r\n\r\n/**\r\n * Resolve the idempotency key for a write operation (requirement 5.3). The CLI\r\n * never generates one:\r\n * - supplied via `--idempotency-key` → validated + normalized;\r\n * - absent under `--yes` → hard error (`PARAM_IDEMPOTENCY_KEY_REQUIRED`,\r\n * reused from cli-core) thrown before any request is sent;\r\n * - absent otherwise → collected interactively, then validated.\r\n *\r\n * The returned key is forwarded verbatim as the `Idempotency-Key` header by the\r\n * caller — it never enters the request body.\r\n */\r\nexport async function resolveIdempotencyKey(\r\n flagValue: string | undefined,\r\n opts: { yes: boolean; commandPath: string },\r\n): Promise<string> {\r\n if (flagValue !== undefined) {\r\n return normalizeIdempotencyKey(flagValue);\r\n }\r\n if (opts.yes) {\r\n throw new IdempotencyKeyRequiredError(opts.commandPath);\r\n }\r\n const entered = await PromptEngine.resolveInput(undefined, {\r\n message: 'Idempotency key (unique per write, for safe retry):',\r\n validate: (v) => IDEMPOTENCY_KEY_PATTERN.test(v.trim()) || IDEMPOTENCY_KEY_RULE,\r\n });\r\n return normalizeIdempotencyKey(entered);\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { CreateRideOrderResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, rideCreateOrderSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (a catalog code, exit 1), mirroring the sibling `book` / `quote` commands.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Validate a passenger phone as E.164 shape (edge fail-fast). The authoritative\r\n * region-aware validity check runs server-side; this catches obviously\r\n * malformed input before a request is sent. Accepts spaces/dashes, normalizes\r\n * them away, and requires a leading \"+\" country code.\r\n */\r\nfunction phone(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n const cleaned = raw.replace(/[\\s-]/g, '');\r\n if (!/^\\+[1-9]\\d{7,14}$/.test(cleaned)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `--${flag} must be a valid international phone number, e.g. +14155552671.`,\r\n );\r\n }\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Number-ify a seat count and enforce the 0–5 range (mirrors `book`).\r\n * Out-of-range values map to `PARAM_INVALID`.\r\n */\r\nfunction seatCount(value: string, flag: string): number {\r\n const n = num(value, flag);\r\n if (!Number.isInteger(n) || n < 0 || n > 5) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer between 0 and 5.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the locked order as a key/value block for `--format table`. Amounts\r\n * are decimal currency units (NOT cents) — printed verbatim. The order\r\n * reference is resolved from `order_ref` when present, else `order_id` (both\r\n * carry the authoritative rio_… value).\r\n */\r\nfunction formatCreateOrder(data: CreateRideOrderResponse): string {\r\n const orderRef = String(data.order_ref ?? data.order_id ?? '-');\r\n const lines: [string, string][] = [\r\n ['Order ref', orderRef],\r\n ['Status', String(data.status ?? '-')],\r\n ['Payment status', String(data.payment_status ?? '-')],\r\n ];\r\n if (data.price) {\r\n lines.push(['Amount', `${data.price.amount} ${data.price.currency}`]);\r\n if (data.price.quote_id) lines.push(['Quote ID', String(data.price.quote_id)]);\r\n }\r\n if (data.is_scheduled !== undefined) lines.push(['Scheduled', String(data.is_scheduled)]);\r\n if (data.order_type) lines.push(['Order type', String(data.order_type)]);\r\n\r\n return [\r\n Formatter.keyValue(lines),\r\n Formatter.status(\r\n 'info',\r\n `Fare locked (AWAITING_PAYMENT) — bind ${orderRef} as the network token external_transaction_id, ` +\r\n `then settle with 'ride-elife pay-order --order-id ${orderRef}'. No funds moved yet.`,\r\n ),\r\n ].join('\\n\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife create-order` — lock a ride fare WITHOUT charging (the first step\r\n * of the two-step network-token direct-charge flow;\r\n * ride-network-token-direct-charge R11.1). Mirrors\r\n * `flight-flink create-order` / `hotel-redaug create-order`: the order enters\r\n * AWAITING_PAYMENT / payment_status=PENDING, NO funds move, and eLife is NOT\r\n * called. It returns the authoritative `order_ref` (rio_…) so the caller can\r\n * mint a network token bound to it (external_transaction_id = order_ref) and\r\n * then settle via `ride-elife pay-order`.\r\n *\r\n * Deliberately carries the SAME trip/quote/passenger/surcharge context as\r\n * `book` MINUS every payment credential (payment_order_id / payment_method_id /\r\n * payment_token_id / authorized_merchant_trans_id) — funding is deferred to\r\n * `pay-order`, so no payment handle is accepted here.\r\n *\r\n * `POST /ride/create-order` with `X-Api-Key` auth + the `Idempotency-Key`\r\n * header (key forwarded verbatim, never in the body). Locking a fare is a real\r\n * commitment (though not a charge), so the non-`--yes` path confirms (restating\r\n * amount/currency) before the write; `--yes` skips it and a missing\r\n * `--idempotency-key` under `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED`\r\n * before any request is sent. A declined confirm maps to `CLIENT_ABORTED`.\r\n */\r\nexport function registerRideCreateOrderCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('create-order')\r\n .description('Lock a ride fare without charging (await payment); returns the order_ref to pay')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--quote-id <id>', 'Quote id from `ride-elife quote`')\r\n .option('--vehicle-class <class>', 'Chosen vehicle class')\r\n .option('--price-amount <amount>', 'Fare in decimal currency units (not cents)')\r\n .option('--price-currency <currency>', 'Currency code (default USD)')\r\n .option('--passenger-name <name>', 'Passenger full name')\r\n .option('--passenger-phone <phone>', 'Passenger phone')\r\n .option('--passenger-email <email>', 'Passenger email')\r\n .option('--luggage-count <n>', 'Luggage count')\r\n .option('--special-requests <text>', 'Free-text special requests')\r\n .option('--pickup-lat <lat>', 'Pickup latitude')\r\n .option('--pickup-lng <lng>', 'Pickup longitude')\r\n .option('--pickup-name <name>', 'Pickup location name')\r\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\r\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\r\n .option('--dropoff-name <name>', 'Dropoff location name')\r\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\r\n .option('--meet-and-greet', 'Enable meet & greet service')\r\n .option('--meet-and-greet-price <amount>', 'Meet & greet surcharge')\r\n .option('--welcome-sign <text>', 'Welcome sign text')\r\n .option('--child-seat-count <n>', 'Number of child seats needed (0-5)')\r\n .option('--infant-seat-count <n>', 'Number of infant seats needed (0-5)')\r\n .option('--toddler-seat-count <n>', 'Number of toddler seats needed (0-5)')\r\n .option('--arrival-flight-no <no>', 'Arrival flight number')\r\n .option('--arrival-airline <airline>', 'Arrival airline')\r\n .option('--departure-flight-no <no>', 'Departure flight number')\r\n .option('--departure-airline <airline>', 'Departure airline')\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, rideCreateOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. Required fields throw PARAM_INVALID before any request\r\n // is sent (mirrors the sibling `book` command). The body carries NO payment\r\n // credential of any kind — create-order only locks the fare; funding is\r\n // deferred to `pay-order`.\r\n const quoteId = need(opts.quoteId as string | undefined, 'quote-id');\r\n const priceAmount = num(opts.priceAmount as string | undefined, 'price-amount');\r\n const priceCurrency = (opts.priceCurrency as string | undefined) ?? 'USD';\r\n const body: Record<string, unknown> = {\r\n quote_id: quoteId,\r\n vehicle_class: need(opts.vehicleClass as string | undefined, 'vehicle-class'),\r\n price_amount: priceAmount,\r\n price_currency: priceCurrency,\r\n passenger_name: need(opts.passengerName as string | undefined, 'passenger-name'),\r\n passenger_phone: phone(opts.passengerPhone as string | undefined, 'passenger-phone'),\r\n passenger_email: need(opts.passengerEmail as string | undefined, 'passenger-email'),\r\n };\r\n\r\n // 归因标签(可选):非空才写入,缺省保持无归属。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n if (opts.luggageCount !== undefined) {\r\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\r\n }\r\n if (opts.specialRequests) body.special_requests = opts.specialRequests as string;\r\n\r\n // Pickup / dropoff / pickup_time are included only when supplied (they must\r\n // match the originating quote). Coordinates are number-ified.\r\n if (opts.pickupLat || opts.pickupLng || opts.pickupName) {\r\n body.pickup = {\r\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\r\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\r\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\r\n };\r\n }\r\n if (opts.dropoffLat || opts.dropoffLng || opts.dropoffName) {\r\n body.dropoff = {\r\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\r\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\r\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\r\n };\r\n }\r\n if (opts.pickupTime) {\r\n body.pickup_time =\r\n opts.pickupTime === 'now' ? 'now' : num(opts.pickupTime as string, 'pickup-time');\r\n }\r\n\r\n if (opts.meetAndGreet) body.meet_and_greet = true;\r\n if (opts.meetAndGreetPrice !== undefined) {\r\n body.meet_and_greet_price = num(opts.meetAndGreetPrice as string, 'meet-and-greet-price');\r\n }\r\n if (opts.welcomeSign) body.welcome_sign = opts.welcomeSign as string;\r\n if (opts.childSeatCount !== undefined) {\r\n body.child_seat_count = seatCount(opts.childSeatCount as string, 'child-seat-count');\r\n }\r\n if (opts.infantSeatCount !== undefined) {\r\n body.infant_seat_count = seatCount(opts.infantSeatCount as string, 'infant-seat-count');\r\n }\r\n if (opts.toddlerSeatCount !== undefined) {\r\n body.toddler_seat_count = seatCount(opts.toddlerSeatCount as string, 'toddler-seat-count');\r\n }\r\n if (opts.arrivalFlightNo || opts.arrivalAirline) {\r\n body.arrival_flight = {\r\n flight_no: opts.arrivalFlightNo as string | undefined,\r\n airline: opts.arrivalAirline as string | undefined,\r\n };\r\n }\r\n if (opts.departureFlightNo || opts.departureAirline) {\r\n body.departure_flight = {\r\n flight_no: opts.departureFlightNo as string | undefined,\r\n airline: opts.departureAirline as string | undefined,\r\n };\r\n }\r\n\r\n // Confirm before the write unless --yes. Locking a fare is a commitment but\r\n // NOT a charge — the prompt restates the amount and says so. The prompt goes\r\n // to stderr; declining maps to CLIENT_ABORTED (exit 5) via the top-level\r\n // envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Lock this ride fare for ${priceAmount} ${priceCurrency}? This reserves the order (AWAITING_PAYMENT) but does NOT charge yet.`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Order creation aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key: resolved before the request. Under --yes a missing key is\r\n // a hard error and no request is sent. The key is sent as a header, never in\r\n // the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife create-order',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Locking ride fare...');\r\n\r\n const result = await deps.apiClient.post<CreateRideOrderResponse>(\r\n '/ride/create-order',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CreateRideOrderResponse> = {\r\n data,\r\n text: () => formatCreateOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { PayRideOrderResponse } from '../types/api.js';\r\nimport { PRICE_ANNOTATION_FLAGS, applyPriceAnnotation } from '../price-annotation.js';\r\nimport { attachSchemaHelp, ridePayOrderSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (a catalog code, exit 1), mirroring the sibling `create-order` / `book`\r\n * commands.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Enforce the exactly-one payment-credential rule (requirement 11.5). The two-step\r\n * pay MUST carry exactly one of `--payment-token-id` (network-token direct charge,\r\n * the main path) or `--payment-method-id` (EVO bound-card fallback). Both missing\r\n * and both present are rejected LOCALLY with a distinguishable `PARAM_INVALID`\r\n * error BEFORE any request is sent, so `Ride_Service.pay` is never called with an\r\n * ambiguous credential set. The two branches carry distinct messages so the\r\n * offending condition (neither vs. both) is itself distinguishable.\r\n */\r\nfunction assertExactlyOneCredential(\r\n paymentTokenId: string | undefined,\r\n paymentMethodId: string | undefined,\r\n): void {\r\n const hasToken = paymentTokenId !== undefined;\r\n const hasMethod = paymentMethodId !== undefined;\r\n if (!hasToken && !hasMethod) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Invalid payment credential options: provide exactly one of --payment-token-id ' +\r\n '(network-token direct charge) or --payment-method-id (EVO bound card). Neither was given.',\r\n );\r\n }\r\n if (hasToken && hasMethod) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Invalid payment credential options: --payment-token-id and --payment-method-id are ' +\r\n 'mutually exclusive — provide exactly one, not both.',\r\n );\r\n }\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the settled order as a key/value block for `--format table`. Amounts\r\n * are decimal currency units (NOT cents) — printed verbatim. The order reference\r\n * is resolved from `order_ref` when present, else `order_id` (both carry the\r\n * authoritative rio_… value). Status / payment status are echoed from the\r\n * response (a successful settlement returns PAID / SETTLED — requirement 11.4).\r\n */\r\nfunction formatPayOrder(data: PayRideOrderResponse): string {\r\n const orderRef = String(data.order_ref ?? data.order_id ?? '-');\r\n const lines: [string, string][] = [\r\n ['Order ref', orderRef],\r\n ['Status', String(data.status ?? '-')],\r\n ['Payment status', String(data.payment_status ?? '-')],\r\n ];\r\n if (data.ride_id !== undefined) lines.push(['Ride ID', String(data.ride_id)]);\r\n if (data.payment_channel) lines.push(['Payment channel', String(data.payment_channel)]);\r\n if (data.price) {\r\n lines.push(['Amount', `${data.price.amount} ${data.price.currency}`]);\r\n if (data.price.quote_id) lines.push(['Quote ID', String(data.price.quote_id)]);\r\n }\r\n // 网络令牌 3DS 挑战(status=AUTHENTICATION_REQUIRED):透出续付句柄与挑战地址。\r\n if (data.charge_no) lines.push(['Charge no', String(data.charge_no)]);\r\n if (data.three_ds_url) lines.push(['3DS URL', String(data.three_ds_url)]);\r\n\r\n // 挑战态不是终态成功:状态行按 AUTHENTICATION_REQUIRED 提示需完成认证,否则报结算成功。\r\n if (String(data.status) === 'AUTHENTICATION_REQUIRED') {\r\n return [\r\n Formatter.keyValue(lines),\r\n Formatter.status(\r\n 'warning',\r\n `Order ${orderRef} needs cardholder 3DS — open the 3DS URL, then resume pay-order with `\r\n + `--authorized-charge-no ${data.charge_no ?? ''}.`,\r\n ),\r\n ].join('\\n\\n');\r\n }\r\n\r\n return [\r\n Formatter.keyValue(lines),\r\n Formatter.status(\r\n 'success',\r\n `Order ${orderRef} settled — ${data.status ?? 'PAID'} / ${data.payment_status ?? 'SETTLED'}.`,\r\n ),\r\n ].join('\\n\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife pay-order` — settle a locked ride order by `--order-id` (the\r\n * second step of the two-step network-token direct-charge flow;\r\n * ride-network-token-direct-charge R11.2/R11.4/R11.5). Mirrors\r\n * `flight-flink pay-order` / `hotel-redaug pay-order`: funds move HERE (not in\r\n * create-order), and on success the order is pushed AWAITING_PAYMENT → PAID /\r\n * payment_status=SETTLED.\r\n *\r\n * Exactly one payment credential is required (requirement 11.5, mutual\r\n * exclusion): `--payment-token-id` (network-token direct charge — the main\r\n * path, `charge(order_id=order_ref)` triggers strict order↔token binding) OR\r\n * `--payment-method-id` (EVO bound-card fallback). Both missing and both present\r\n * are rejected LOCALLY with a distinguishable `PARAM_INVALID` error before any\r\n * request is sent — `Ride_Service.pay` is never called with an ambiguous\r\n * credential set. `--authorized-merchant-trans-id` resumes an EVO 3DS challenge.\r\n *\r\n * `POST /ride/pay` with `X-Api-Key` auth + the `Idempotency-Key` header (key\r\n * forwarded verbatim, never in the body). The order reference and payment\r\n * credentials travel in the body. Since this step actually charges the card,\r\n * the non-`--yes` path confirms before the write; `--yes` skips it and a missing\r\n * `--idempotency-key` under `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED`\r\n * before any request is sent. A declined confirm maps to `CLIENT_ABORTED`.\r\n */\r\nexport function registerRidePayOrderCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('pay-order')\r\n .description('Settle a locked ride order by --order-id (charges the card, creates the ride)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The order_ref (rio_…) from create-order to settle')\r\n .option(\r\n '--payment-token-id <id>',\r\n 'Network-token id (unionpay/visa direct-charge path). Exactly one of ' +\r\n '--payment-token-id / --payment-method-id is required.',\r\n )\r\n .option(\r\n '--payment-method-id <id>',\r\n 'Bound-card id to charge via EVO preauth+capture (fallback path). Exactly one of ' +\r\n '--payment-token-id / --payment-method-id is required.',\r\n )\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'Resume an EVO-card 3DS challenge: merchant trans id of an already-authorised preauth',\r\n )\r\n .option(\r\n '--authenticate',\r\n 'Opt-in to require cardholder 3DS on the network-token direct charge (--payment-token-id, EVO/Mastercard). When a step-up is needed the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume with --authorized-charge-no. Default off = frictionless.',\r\n )\r\n .option(\r\n '--return-url <url>',\r\n 'Optional 3DS/passkey return URL for the network-token authenticate path (falls back to the platform EVO_3DS_RETURN_URL)',\r\n )\r\n .option(\r\n '--authorized-charge-no <no>',\r\n 'Resume a network-token 3DS challenge: charge_no returned by a prior AUTHENTICATION_REQUIRED response (settled via ChargeService.resume_token). When set, the exactly-one-credential rule is relaxed (this is a continuation, not a fresh charge).',\r\n )\r\n .option(\r\n '--evo-explicit',\r\n '[方案 B/R16] Explicit opt-in to settle this pay_per_call ride via the EVO bound-card fallback rail. Set ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side.',\r\n )\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n )\r\n .option(\r\n '--original-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['original-amount-cents'].description,\r\n )\r\n .option(\r\n '--discount-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['discount-amount-cents'].description,\r\n );\r\n\r\n attachSchemaHelp(cmd, ridePayOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n // Validate the target order + payment credentials FIRST — before resolving\r\n // the API key or prompting — so an invalid credential set fails fast and\r\n // never triggers a request to Ride_Service.pay (requirement 11.5).\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n const paymentTokenId = opts.paymentTokenId as string | undefined;\r\n const paymentMethodId = opts.paymentMethodId as string | undefined;\r\n const authorizedChargeNo = opts.authorizedChargeNo as string | undefined;\r\n // 3DS 续付(--authorized-charge-no)是已放行网络令牌扣款的收尾,本身即凭证,不再要求\r\n // token/method 二选一(首扣时已校验过);仅首扣路径强制 exactly-one。\r\n if (authorizedChargeNo === undefined) {\r\n assertExactlyOneCredential(paymentTokenId, paymentMethodId);\r\n }\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. The order reference and the (validated) exactly-one\r\n // payment credential travel in the body; the amount/currency are NOT sent —\r\n // the platform settles at the order's locked authoritative amount and the\r\n // token's minted amount, never a caller-supplied value (requirement 2.6).\r\n const body: Record<string, unknown> = { order_id: orderId };\r\n if (paymentTokenId !== undefined) body.payment_token_id = paymentTokenId;\r\n if (paymentMethodId !== undefined) body.payment_method_id = paymentMethodId;\r\n if (opts.authorizedMerchantTransId !== undefined) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 网络令牌支付时 3DS(opt-in):仅置位时透传 authenticate=true;return_url 可选(缺省平台\r\n // 回落 EVO_3DS_RETURN_URL);authorized_charge_no 是续付句柄。\r\n if (opts.authenticate) body.authenticate = true;\r\n if (opts.returnUrl !== undefined) body.return_url = opts.returnUrl as string;\r\n if (authorizedChargeNo !== undefined) body.authorized_charge_no = authorizedChargeNo;\r\n // 方案 B/R16 显式 EVO 选择信号:仅在置位时透传 evo_explicit=true;缺省则不发(平台默认 false)。\r\n if (opts.evoExplicit) body.evo_explicit = true;\r\n // 价格批注(原价 / 优惠,纯记录):落订单 auth_snapshot + 统一流水并在订单详情回显,\r\n // 不进网关报文、不参与「实扣额 == 锁单权威价」那道核验(金额仍不由调用方决定,R2.6)。\r\n applyPriceAnnotation(body, opts);\r\n\r\n // Confirm before the write unless --yes. This step actually moves money\r\n // (network-token direct charge or EVO preauth+capture) and creates the ride\r\n // upstream. The prompt goes to stderr; declining maps to CLIENT_ABORTED\r\n // (exit 5) via the top-level envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Settle ride order ${orderId}? This charges the card and creates the ride (AWAITING_PAYMENT → PAID).`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Payment aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key: resolved before the request. Under --yes a missing key is\r\n // a hard error and no request is sent. The key is sent as a header, never in\r\n // the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife pay-order',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Settling ride order...');\r\n\r\n const result = await deps.apiClient.post<PayRideOrderResponse>(\r\n '/ride/pay',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<PayRideOrderResponse> = {\r\n data,\r\n text: () => formatPayOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { GetOrderResponse } from '../types/api.js';\r\nimport {\r\n DEFAULT_WATCH_INTERVAL_SECONDS,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n resolveSeconds,\r\n watchRideStatus,\r\n} from './watch.js';\r\nimport { attachSchemaHelp, rideGetSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 3.1 / §4.4.1.3) — a catalog code (exit 1), mirroring the\r\n * sibling quote/book commands' convention.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary, non-watch path only)\r\n// ============================================================\r\n\r\n/**\r\n * Render a single ride order as a key/value block for `--format table`.\r\n * Pickup/dropoff are `from_location`/`to_location` (v3 snake_case, NOT the\r\n * elife `from`/`to` aliases). Amounts are decimal currency units (NOT cents).\r\n */\r\nfunction formatGetOrder(data: GetOrderResponse): string {\r\n const lines: [string, string][] = [\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ];\r\n if (data.source) lines.push(['Source', String(data.source)]);\r\n if (data.is_scheduled !== undefined) lines.push(['Scheduled', String(data.is_scheduled)]);\r\n if (data.from_location) {\r\n lines.push(['From', String(data.from_location.name ?? '-')]);\r\n }\r\n if (data.to_location) {\r\n lines.push(['To', String(data.to_location.name ?? '-')]);\r\n }\r\n if (data.pickup_time !== undefined) lines.push(['Pickup time', String(data.pickup_time)]);\r\n if (data.vehicle_class) lines.push(['Vehicle class', String(data.vehicle_class)]);\r\n if (data.price) {\r\n lines.push(['Price', `${data.price.amount} ${data.price.currency}`]);\r\n }\r\n if (data.final_amount !== undefined && data.final_amount !== null) {\r\n lines.push(['Final amount', String(data.final_amount)]);\r\n }\r\n if (data.final_settlement_status) {\r\n lines.push(['Settlement', String(data.final_settlement_status)]);\r\n }\r\n if (data.driver) {\r\n const driver = data.driver;\r\n const phone = driver.phone_number ? ` (${driver.phone_number})` : '';\r\n lines.push(['Driver', `${driver.name ?? '-'}${phone}`]);\r\n }\r\n if (data.vehicle) {\r\n const v = data.vehicle;\r\n const desc = [v.color, v.make, v.model].filter(Boolean).join(' ') || '-';\r\n const plate = v.license_plate ? ` [${v.license_plate}]` : '';\r\n lines.push(['Vehicle', `${desc}${plate}`]);\r\n }\r\n if (data.created_at) lines.push(['Created at', String(data.created_at)]);\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife get` — fetch a ride order status by id (§4.4.1.3 get schema).\r\n * Read-only (no idempotency key).\r\n *\r\n * Two modes:\r\n * - Non-`--watch`: a single `GET /ride/<id>/status` → `CommandResult` +\r\n * `renderWithContext` (json carries the profile/endpoint envelope).\r\n * - `--watch`: hands off to `watch.ts`, which polls until a terminal status\r\n * or timeout, writing each result as ONE NDJSON line on stdout. The watch\r\n * stream is NOT wrapped in the profile/endpoint envelope (it is a line\r\n * stream); on timeout the final line is `{ watch_status:'timeout', ... }`\r\n * (design Property 2).\r\n *\r\n * Named `registerRideGetCommand` to avoid clashing with the `services get`\r\n * registration.\r\n */\r\nexport function registerRideGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('get')\r\n .description('Retrieve a ride order status by id (repeatable for polling)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Ride order id (the ride_id returned by `ride-elife book`)')\r\n .option('--watch', 'Poll until a terminal status, emitting one NDJSON line per update')\r\n .option(\r\n '--watch-interval <seconds>',\r\n `Seconds between polls when --watch is set (default ${DEFAULT_WATCH_INTERVAL_SECONDS})`,\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n `Max seconds to poll before giving up (default ${DEFAULT_WATCH_TIMEOUT_SECONDS})`,\r\n );\r\n\r\n attachSchemaHelp(cmd, rideGetSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n\r\n // --watch: NDJSON line stream (no profile/endpoint envelope). The stream\r\n // itself is the progress, so no spinner/notify is emitted.\r\n if (opts.watch) {\r\n await watchRideStatus(deps.apiClient, apiKey, orderId, {\r\n intervalSeconds: resolveSeconds(\r\n opts.watchInterval as string | undefined,\r\n DEFAULT_WATCH_INTERVAL_SECONDS,\r\n ),\r\n timeoutSeconds: resolveSeconds(\r\n opts.watchTimeout as string | undefined,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n ),\r\n });\r\n return;\r\n }\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching ride status...');\r\n\r\n const result = await deps.apiClient.get<GetOrderResponse>(\r\n `/ride/${encodeURIComponent(orderId)}/status`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<GetOrderResponse> = {\r\n data,\r\n text: () => formatGetOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { CancelResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, cancelSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 3.3 / §4.4.1.3 cancel schema) — a catalog code (exit 1),\r\n * mirroring the sibling quote/book/get commands' convention.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render a cancelled ride as a key/value block for `--format table`. Amounts\r\n * are decimal currency units (NOT cents) — printed verbatim. `cancellation`\r\n * may be null when the backend reports no fee/reversal breakdown.\r\n */\r\nfunction formatCancel(data: CancelResponse): string {\r\n const lines: [string, string][] = [\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Status', String(data.ride_stat ?? '-')],\r\n ];\r\n if (data.cancellation) {\r\n const c = data.cancellation;\r\n lines.push(['Cancellation fee', `${c.cancellation_fee} ${c.currency}`]);\r\n lines.push(['Reversal amount', `${c.reversal_amount} ${c.currency}`]);\r\n }\r\n if (data.refund_amount !== undefined && data.refund_amount !== null) {\r\n lines.push(['Refund amount', String(data.refund_amount)]);\r\n }\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife cancel` — cancel a ride order by id (§4.4.1.3 cancel schema).\r\n * Write op (W/Y).\r\n *\r\n * `POST /ride/<order-id>/cancel` with NO request body, `X-Api-Key` auth, and\r\n * the `Idempotency-Key` header (key forwarded verbatim, never in the body).\r\n * Cancelling may incur a fee, so the non-`--yes` path MUST confirm before the\r\n * write; `--yes` skips the confirmation. A missing `--idempotency-key` under\r\n * `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED` before any request is sent;\r\n * non-`--yes` prompts for it. Declining the confirmation maps to\r\n * `CLIENT_ABORTED` (exit 5) via the top-level envelope. Renders\r\n * `CancelResponse` via `renderWithContext` (json carries the profile/endpoint\r\n * envelope); the progress line goes to stderr via `notify` and stays silent in\r\n * json mode.\r\n */\r\nexport function registerCancelCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('cancel')\r\n .description('Cancel a ride order by id (may incur a cancellation fee)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Ride order id to cancel (the ride_id returned by book)')\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, cancelSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required input throws PARAM_INVALID before any request is sent (mirrors\r\n // the sibling get/book commands).\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n\r\n // Confirm before the write unless --yes. Cancelling may incur a fee, so the\r\n // prompt warns explicitly (requirement 3.3). The warning/prompt go to\r\n // stderr; declining maps to CLIENT_ABORTED (exit 5) via the top-level\r\n // envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Cancel ride ${orderId}? This may incur a fee.`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Cancellation aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key (requirement 5.3): resolved before the request. Under\r\n // --yes a missing key is a hard error and no request is sent. The key is\r\n // sent as a header, never in the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife cancel',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Cancelling ride...');\r\n\r\n // POST /ride/<id>/cancel carries NO body — only the Idempotency-Key header.\r\n const result = await deps.apiClient.post<CancelResponse>(\r\n `/ride/${encodeURIComponent(orderId)}/cancel`,\r\n { type: 'api-key', key: apiKey },\r\n undefined,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CancelResponse> = {\r\n data,\r\n text: () => formatCancel(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { UpdateResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, rideUpdateSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (a catalog code, exit 1), mirroring the sibling get/cancel commands.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Parse a numeric flag, rejecting non-numbers as `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number | undefined {\r\n if (value === undefined) return undefined;\r\n const parsed = Number(value);\r\n if (!Number.isFinite(parsed)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return parsed;\r\n}\r\n\r\n/** Parse an integer flag, rejecting non-integers as `PARAM_INVALID`. */\r\nfunction int(value: string | undefined, flag: string): number | undefined {\r\n const parsed = num(value, flag);\r\n if (parsed === undefined) return undefined;\r\n if (!Number.isInteger(parsed)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer.`);\r\n }\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Epoch seconds or the literal `now` (same convention as book/quote). Anything\r\n * else is `PARAM_INVALID` — the CLI does not guess at date strings.\r\n */\r\nfunction pickupTime(value: string | undefined): number | string | undefined {\r\n if (value === undefined) return undefined;\r\n if (value === 'now') return 'now';\r\n const parsed = Number(value);\r\n if (!Number.isInteger(parsed)) {\r\n throw new CliError('PARAM_INVALID', \"--pickup-time must be epoch seconds or 'now'.\");\r\n }\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Build a location object only when at least one of its parts was passed, and\r\n * require all three parts together — a half-specified point would silently\r\n * change the route to something the user never asked for.\r\n */\r\nfunction location(\r\n lat: string | undefined,\r\n lng: string | undefined,\r\n name: string | undefined,\r\n side: 'pickup' | 'dropoff',\r\n): { lat: number; lng: number; name: string } | undefined {\r\n if (lat === undefined && lng === undefined && name === undefined) return undefined;\r\n if (lat === undefined || lng === undefined || name === undefined) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `--${side}-lat, --${side}-lng and --${side}-name must be passed together.`,\r\n );\r\n }\r\n return {\r\n lat: num(lat, `${side}-lat`) as number,\r\n lng: num(lng, `${side}-lng`) as number,\r\n name,\r\n };\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/** Render the modification outcome, making the per-side result explicit. */\r\nfunction formatUpdate(data: UpdateResponse): string {\r\n return Formatter.keyValue([\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ['Trip details updated', data.ride_updated ? 'yes' : 'no'],\r\n ['Passenger updated', data.passenger_updated ? 'yes' : 'no'],\r\n ]);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife update` — modify an existing ride order. Write op (W/Y).\r\n *\r\n * `POST /ride/<order-id>/update` with only the fields the caller passed, plus\r\n * the `Idempotency-Key` header (never in the body). Trip-side and passenger-side\r\n * changes are two separate upstream calls with NO transaction, so the response\r\n * reports each side; a partial application surfaces as `UPSTREAM_ERROR` carrying\r\n * `data.partial_update`.\r\n *\r\n * At least one modifiable field is required — an empty update is rejected\r\n * client-side as `PARAM_INVALID` before any request is sent, so we never spend\r\n * an idempotency key on a no-op.\r\n */\r\nexport function registerRideUpdateCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('update')\r\n .description('Modify an existing ride order (trip details and/or passenger)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Ride order id to modify (the ride_id returned by book)')\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n )\r\n .option('--quote-id <id>', 'New quote id when the fare changes')\r\n .option('--vehicle-class <class>', 'New vehicle class')\r\n .option('--price-amount <amount>', 'New fare in decimal currency units (NOT cents)')\r\n .option('--price-currency <code>', 'ISO 4217 currency code for the new fare')\r\n .option('--pickup-lat <lat>', 'New pickup latitude')\r\n .option('--pickup-lng <lng>', 'New pickup longitude')\r\n .option('--pickup-name <name>', 'New pickup location name')\r\n .option('--dropoff-lat <lat>', 'New dropoff latitude')\r\n .option('--dropoff-lng <lng>', 'New dropoff longitude')\r\n .option('--dropoff-name <name>', 'New dropoff location name')\r\n .option('--pickup-time <time>', \"New pickup time: epoch seconds or 'now'\")\r\n .option('--meet-and-greet', 'Enable meet & greet service')\r\n .option('--no-meet-and-greet', 'Disable meet & greet service')\r\n .option('--welcome-sign <text>', 'New welcome sign text (meet & greet)')\r\n .option('--arrival-flight-no <no>', 'New arrival flight number')\r\n .option('--arrival-airline <name>', 'New arrival airline name')\r\n .option('--departure-flight-no <no>', 'New departure flight number')\r\n .option('--departure-airline <name>', 'New departure airline name')\r\n .option('--service-area-id <id>', 'Service area id, when the upstream requires re-scoping')\r\n .option('--passenger-name <name>', 'New passenger full name')\r\n .option('--passenger-phone <phone>', 'New passenger phone (E.164)')\r\n .option('--passenger-email <email>', 'New passenger email')\r\n .option('--luggage-count <count>', 'New luggage count');\r\n\r\n attachSchemaHelp(cmd, rideUpdateSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n\r\n // `--meet-and-greet` / `--no-meet-and-greet` are only meaningful when the\r\n // user actually passed one: commander materialises `meetAndGreet: true` by\r\n // default for `--no-` pairs, so an untouched flag must stay out of the body.\r\n const mgTouched = process.argv.some(\r\n (a) => a === '--meet-and-greet' || a === '--no-meet-and-greet',\r\n );\r\n\r\n const body: Record<string, unknown> = {};\r\n const set = (key: string, value: unknown): void => {\r\n if (value !== undefined) body[key] = value;\r\n };\r\n set('quote_id', opts.quoteId as string | undefined);\r\n set('vehicle_class', opts.vehicleClass as string | undefined);\r\n set('price_amount', num(opts.priceAmount as string | undefined, 'price-amount'));\r\n set('price_currency', opts.priceCurrency as string | undefined);\r\n set(\r\n 'pickup',\r\n location(\r\n opts.pickupLat as string | undefined,\r\n opts.pickupLng as string | undefined,\r\n opts.pickupName as string | undefined,\r\n 'pickup',\r\n ),\r\n );\r\n set(\r\n 'dropoff',\r\n location(\r\n opts.dropoffLat as string | undefined,\r\n opts.dropoffLng as string | undefined,\r\n opts.dropoffName as string | undefined,\r\n 'dropoff',\r\n ),\r\n );\r\n set('pickup_time', pickupTime(opts.pickupTime as string | undefined));\r\n if (mgTouched) set('meet_and_greet', Boolean(opts.meetAndGreet));\r\n set('welcome_sign', opts.welcomeSign as string | undefined);\r\n if (opts.arrivalFlightNo !== undefined || opts.arrivalAirline !== undefined) {\r\n set('arrival_flight', {\r\n flight_no: opts.arrivalFlightNo as string | undefined,\r\n airline: opts.arrivalAirline as string | undefined,\r\n });\r\n }\r\n if (opts.departureFlightNo !== undefined || opts.departureAirline !== undefined) {\r\n set('departure_flight', {\r\n flight_no: opts.departureFlightNo as string | undefined,\r\n airline: opts.departureAirline as string | undefined,\r\n });\r\n }\r\n set('service_area_id', opts.serviceAreaId as string | undefined);\r\n set('passenger_name', opts.passengerName as string | undefined);\r\n set('passenger_phone', opts.passengerPhone as string | undefined);\r\n set('passenger_email', opts.passengerEmail as string | undefined);\r\n set('luggage_count', int(opts.luggageCount as string | undefined, 'luggage-count'));\r\n\r\n // Reject an empty update before spending an idempotency key on a no-op.\r\n if (Object.keys(body).length === 0) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Nothing to update. Pass at least one trip field or one passenger-* flag.',\r\n );\r\n }\r\n\r\n // Confirm before the write unless --yes: a modification can re-price the\r\n // ride upstream. Declining maps to CLIENT_ABORTED (exit 5).\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Apply ${Object.keys(body).length} change(s) to ride ${orderId}? The fare may change.`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Update aborted by user.');\r\n }\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'ride-elife update',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Updating ride...');\r\n\r\n const result = await deps.apiClient.post<UpdateResponse>(\r\n `/ride/${encodeURIComponent(orderId)}/update`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<UpdateResponse> = {\r\n data,\r\n text: () => formatUpdate(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { TripStatusResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, rideTripStatusSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\n/** Missing required input maps to `PARAM_INVALID` (catalog code, exit 1). */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Leg index is 1-based; 0 or negative is a client-side `PARAM_INVALID`. */\r\nfunction tripNo(value: string | undefined): number {\r\n if (value === undefined) return 1;\r\n const parsed = Number(value);\r\n if (!Number.isInteger(parsed) || parsed < 1) {\r\n throw new CliError('PARAM_INVALID', '--trip-no must be an integer >= 1.');\r\n }\r\n return parsed;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render one leg's status. Location points are summarised (count + latest\r\n * sample) rather than dumped — a long ride can carry hundreds of points, and\r\n * `--format json` is the right channel for the full array.\r\n */\r\nfunction formatTripStatus(data: TripStatusResponse): string {\r\n const lines: [string, string][] = [\r\n ['Ride ID', String(data.ride_id ?? '-')],\r\n ['Trip no', String(data.trip_no ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ];\r\n const points = data.points ?? [];\r\n lines.push(['Location points', String(points.length)]);\r\n const latest = points[points.length - 1];\r\n if (latest) {\r\n lines.push(['Latest position', `${latest.lat}, ${latest.lng} @ ${latest.utc_timestamp}`]);\r\n }\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife trip-status` — status of ONE leg of a multi-leg ride. Read-only\r\n * (no idempotency key).\r\n *\r\n * `GET /ride/<order-id>/trips/<trip-no>`. Single-shot only: whole-ride polling\r\n * belongs to `ride-elife get --watch`, and duplicating a watch loop here would\r\n * give two competing pollers for the same ride.\r\n */\r\nexport function registerRideTripStatusCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('trip-status')\r\n .description('Retrieve the status and driver location points of one leg of a ride')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Ride order id (the ride_id returned by `ride-elife book`)')\r\n .option('--trip-no <no>', '1-based leg index (default 1)');\r\n\r\n attachSchemaHelp(cmd, rideTripStatusSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n const leg = tripNo(opts.tripNo as string | undefined);\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching trip status...');\r\n\r\n const result = await deps.apiClient.get<TripStatusResponse>(\r\n `/ride/${encodeURIComponent(orderId)}/trips/${leg}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<TripStatusResponse> = {\r\n data,\r\n text: () => formatTripStatus(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { ListOrdersResponse, RideOrderListItem } from '../types/api.js';\r\nimport { attachSchemaHelp, listOrdersSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\n\r\n// ============================================================\r\n// Input helpers (ride-domain — stays in app per req 4.4)\r\n// ============================================================\r\n\r\nconst DEFAULT_PAGE = '1';\r\nconst DEFAULT_PAGE_SIZE = '20';\r\n\r\n/**\r\n * Number-ify a pagination flag. Non-finite / non-integer / non-positive input\r\n * maps to `PARAM_INVALID` (catalog code, exit 1) — mirroring the sibling\r\n * quote/get/cancel commands' convention. Returns the canonical string form to\r\n * be passed through as a query parameter.\r\n */\r\nfunction positiveInt(value: string, flag: string): string {\r\n const n = Number(value);\r\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\r\n }\r\n return String(n);\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the order list as a table for `--format table`. Each order is one\r\n * row; amounts are decimal currency units (NOT cents) — printed verbatim.\r\n */\r\nfunction formatOrders(data: ListOrdersResponse): string {\r\n const orders: RideOrderListItem[] = data.orders ?? [];\r\n if (orders.length === 0) {\r\n return Formatter.status('info', 'No ride orders found');\r\n }\r\n\r\n const headers = ['Order ID', 'Ride ID', 'Status', 'Vehicle Class', 'Price', 'Currency', 'Payment'];\r\n const rows = orders.map((o) => [\r\n String(o.order_id ?? '-'),\r\n String(o.ride_id ?? '-'),\r\n String(o.status ?? '-'),\r\n String(o.vehicle_class ?? '-'),\r\n String(o.price_amount ?? '-'),\r\n String(o.price_currency ?? '-'),\r\n String(o.payment_status ?? '-'),\r\n ]);\r\n\r\n const summary: [string, string][] = [\r\n ['Total', String(data.total ?? '-')],\r\n ['Page', String(data.page ?? '-')],\r\n ['Page size', String(data.page_size ?? '-')],\r\n ];\r\n\r\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(summary)}`;\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `ride-elife list-orders` — list previously placed ride orders (§4.4.1.3\r\n * list-orders schema). Read-only (no idempotency key).\r\n *\r\n * Passes `--page`(default 1) / `--page-size`(default 20) / `--status` /\r\n * `--order-type` through as query parameters to `GET /ride/orders` with the\r\n * `X-Api-Key` auth, and renders `ListOrdersResponse` via `renderWithContext`\r\n * (json carries the profile/endpoint envelope). `page`/`page-size` are\r\n * validated as positive integers (invalid → `PARAM_INVALID`); `status` /\r\n * `order-type` are forwarded verbatim only when set. The progress line is\r\n * emitted through `notify` so it goes to stderr and stays silent in json mode.\r\n */\r\nexport function registerListOrdersCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('list-orders')\r\n .description('List previously placed ride orders')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--page <page>', 'Page number', DEFAULT_PAGE)\r\n .option('--page-size <size>', 'Page size', DEFAULT_PAGE_SIZE)\r\n .option('--status <status>', 'Filter by order status')\r\n .option('--order-type <type>', 'Filter by order type')\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n\r\n attachSchemaHelp(cmd, listOrdersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build query params. page/page-size are validated as positive integers\r\n // (invalid → PARAM_INVALID before any request); status/order-type are\r\n // forwarded verbatim only when set. Sent as a query string, never a body.\r\n const params: Record<string, string> = {\r\n page: positiveInt((opts.page as string | undefined) ?? DEFAULT_PAGE, 'page'),\r\n page_size: positiveInt((opts.pageSize as string | undefined) ?? DEFAULT_PAGE_SIZE, 'page-size'),\r\n };\r\n if (opts.status !== undefined) params.status = opts.status as string;\r\n if (opts.orderType !== undefined) params.order_type = opts.orderType as string;\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) params.member_id = member;\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching orders...');\r\n\r\n const result = await deps.apiClient.get<ListOrdersResponse>(\r\n '/ride/orders',\r\n { type: 'api-key', key: apiKey },\r\n params,\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<ListOrdersResponse> = {\r\n data,\r\n text: () => formatOrders(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n notify,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport {\r\n attachSchemaHelp,\r\n rideCallbackSetSchema,\r\n rideCallbackGetSchema,\r\n rideCallbackDefaultSetSchema,\r\n rideCallbackDefaultGetSchema,\r\n rideCallbackDeliveriesSchema,\r\n rideCallbackReplaySchema,\r\n} from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n/**\r\n * Ride status-callback commands — thin wrappers over the platform's callback routes:\r\n *\r\n * callback-set POST /ride/<order-id>/callback (per-ride destination)\r\n * callback-get GET /ride/<order-id>/callback\r\n * callback-default-set POST /ride/callback/default (developer-wide fallback)\r\n * callback-default-get GET /ride/callback/default\r\n * callback-deliveries GET /ride/<order-id>/callback/deliveries\r\n * callback-replay POST /ride/<order-id>/callback/replay\r\n *\r\n * The platform enforces ownership (another developer's ride reads as not found) and the\r\n * https / non-internal URL rule (SSRF guard); the CLI only checks shape. The signing secret\r\n * comes back exactly once, in the set response that issued it — it is printed with a warning\r\n * and never retrievable again.\r\n */\r\n\r\nconst SIGNATURE_MODES = ['off', 'optional', 'required'] as const;\r\nconst DELIVERIES_LIMIT_MAX = 100;\r\n\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || String(value).trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return String(value);\r\n}\r\n\r\nfunction intFlag(value: string | undefined, flag: string, min: number, max?: number): number | undefined {\r\n if (value === undefined) return undefined;\r\n const parsed = Number(value);\r\n if (!Number.isInteger(parsed) || parsed < min || (max !== undefined && parsed > max)) {\r\n const range = max === undefined ? `>= ${min}` : `${min}-${max}`;\r\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer ${range}.`);\r\n }\r\n return parsed;\r\n}\r\n\r\nasync function apiKeyOf(opts: Record<string, unknown>): Promise<string> {\r\n return PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n}\r\n\r\n/** Body shared by per-ride and default registration. Omitted flags are not sent (server keeps the stored value). */\r\nfunction subscriptionBody(opts: Record<string, unknown>): Record<string, unknown> {\r\n const body: Record<string, unknown> = { callback_url: need(opts.callbackUrl as string | undefined, 'callback-url') };\r\n if (opts.adapter !== undefined) body.adapter = need(opts.adapter as string, 'adapter');\r\n if (opts.signatureMode !== undefined) {\r\n const mode = String(opts.signatureMode);\r\n if (!(SIGNATURE_MODES as readonly string[]).includes(mode)) {\r\n throw new CliError('PARAM_INVALID', `--signature-mode must be one of ${SIGNATURE_MODES.join(' / ')}.`);\r\n }\r\n body.signature_mode = mode;\r\n }\r\n if (opts.callbackApiKey !== undefined) body.callback_api_key = String(opts.callbackApiKey);\r\n if (opts.rotateSecret) body.rotate_secret = true;\r\n return body;\r\n}\r\n\r\nfunction formatSubscription(data: Record<string, unknown>): string {\r\n const lines: [string, string][] = [];\r\n for (const key of ['ride_id', 'order_id', 'developer_id', 'callback_url', 'adapter', 'signature_mode', 'status']) {\r\n if (data[key] !== undefined && data[key] !== null) lines.push([key, String(data[key])]);\r\n }\r\n const out = [Formatter.keyValue(lines)];\r\n if (typeof data.callback_secret === 'string' && data.callback_secret) {\r\n out.push('', Formatter.keyValue([['callback_secret', data.callback_secret]]));\r\n out.push('Save this signing secret now — it is shown only once and cannot be read back.');\r\n }\r\n return out.join('\\n');\r\n}\r\n\r\ntype Format = ReturnType<typeof resolveFormat>;\r\n\r\nasync function render<T>(data: T, text: () => string, format: Format): Promise<void> {\r\n const commandResult: CommandResult<T> = { data, text };\r\n await renderWithContext(commandResult, { format }, new ConfigManager());\r\n}\r\n\r\nfunction withSubscriptionFlags(cmd: Command): Command {\r\n return cmd\r\n .option('--callback-url <url>', 'https URL that receives ride status events (must not be an internal address)')\r\n .option('--adapter <name>', 'Outbound event shape (default techtanium_v1)')\r\n .option('--signature-mode <mode>', 'off / optional / required (default off)')\r\n .option('--callback-api-key <key>', 'API key the platform sends to your endpoint; omit to keep the stored one')\r\n .option('--rotate-secret', 'Issue a new HMAC signing secret (breaks verification with the old one)')\r\n .option('--idempotency-key <key>', 'Idempotency key forwarded verbatim as the Idempotency-Key header');\r\n}\r\n\r\nasync function postSubscription(\r\n deps: { apiClient: ApiClient },\r\n cmd: Command,\r\n path: (opts: Record<string, unknown>) => string,\r\n commandPath: string,\r\n doneMessage: string,\r\n): Promise<void> {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const target = path(opts);\r\n const body = subscriptionBody(opts);\r\n const apiKey = await apiKeyOf(opts);\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: Boolean(opts.yes),\r\n commandPath,\r\n });\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n target,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n notify(format, 'success', doneMessage);\r\n await render(result.data, () => formatSubscription(result.data), format);\r\n}\r\n\r\nasync function getJson(\r\n deps: { apiClient: ApiClient },\r\n cmd: Command,\r\n path: (opts: Record<string, unknown>) => string,\r\n text: (data: Record<string, unknown>) => string,\r\n params?: (opts: Record<string, unknown>) => Record<string, string> | undefined,\r\n): Promise<void> {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const target = path(opts);\r\n const query = params?.(opts);\r\n const apiKey = await apiKeyOf(opts);\r\n const result = await deps.apiClient.get<Record<string, unknown>>(target, { type: 'api-key', key: apiKey }, query);\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, () => text(result.data), format);\r\n}\r\n\r\nconst ridePath = (opts: Record<string, unknown>, suffix: string): string =>\r\n `/ride/${encodeURIComponent(need(opts.orderId as string | undefined, 'order-id'))}/callback${suffix}`;\r\n\r\nexport function registerRideCallbackCommands(parent: Command, deps: { apiClient: ApiClient }): void {\r\n // callback-set\r\n const set = withSubscriptionFlags(\r\n parent\r\n .command('callback-set')\r\n .description('Register (or update) where one ride\\'s status events are forwarded')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The numeric ride_id returned by book'),\r\n );\r\n attachSchemaHelp(set, rideCallbackSetSchema);\r\n set.action(() =>\r\n postSubscription(deps, set, (o) => ridePath(o, ''), 'ride-elife callback-set', 'Ride callback registered'),\r\n );\r\n\r\n // callback-get\r\n const get = parent\r\n .command('callback-get')\r\n .description('Show one ride\\'s callback registration (the signing secret is never returned)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The numeric ride_id returned by book');\r\n attachSchemaHelp(get, rideCallbackGetSchema);\r\n get.action(() => getJson(deps, get, (o) => ridePath(o, ''), formatSubscription));\r\n\r\n // callback-default-set\r\n const defSet = withSubscriptionFlags(\r\n parent\r\n .command('callback-default-set')\r\n .description('Register (or update) the developer-wide fallback for rides without their own callback')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)'),\r\n );\r\n attachSchemaHelp(defSet, rideCallbackDefaultSetSchema);\r\n defSet.action(() =>\r\n postSubscription(\r\n deps,\r\n defSet,\r\n () => '/ride/callback/default',\r\n 'ride-elife callback-default-set',\r\n 'Default ride callback registered',\r\n ),\r\n );\r\n\r\n // callback-default-get\r\n const defGet = parent\r\n .command('callback-default-get')\r\n .description('Show the developer-wide fallback callback (the signing secret is never returned)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n attachSchemaHelp(defGet, rideCallbackDefaultGetSchema);\r\n defGet.action(() => getJson(deps, defGet, () => '/ride/callback/default', formatSubscription));\r\n\r\n // callback-deliveries\r\n const deliveries = parent\r\n .command('callback-deliveries')\r\n .description('List one ride\\'s callback forwarding records (pending / delivered / dead)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The numeric ride_id returned by book')\r\n .option('--limit <n>', `Page size 1-${DELIVERIES_LIMIT_MAX} (default 50)`)\r\n .option('--offset <n>', 'Records to skip (default 0)');\r\n attachSchemaHelp(deliveries, rideCallbackDeliveriesSchema);\r\n deliveries.action(() =>\r\n getJson(\r\n deps,\r\n deliveries,\r\n (o) => ridePath(o, '/deliveries'),\r\n (data) => {\r\n const rows = (data.deliveries as Record<string, unknown>[] | undefined) ?? [];\r\n if (rows.length === 0) return Formatter.status('info', 'No callback deliveries');\r\n return Formatter.table(\r\n ['Event', 'Status', 'Attempts', 'Last error'],\r\n rows.map((r) => [\r\n String(r.event_id ?? '-'),\r\n String(r.status ?? '-'),\r\n String(r.attempts ?? '-'),\r\n String(r.last_error ?? '-'),\r\n ]),\r\n );\r\n },\r\n (o) => {\r\n const limit = intFlag(o.limit as string | undefined, 'limit', 1, DELIVERIES_LIMIT_MAX);\r\n const offset = intFlag(o.offset as string | undefined, 'offset', 0);\r\n const params: Record<string, string> = {};\r\n if (limit !== undefined) params.limit = String(limit);\r\n if (offset !== undefined) params.offset = String(offset);\r\n return Object.keys(params).length > 0 ? params : undefined;\r\n },\r\n ),\r\n );\r\n\r\n // callback-replay\r\n const replay = parent\r\n .command('callback-replay')\r\n .description('Requeue one ride\\'s dead (or failed) callback records; delivered records are never re-sent')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'The numeric ride_id returned by book')\r\n .option('--event-id <id>', 'Requeue only this record (default: all dead records of the ride)')\r\n .option('--include-failed', 'Also requeue pending records that already failed at least once')\r\n .option('--reset-attempts', 'Reset the retry counter of requeued records')\r\n .option('--idempotency-key <key>', 'Idempotency key forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(replay, rideCallbackReplaySchema);\r\n replay.action(async () => {\r\n const opts = replay.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const target = ridePath(opts, '/replay');\r\n const body: Record<string, unknown> = {};\r\n if (opts.eventId !== undefined) body.event_id = need(opts.eventId as string, 'event-id');\r\n if (opts.includeFailed) body.include_failed = true;\r\n if (opts.resetAttempts) body.reset_attempts = true;\r\n const apiKey = await apiKeyOf(opts);\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: Boolean(opts.yes),\r\n commandPath: 'ride-elife callback-replay',\r\n });\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n target,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n notify(format, 'success', `Requeued ${String(result.data.requeued ?? 0)} callback record(s)`);\r\n await render(\r\n result.data,\r\n () => Formatter.keyValue([\r\n ['Ride ID', String(result.data.ride_id ?? '-')],\r\n ['Requeued', String(result.data.requeued ?? 0)],\r\n ]),\r\n format,\r\n );\r\n });\r\n}\r\n","/**\r\n * Built-in static capability registry (D4, merchant-domain only).\r\n *\r\n * NOTE: this is a CLI-bundled, single-merchant catalog — NOT a live backend\r\n * discovery feed. It does not reflect which services are enabled for the\r\n * current API key, nor the developer's billing mode (that is a per-developer\r\n * property decided by the backend, surfaced via the `book` response /\r\n * error codes, not advertised here). The §4.4.1 backend `/services` discovery\r\n * endpoint (BACK-063) + top-level `billing` block + `page` cursor are pending\r\n * impl; until they land, `services list/get` read this table.\r\n *\r\n * Each entry describes a CLI-exposed service: which `cli_noun` group hosts it,\r\n * the verbs it offers (with one-line descriptions), the recommended call\r\n * `workflow`, and discovery hints. `services list` renders a summary of these\r\n * entries and `services get <service-id>` returns one in full.\r\n *\r\n * `ServiceCapability` / the registry are merchant-domain specific (only\r\n * merchant-cli uses them) and stay in the app — they are NOT lifted to\r\n * `@agenzo/cli-core`.\r\n */\r\n\r\n/** Discovery hints for a capability (§4.4.1 schema). */\r\nexport interface ServiceDiscovery {\r\n /** Command an agent can run to discover the verbs in detail. */\r\n help_command: string;\r\n /**\r\n * Capability-layer schema download URL (the provider's aggregate\r\n * `schema/<cli_noun>.json`, mirrored by its `schema_ref.schema_url`). The\r\n * aggregate HTTP endpoint is reserved/pending; until it lands, agents use\r\n * `help_command` (`<noun> <verb> --help --format json`) for the live schema.\r\n */\r\n schema_url?: string;\r\n}\r\n\r\nexport interface ServiceCapability {\r\n service_id: string;\r\n name: string;\r\n description: string;\r\n /** Service category (e.g. `ride`); part of the §4.4.1 schema form. */\r\n category: string;\r\n version: string;\r\n /** Upstream capability provider. */\r\n provider: string;\r\n /** Top-level CLI noun (command group) that hosts this service's verbs (`<category>-<provider>`). */\r\n cli_noun: string;\r\n /** Verb names exposed under `cli_noun`. */\r\n verbs: string[];\r\n /** One-line description per verb, keyed by verb name. */\r\n verb_descriptions: Record<string, string>;\r\n /** Ordered call sequence; `[cancel]` is optional. */\r\n workflow: string[];\r\n /** ISO date the capability became available. */\r\n since: string;\r\n discovery: ServiceDiscovery;\r\n}\r\n\r\n/** Static registry. This iteration ships ride-elife and hotel-redaug capabilities. */\r\nexport const SERVICE_REGISTRY: ServiceCapability[] = [\r\n {\r\n // Agent-facing service_id = cli_noun(Agent 拼命令用这个标识)。\r\n // 平台级不透明内部 ULID: svc_01KWTPBWDH5YZ52H717BFVWZA8(与后端\r\n // services/merchant_service/discovery/catalog.py 的 RIDE_ELIFE_SERVICE_ID 对应)。\r\n service_id: 'ride-elife',\r\n name: 'Ride hailing (eLife)',\r\n description: 'On-demand ride ordering: quote a fare, book it, poll status, and cancel.',\r\n category: 'ride',\r\n version: '1.0.0',\r\n provider: 'elife',\r\n cli_noun: 'ride-elife',\r\n verbs: ['quote', 'book', 'get', 'cancel', 'update', 'trip-status', 'list-orders'],\r\n verb_descriptions: {\r\n quote: 'Request fare quotes for a ride between two points.',\r\n book: 'Book a ride using a quote_id returned by quote.',\r\n get: 'Retrieve a ride order by id (poll for status changes with --watch).',\r\n cancel: 'Cancel a ride order by id (may incur a fee).',\r\n update: 'Modify a booked ride: trip details and/or passenger info.',\r\n 'trip-status': 'Retrieve status and driver location points for one leg of a multi-leg ride.',\r\n 'list-orders': 'List previously placed ride orders.',\r\n },\r\n workflow: [\r\n 'quote',\r\n 'book',\r\n 'get (poll for status)',\r\n 'update (optional)',\r\n 'trip-status (optional, multi-leg rides)',\r\n 'cancel (optional)',\r\n ],\r\n since: '2026-06-01',\r\n discovery: {\r\n help_command: 'agenzo-merchant-cli ride-elife --help',\r\n },\r\n },\r\n {\r\n service_id: 'hotel-redaug',\r\n name: 'Hotel booking (Redaug)',\r\n description:\r\n 'International hotel booking via Redaug: search by location, real-time room/rate availability, two-step create-then-pay flow supporting monthly_settlement and pay_per_call (EVO) billing modes, cancel and partial check-out.',\r\n category: 'hotel',\r\n version: 'v1',\r\n provider: 'redaug',\r\n cli_noun: 'hotel-redaug',\r\n verbs: [\r\n 'find-destination',\r\n 'hotel-filters',\r\n 'list-cities',\r\n 'search',\r\n 'hotel-detail',\r\n 'quote',\r\n 'create-order',\r\n 'pay-order',\r\n 'get',\r\n 'cancel',\r\n 'checkout',\r\n 'get-checkout',\r\n 'list-orders',\r\n ],\r\n verb_descriptions: {\r\n 'find-destination': 'Resolve a free-text place into destinations.',\r\n 'hotel-filters': 'Get available filter options for a location.',\r\n 'list-cities': 'List the cities of a country.',\r\n search: 'Search hotels by destination or coordinates.',\r\n 'hotel-detail': 'Get hotel detail (name/star/address/facilities/photos).',\r\n quote: 'Get real-time room types and bookable rates for a hotel.',\r\n 'create-order': 'Create a hotel order without charging (locks the rate, no payment).',\r\n 'pay-order': 'Settle a created order by --order-id (path chosen server-side by billing_mode: monthly_settlement or pay_per_call).',\r\n get: 'Query order status (poll for async confirmation).',\r\n cancel: 'Cancel an order (whole-order, in-policy).',\r\n checkout: 'Apply for partial check-out / out-of-policy cancellation.',\r\n 'get-checkout': 'Poll a check-out application status.',\r\n 'list-orders': 'List hotel orders (local store, no upstream call).',\r\n },\r\n workflow: [\r\n 'find-destination / list-cities (optional)',\r\n 'hotel-filters (optional)',\r\n 'search',\r\n 'hotel-detail (optional)',\r\n 'quote',\r\n 'create-order (locks the rate, no charge)',\r\n 'pay-order (settles: monthly_settlement or pay_per_call)',\r\n 'get (poll until CONFIRMED)',\r\n 'cancel / checkout (optional)',\r\n ],\r\n since: '2026-06-25',\r\n discovery: {\r\n help_command: 'agenzo-merchant-cli hotel-redaug --help',\r\n },\r\n },\r\n {\r\n // 与后端 services/merchant_service/discovery/catalog.py 的 flight-flink 条目 + provider\r\n // schema flight-flink.json 的 service_id 保持一致。Agent 拼命令用 cli_noun=\"flight-flink\"。\r\n service_id: 'svc_01J0HT5FLINK0001',\r\n name: 'Flight booking (Flink)',\r\n description:\r\n 'International flight booking: airport/city resolution, one-way/round-trip/multi-city search with journeyId relay, price verification, two-step create-then-pay ticketing, order polling, plus change (rebooking) and refund flows.',\r\n category: 'flight',\r\n version: '1.0.0',\r\n provider: 'flink',\r\n cli_noun: 'flight-flink',\r\n verbs: [\r\n 'find-airport',\r\n 'list-airports',\r\n 'list-airlines',\r\n 'list-nationalities',\r\n 'search',\r\n 'more-offers',\r\n 'verify',\r\n 'create-order',\r\n 'pay-order',\r\n 'get-order',\r\n 'cancel-order',\r\n 'list-orders',\r\n 'change-search',\r\n 'change-apply',\r\n 'change-detail',\r\n 'change-pay',\r\n 'change-cancel',\r\n 'refund-apply',\r\n 'refund-detail',\r\n 'refund-confirm',\r\n ],\r\n verb_descriptions: {\r\n 'find-airport': 'Resolve free-text into city/airport candidates.',\r\n 'list-airports': 'Paged airport dictionary.',\r\n 'list-airlines': 'Paged airline dictionary.',\r\n 'list-nationalities': 'Nationality list.',\r\n search: 'Search flights (one-way/round-trip/multi-city) with journeyId relay.',\r\n 'more-offers': 'More fare offers for a priceKey.',\r\n verify: 'Verify the latest price before booking; returns the authoritative product_token.',\r\n 'create-order': 'Create a flight order without charging (locks the fare).',\r\n 'pay-order': 'Settle a created order by --order-no (triggers ticketing).',\r\n 'get-order': 'Query order status (poll ticketing 5→8).',\r\n 'cancel-order': 'Cancel an un-ticketed order (with refund).',\r\n 'list-orders': 'List flight orders (local store, no upstream call).',\r\n 'change-search': 'Search rebook-eligible flights.',\r\n 'change-apply': 'Submit a change request (pending review).',\r\n 'change-detail': 'Change request detail.',\r\n 'change-pay': 'Pay the change fee and trigger change ticketing.',\r\n 'change-cancel': 'Cancel a change request (immediate terminal).',\r\n 'refund-apply': 'Submit a refund request (pending review).',\r\n 'refund-detail': 'Refund request detail.',\r\n 'refund-confirm': 'Confirm (\"1\") or cancel (\"2\") a refund.',\r\n },\r\n workflow: [\r\n 'find-airport',\r\n 'search (relay journey-id for round-trip/multi-city)',\r\n 'verify',\r\n 'create-order (locks the fare, no charge)',\r\n 'pay-order (settles + ticketing)',\r\n 'get-order (poll until TICKETED)',\r\n 'change-* / refund-* / cancel-order (optional)',\r\n ],\r\n since: '2026-07-09',\r\n discovery: {\r\n help_command: 'agenzo-merchant-cli flight-flink --help',\r\n },\r\n },\r\n];\r\n\r\n/** Look up a capability by its service_id or cli_noun. Returns undefined when not found. */\r\nexport function findService(serviceId: string): ServiceCapability | undefined {\r\n return SERVICE_REGISTRY.find((s) => s.service_id === serviceId || s.cli_noun === serviceId);\r\n}\r\n","import { Command } from 'commander';\r\n\r\n/**\r\n * Map of `cli_noun` → the verb names this CLI binary actually registers.\r\n *\r\n * This is the CLI's local source of truth for \"what can I execute\". It is built\r\n * by introspecting the commander program's command tree — NOT from any bundled\r\n * schema. The discovery gate intersects backend capabilities against this map so\r\n * the Agent never sees a service/verb the local CLI cannot run.\r\n */\r\nexport type LocalCapabilityMap = Record<string, string[]>;\r\n\r\n/** Command groups that are NOT discoverable services (utility groups). */\r\nconst NON_SERVICE_NOUNS = new Set(['services', 'help', 'config']);\r\n\r\n/**\r\n * Build the local capability map from the commander program: each top-level\r\n * command group (noun) → its registered subcommand (verb) names.\r\n *\r\n * Excludes utility groups (e.g. `services` itself) and any command with no\r\n * subcommands (those are not service nouns).\r\n */\r\nexport function buildLocalCapabilityMap(program: Command): LocalCapabilityMap {\r\n const map: LocalCapabilityMap = {};\r\n for (const noun of program.commands) {\r\n const name = noun.name();\r\n if (NON_SERVICE_NOUNS.has(name)) continue;\r\n const verbs = noun.commands.map((v) => v.name()).filter((n) => n !== 'help');\r\n if (verbs.length === 0) continue;\r\n map[name] = verbs;\r\n }\r\n return map;\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n Formatter,\r\n PromptEngine,\r\n CliError,\r\n resolveFormat,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { SERVICE_REGISTRY } from './registry.js';\r\nimport { buildLocalCapabilityMap, type LocalCapabilityMap } from './local-caps.js';\r\n\r\n/**\r\n * Summary view of a capability for `services list` output. Lightweight on\r\n * purpose — the full schema (incl. per-verb detail) is fetched via `services\r\n * get`. Heavy fields (verb_descriptions / workflow / description / schema_content)\r\n * are deliberately omitted here.\r\n */\r\ninterface ServiceListItem {\r\n service_id: string;\r\n name: string;\r\n category: string;\r\n provider: string;\r\n cli_noun: string;\r\n version: string;\r\n verbs: string[];\r\n since: string;\r\n discovery?: unknown;\r\n}\r\n\r\n/**\r\n * Normalize any capability-like record — a backend discovery item OR a local\r\n * registry entry — down to the lightweight list summary. Both sources share\r\n * field names, so one normalizer keeps `list` output identical regardless of\r\n * where it came from and prevents heavy fields from leaking in.\r\n */\r\nfunction toListItem(s: Record<string, unknown>): ServiceListItem {\r\n return {\r\n service_id: String(s.service_id ?? ''),\r\n name: String(s.name ?? ''),\r\n category: String(s.category ?? ''),\r\n provider: String(s.provider ?? ''),\r\n cli_noun: String(s.cli_noun ?? ''),\r\n version: String(s.version ?? ''),\r\n verbs: Array.isArray(s.verbs) ? (s.verbs as string[]) : [],\r\n since: String(s.since ?? ''),\r\n discovery: s.discovery,\r\n };\r\n}\r\n\r\n/**\r\n * Gate backend capabilities against what this CLI binary can actually execute.\r\n *\r\n * The schema lives on the backend (dynamic); the CLI does NOT bundle it. The\r\n * gate uses the CLI's own command tree (`localCaps`): a capability is kept only\r\n * if this CLI registers its `cli_noun`, and its `verbs` are intersected with the\r\n * locally-registered verbs (so a verb the CLI doesn't implement is never shown).\r\n * Capabilities with no executable verb are dropped entirely — the Agent never\r\n * sees a service/verb it cannot run.\r\n */\r\nfunction gateByLocalCommands(\r\n capabilities: ServiceListItem[],\r\n localCaps: LocalCapabilityMap,\r\n): ServiceListItem[] {\r\n const gated: ServiceListItem[] = [];\r\n for (const cap of capabilities) {\r\n const localVerbs = localCaps[cap.cli_noun];\r\n if (!localVerbs) continue; // CLI doesn't have this noun at all → hide\r\n const usableVerbs = (cap.verbs || []).filter((v) => localVerbs.includes(v));\r\n if (usableVerbs.length === 0) continue; // nothing executable → hide\r\n gated.push({ ...cap, verbs: usableVerbs });\r\n }\r\n return gated;\r\n}\r\n\r\n/**\r\n * `services list` — discover available merchant capabilities.\r\n *\r\n * Primary path: call the platform discovery API (`GET /api/discovery/v1/catalog`),\r\n * then gate the result against this CLI's command tree (see gateByLocalCommands)\r\n * so only services/verbs this binary can run are shown.\r\n *\r\n * Fallback: if the platform is unreachable, fall back to the CLI-bundled local\r\n * registry (offline usability), gated the same way.\r\n */\r\nexport function registerServicesListCommand(\r\n parent: Command,\r\n deps: { discoveryClient: ApiClient; program: Command },\r\n): void {\r\n const cmd = parent\r\n .command('list')\r\n .description('List available merchant services (from platform discovery)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const localCaps = buildLocalCapabilityMap(deps.program);\r\n\r\n let services: ServiceListItem[];\r\n\r\n try {\r\n // Resolve API key (required for the discovery endpoint).\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Discovery lives at /api/discovery/v1/catalog (host root, not the merchant\r\n // prefix); deps.discoveryClient is built from the raw host in index.ts.\r\n const result = await deps.discoveryClient.get<{\r\n capabilities: Array<Record<string, unknown>>;\r\n }>('/api/discovery/v1/catalog', { type: 'api-key', key: apiKey });\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n services = gateByLocalCommands(\r\n (result.data.capabilities || []).map(toListItem),\r\n localCaps,\r\n );\r\n } catch {\r\n // Fallback to local registry when the backend is unreachable.\r\n services = gateByLocalCommands(\r\n SERVICE_REGISTRY.map((s) => toListItem(s as unknown as Record<string, unknown>)),\r\n localCaps,\r\n );\r\n }\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<{ services: ServiceListItem[] }> = {\r\n data: { services },\r\n text: () => {\r\n if (services.length === 0) {\r\n return Formatter.status('info', 'No services found');\r\n }\r\n const headers = ['Service ID', 'Name', 'Category', 'Provider', 'Version', 'Verbs'];\r\n const rows = services.map((s) => [\r\n s.service_id,\r\n s.name,\r\n s.category,\r\n s.provider,\r\n s.version,\r\n s.verbs.join(', '),\r\n ]);\r\n return Formatter.table(headers, rows);\r\n },\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n Formatter,\r\n PromptEngine,\r\n CliError,\r\n resolveFormat,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { findService } from './registry.js';\r\nimport { buildLocalCapabilityMap, type LocalCapabilityMap } from './local-caps.js';\r\n\r\n/**\r\n * Render the full capability as a key/value block for table output. Heavy\r\n * detail (workflow, per-verb descriptions) is appended when present so the\r\n * human-facing table stays as informative as the JSON payload.\r\n */\r\nfunction formatServiceGet(s: Record<string, unknown>): string {\r\n const lines: [string, string][] = [\r\n ['Service ID', String(s.service_id ?? '')],\r\n ['Name', String(s.name ?? '')],\r\n ['Description', String(s.description ?? s.summary ?? '')],\r\n ['Category', String(s.category ?? '')],\r\n ['Version', String(s.version ?? '')],\r\n ['Provider', String(s.provider ?? '')],\r\n ['CLI Noun', String(s.cli_noun ?? '')],\r\n ['Verbs', Array.isArray(s.verbs) ? (s.verbs as string[]).join(', ') : ''],\r\n ];\r\n if (Array.isArray(s.workflow) && s.workflow.length > 0) {\r\n lines.push(['Workflow', (s.workflow as string[]).join(' → ')]);\r\n }\r\n\r\n const block = Formatter.keyValue(lines);\r\n\r\n const verbDescriptions = s.verb_descriptions as Record<string, string> | undefined;\r\n if (verbDescriptions && Object.keys(verbDescriptions).length > 0) {\r\n const detail = Object.entries(verbDescriptions)\r\n .map(([verb, desc]) => ` ${verb}: ${desc}`)\r\n .join('\\n');\r\n return `${block}\\n\\nVerb descriptions:\\n${detail}`;\r\n }\r\n return block;\r\n}\r\n\r\n/**\r\n * Gate a single backend capability against the CLI's command tree: the\r\n * `cli_noun` must be registered locally, otherwise the service is treated as\r\n * not found (the CLI can't execute it, so it must not surface its schema).\r\n * Verb lists inside the returned payload are intersected with local verbs so a\r\n * verb the CLI lacks is never advertised to the Agent.\r\n */\r\nfunction gateCapability(\r\n data: Record<string, unknown>,\r\n localCaps: LocalCapabilityMap,\r\n): Record<string, unknown> | null {\r\n const noun = String(data.cli_noun ?? '');\r\n const localVerbs = localCaps[noun];\r\n if (!localVerbs) return null;\r\n\r\n const out = { ...data };\r\n // Intersect the top-level verbs[] summary.\r\n if (Array.isArray(out.verbs)) {\r\n out.verbs = (out.verbs as string[]).filter((v) => localVerbs.includes(v));\r\n }\r\n // Intersect the full schema_content.verbs map when present.\r\n const schema = out.schema_content as Record<string, unknown> | undefined;\r\n if (schema && schema.verbs && typeof schema.verbs === 'object') {\r\n const filtered: Record<string, unknown> = {};\r\n for (const [verb, def] of Object.entries(schema.verbs as Record<string, unknown>)) {\r\n if (localVerbs.includes(verb)) filtered[verb] = def;\r\n }\r\n out.schema_content = { ...schema, verbs: filtered };\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * `services get <service-id>` — retrieve a single capability's full metadata\r\n * including the complete schema_content (the Agent reads this to learn how to\r\n * use the service).\r\n *\r\n * Primary path: `GET /api/discovery/v1/catalog/<service-id>` → full schema, then\r\n * gated against the CLI command tree (noun must exist; verbs intersected).\r\n * Fallback: local registry (basic metadata, no schema_content).\r\n */\r\nexport function registerServiceGetCommand(\r\n parent: Command,\r\n deps: { discoveryClient: ApiClient; program: Command },\r\n): void {\r\n const cmd = parent\r\n .command('get <service-id>')\r\n .description('Retrieve a single merchant service by id (includes full schema)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n\r\n cmd.action(async (serviceId: string) => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const localCaps = buildLocalCapabilityMap(deps.program);\r\n\r\n let data: Record<string, unknown> | null = null;\r\n\r\n try {\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const result = await deps.discoveryClient.get<Record<string, unknown>>(\r\n `/api/discovery/v1/catalog/${encodeURIComponent(serviceId)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n data = gateCapability(result.data, localCaps);\r\n } catch {\r\n // Fallback to local registry.\r\n const local = findService(serviceId);\r\n data = local ? gateCapability(local as unknown as Record<string, unknown>, localCaps) : null;\r\n }\r\n\r\n if (data === null) {\r\n throw new CliError(\r\n 'SERVICE_NOT_FOUND',\r\n `Service '${serviceId}' is not available in this CLI. Run \"services list\" to see available services.`,\r\n );\r\n }\r\n\r\n const resolved = data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<Record<string, unknown>> = {\r\n data: resolved,\r\n text: () => formatServiceGet(resolved),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { UnifiedListOrdersResponse, UnifiedOrderListItem } from '../types/api.js';\r\nimport { attachSchemaHelp, unifiedOrdersListSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\n\r\nconst DEFAULT_PAGE = '1';\r\nconst DEFAULT_PAGE_SIZE = '20';\r\n\r\nfunction positiveInt(value: string, flag: string): string {\r\n const n = Number(value);\r\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\r\n }\r\n return String(n);\r\n}\r\n\r\nfunction assertCompatibleOptions(opts: Record<string, unknown>): void {\r\n if (opts.orderType !== undefined && opts.orderTypes !== undefined) {\r\n throw new CliError('PARAM_INVALID', '--order-type and --order-types cannot be used together.');\r\n }\r\n if (opts.status !== undefined && opts.statuses !== undefined) {\r\n throw new CliError('PARAM_INVALID', '--status and --statuses cannot be used together.');\r\n }\r\n if (opts.cursor !== undefined && Number(opts.page ?? DEFAULT_PAGE) !== 1) {\r\n throw new CliError('PARAM_INVALID', '--cursor cannot be combined with --page greater than 1.');\r\n }\r\n}\r\n\r\n/** Render a compact cross-provider list summary for table output. */\r\nfunction formatOrders(data: UnifiedListOrdersResponse): string {\r\n const orders: UnifiedOrderListItem[] = data.orders ?? [];\r\n if (orders.length === 0) {\r\n return Formatter.status('info', 'No orders found');\r\n }\r\n\r\n const headers = ['Order ID', 'Type', 'Status', 'Amount', 'Currency'];\r\n const rows = orders.map((o) => [\r\n String(o.order_id ?? '-'),\r\n String(o.order_type ?? '-'),\r\n String(o.status ?? '-'),\r\n String(o.amount ?? '-'),\r\n String(o.currency ?? '-'),\r\n ]);\r\n\r\n const summary: [string, string][] = [\r\n ['Total', String(data.total ?? '-')],\r\n ['Page', String(data.page ?? '-')],\r\n ['Page size', String(data.page_size ?? '-')],\r\n ];\r\n if (data.has_more !== undefined) summary.push(['Has more', String(data.has_more)]);\r\n if (data.next_cursor) summary.push(['Next cursor', data.next_cursor]);\r\n\r\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(summary)}`;\r\n}\r\n\r\n/**\r\n * `orders list` — cross-provider order list (`GET /orders`). This is the\r\n * only list spanning ride, hotel, and flight in one call. Domain-specific\r\n * list commands remain available when provider-specific columns are needed.\r\n */\r\nexport function registerOrdersListCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('list')\r\n .description('List orders across ALL providers (ride + hotel + flight), with filters and pagination')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-type <type>', 'Legacy single order type filter: ride | hotel | flight')\r\n .option('--order-types <types>', 'Comma-separated order types: ride,hotel,flight')\r\n .option('--status <status>', 'Legacy single normalized status filter')\r\n .option('--statuses <statuses>', 'Comma-separated statuses: PENDING,CONFIRMED,COMPLETED,CANCELLED,FAILED')\r\n .option('--created-from <datetime>', 'Created at or after this ISO 8601 datetime (inclusive)')\r\n .option('--created-to <datetime>', 'Created before this ISO 8601 datetime (exclusive)')\r\n .option('--cursor <cursor>', 'Opaque cursor returned by the previous page')\r\n .option('--page <page>', 'Legacy 1-based page number', DEFAULT_PAGE)\r\n .option('--page-size <size>', 'Page size', DEFAULT_PAGE_SIZE)\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n\r\n attachSchemaHelp(cmd, unifiedOrdersListSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n assertCompatibleOptions(opts);\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const params: Record<string, string> = {\r\n page: positiveInt((opts.page as string | undefined) ?? DEFAULT_PAGE, 'page'),\r\n page_size: positiveInt((opts.pageSize as string | undefined) ?? DEFAULT_PAGE_SIZE, 'page-size'),\r\n };\r\n if (opts.orderType !== undefined) params.order_type = opts.orderType as string;\r\n if (opts.orderTypes !== undefined) params.order_types = opts.orderTypes as string;\r\n if (opts.status !== undefined) params.status = opts.status as string;\r\n if (opts.statuses !== undefined) params.statuses = opts.statuses as string;\r\n if (opts.createdFrom !== undefined) params.created_from = opts.createdFrom as string;\r\n if (opts.createdTo !== undefined) params.created_to = opts.createdTo as string;\r\n if (opts.cursor !== undefined) params.cursor = opts.cursor as string;\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) params.member_id = member;\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching orders...');\r\n const result = await deps.apiClient.get<UnifiedListOrdersResponse>(\r\n '/orders',\r\n { type: 'api-key', key: apiKey },\r\n params,\r\n );\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<UnifiedListOrdersResponse> = {\r\n data,\r\n text: () => formatOrders(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { UnifiedOrderDetailResponse } from '../types/api.js';\r\nimport { attachSchemaHelp, unifiedOrdersGetSchema } from '../verb-schema.js';\r\n\r\n/**\r\n * `orders get` — cross-provider order detail (`GET /orders/{id}`). The\r\n * platform resolves order_id -> order_type and delegates to the owning ride,\r\n * hotel, or flight domain. Treat the domain detail as an opaque object.\r\n */\r\nexport function registerOrdersGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('get')\r\n .description('Get a single order detail by id, regardless of provider (ride/hotel/flight)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .requiredOption('--order-id <id>', 'Order id (e.g. rio_..., hho_..., or ffo_...)');\r\n\r\n attachSchemaHelp(cmd, unifiedOrdersGetSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching order...');\r\n\r\n const result = await deps.apiClient.get<UnifiedOrderDetailResponse>(\r\n `/orders/${encodeURIComponent(opts.orderId as string)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<UnifiedOrderDetailResponse> = {\r\n data,\r\n text: () =>\r\n Formatter.keyValue(\r\n Object.entries(data).map(([k, v]) => [k, typeof v === 'object' ? JSON.stringify(v) : String(v)]),\r\n ),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { attachSchemaHelp, ordersPayBatchSchema } from '../verb-schema.js';\r\n// 复用打车 watch 模块导出的 NDJSON 写行 / 真实定时器 / 秒数解析(与 pay-order.ts 同源)。\r\nimport { ndjsonWriteLine, realSleep, resolveSeconds } from '../ride-elife/watch.js';\r\n\r\n// ============================================================\r\n// Response types(后端 pay-batch 契约:成功体 / 3DS 挑战体)\r\n// ============================================================\r\n\r\n/** 聚合结算里单笔订单的最终结果(逐单确认后:成功 / 退款 / 失败)。 */\r\nexport interface PayBatchOrderResult {\r\n order_id: string;\r\n /** 该订单所属领域(hotel / flight / ride),逐单上游确认按此分派。 */\r\n domain?: string;\r\n /** confirmed(上游确认成功)| refunded(确认失败已退款)| failed。 */\r\n status: string;\r\n /** 该订单的权威金额(十进制币种单位,非最小单位)。 */\r\n amount?: number;\r\n /** 确认失败时按该订单金额退款的金额。 */\r\n refunded_amount?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * `POST /orders/pay-batch` 的返回体。同一形状承载三种结果:\r\n * - 成功体:`status ∈ {settled, partially_settled}`,携 `total_amount`/`currency`/`per_order[]`\r\n * (逐单项 `{order_id, domain, status, amount, refunded_amount}`);\r\n * - 3DS 挑战体(轨 B EVO 强制认证):`status == \"AUTHENTICATION_REQUIRED\"`,携 `three_ds_url`/`merchant_trans_id`/`amount`;\r\n * - 失败终态:`status == \"failed\"`。\r\n * CLI 是薄透传层,原样透出后端字段,不做业务判定。逐单列表键名 `per_order`(含 `domain`)与\r\n * 后端 `_build_result_body` / 编排层 `trip-aggregate.json`(`$.per_order`)跨仓契约一致。\r\n */\r\nexport interface PayBatchResponse {\r\n payment_group_id: string;\r\n /** settled | partially_settled | failed | AUTHENTICATION_REQUIRED。 */\r\n status: string;\r\n currency?: string;\r\n /** 合计总额 = 各订单权威价之和(后端计算,调用方不传各订单金额)。 */\r\n total_amount?: number;\r\n per_order?: PayBatchOrderResult[];\r\n // ---- 3DS 挑战体专有字段 ----\r\n three_ds_url?: string;\r\n merchant_trans_id?: string;\r\n /** 挑战金额(= 合计总额)。 */\r\n amount?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n// ============================================================\r\n// Constants\r\n// ============================================================\r\n\r\n/** `--watch` 轮询间隔默认值(秒)。 */\r\nexport const DEFAULT_PAY_BATCH_WATCH_INTERVAL_SECONDS = 5;\r\n/** `--watch` 轮询超时默认值(秒)。 */\r\nexport const DEFAULT_PAY_BATCH_WATCH_TIMEOUT_SECONDS = 300;\r\n\r\n/**\r\n * 聚合支付的终态集合(对齐 checkout-cart plan 的 `poll` 步\r\n * `until: batch.status in [settled, partially_settled, failed]`)。大小写敏感,\r\n * 必须与后端返回的 `status` 字面量一致。`AUTHENTICATION_REQUIRED` 与授权/捕获中\r\n * 等状态均非终态,`--watch` 会继续轮询(幂等重放复查)。\r\n */\r\nexport const PAY_BATCH_TERMINAL_STATUSES: ReadonlySet<string> = new Set([\r\n 'settled',\r\n 'partially_settled',\r\n 'failed',\r\n]);\r\n\r\n// ============================================================\r\n// Input helper:解析 --order-ids(有序,可混合 hho_/ffo_/rio_ 三域)\r\n// ============================================================\r\n\r\n/**\r\n * 解析并 shape 校验 `--order-ids`。接受两种写法(都保持顺序):\r\n * - 逗号分隔:`hho_1,ffo_2,rio_3`;\r\n * - JSON 数组字符串:`[\"hho_1\",\"ffo_2\",\"rio_3\"]`。\r\n *\r\n * 产出一个非空、去除首尾空白后的字符串列表;空值/非字符串元素/空列表 → `PARAM_INVALID`\r\n * (在发起任何请求前抛出)。CLI 只做\"是一批非空 order_id\"的最小结构校验,**不校验前缀域**\r\n * ——具体不可支付单 / 币种不一致 / 令牌绑定不符由后端在 4xx 里标明 order_id 与原因。\r\n *\r\n * 导出以便注册命令与后续测试直接调用。\r\n */\r\nexport function parseOrderIds(raw: string): string[] {\r\n const INVALID =\r\n '--order-ids must be a comma-separated list OR a JSON array of order ids '\r\n + '(e.g. \"hho_1,ffo_2,rio_3\" or [\"hho_1\",\"ffo_2\"]).';\r\n\r\n const trimmed = raw.trim();\r\n let ids: string[];\r\n\r\n if (trimmed.startsWith('[')) {\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(trimmed);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n if (!parsed.every((el) => typeof el === 'string')) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n ids = (parsed as string[]).map((s) => s.trim());\r\n } else {\r\n ids = trimmed.split(',').map((s) => s.trim());\r\n }\r\n\r\n // 去除空片段(如尾随逗号),并要求至少一个有效 order_id。\r\n ids = ids.filter((s) => s.length > 0);\r\n if (ids.length === 0) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n return ids;\r\n}\r\n\r\n// ============================================================\r\n// Output helper\r\n// ============================================================\r\n\r\n/** 导出供 `orders get-payment-group` 复用:查进度和付款返回同形,展示也一致。 */\r\nexport function formatPayBatch(data: PayBatchResponse): string {\r\n const lines: [string, string][] = [\r\n ['Payment group', String(data.payment_group_id ?? '-')],\r\n ['Status', String(data.status ?? '-')],\r\n ];\r\n if (data.total_amount != null && data.currency) {\r\n lines.push(['Total', `${data.total_amount} ${data.currency}`]);\r\n }\r\n // 3DS 挑战体:透出续付所需的 URL / merchantTransID / 挑战金额。\r\n if (data.status === 'AUTHENTICATION_REQUIRED') {\r\n if (data.three_ds_url) lines.push(['3DS URL', String(data.three_ds_url)]);\r\n if (data.merchant_trans_id) lines.push(['Merchant trans ID', String(data.merchant_trans_id)]);\r\n if (data.amount != null && data.currency) {\r\n lines.push(['Challenge amount', `${data.amount} ${data.currency}`]);\r\n }\r\n }\r\n\r\n const out: string[] = [Formatter.keyValue(lines)];\r\n\r\n const perOrder = data.per_order ?? [];\r\n if (perOrder.length > 0) {\r\n const headers = ['Order ID', 'Domain', 'Status', 'Amount', 'Refunded'];\r\n const rows = perOrder.map((o) => [\r\n String(o.order_id ?? '-'),\r\n String(o.domain ?? '-'),\r\n String(o.status ?? '-'),\r\n String(o.amount ?? '-'),\r\n String(o.refunded_amount ?? '-'),\r\n ]);\r\n out.push('', Formatter.table(headers, rows));\r\n }\r\n\r\n return out.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Watch (polling) terminal predicate\r\n// ============================================================\r\n\r\n/**\r\n * 纯终态判定(导出以便单元/属性测试直接调用):`status ∈ {settled,\r\n * partially_settled, failed}` 即终态。缺失/未知状态永不终态,轮询继续直到终态或超时。\r\n */\r\nexport function isBatchTerminal(record: unknown): boolean {\r\n const status = (record as { status?: unknown }).status;\r\n return typeof status === 'string' && PAY_BATCH_TERMINAL_STATUSES.has(status);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `orders pay-batch` —— 行程聚合支付:以**一份支付凭证**对一批订单(`order_ids[]`,\r\n * 可混合 `hho_`/`ffo_`/`rio_` 三域)一次结算合计总额。调用 `POST /orders/pay-batch`,\r\n * `Idempotency-Key` 走 header,body 为\r\n * `{order_ids[], payment_token_id?, payment_method_id?, evo_explicit?, payment_group_id?, member_id?}`。\r\n *\r\n * - `--order-ids`(必填):有序订单列表(逗号分隔或 JSON 数组)。金额取各订单锁单落库的\r\n * 权威价、由后端求和,**调用方不传各订单金额**。\r\n * - `--payment-token-id`(可选,轨 A):以合计总额created、`external_transaction_id` 绑定到\r\n * 本次 payment_group 的网络令牌(银联/Visa 一次 passkey)。\r\n * - `--payment-method-id`(可选,轨 B):EVO 绑卡(一次 3DS)。\r\n * - `--evo-explicit`(可选,轨 B 硬门槛):仅在用户显式选择 EVO 时置位,透传 `evo_explicit=true`。\r\n * - `--payment-group-id`(可选):调用方预生成的组号;缺省由后端生成。\r\n * - `--member`(可选):归因的终端用户 member id。\r\n * - `--idempotency-key`(必填):原样作为 `Idempotency-Key` header 转发;相同键 + 有序\r\n * `order_ids` 重放为同一批次去重复查,不重复扣款。\r\n * - `--watch` / `--watch-interval` / `--watch-timeout`:NDJSON 轮询到终态\r\n * (`settled` / `partially_settled` / `failed`)。\r\n *\r\n * 这是真正动钱的一步(一次卡交互覆盖整趟总额),故非 `--yes` 路径在写之前必须二次确认;\r\n * `--yes` 跳过。确认被拒绝映射为 `CLIENT_ABORTED`(exit 5)。单发与 `--watch` 两条路径都\r\n * 适用(确认只在轮询开始前发生一次)。\r\n *\r\n * 成功:exit 0,打印聚合结算结果(含逐单成功/退款金额)。\r\n * 业务错误:exit 1,错误码写 stderr(后端在 4xx 里标明具体 order_id 与原因)。\r\n * Watch 模式:每次轮询输出一行 NDJSON。\r\n */\r\nexport function registerOrdersPayBatchCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('pay-batch')\r\n .description(\r\n 'Settle a batch of orders (may mix ride/hotel/flight) in one aggregate payment via a single payment credential',\r\n )\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option(\r\n '--order-ids <ids>',\r\n 'Ordered order ids to settle together — comma-separated (hho_1,ffo_2,rio_3) or a JSON array. '\r\n + 'May mix hho_/ffo_/rio_ domains. Amounts come from each order\\'s locked authoritative price (not passed here).',\r\n )\r\n .option(\r\n '--payment-token-id <id>',\r\n '[轨 A] Network-token id minted for the aggregate total and bound to this payment_group (unionpay/visa charge path)',\r\n )\r\n .option(\r\n '--payment-method-id <id>',\r\n '[轨 B] EVO bound-card id to settle the aggregate total (one 3DS challenge)',\r\n )\r\n .option(\r\n '--evo-explicit',\r\n '[轨 B 硬门槛] Explicit opt-in to settle via the EVO bound-card rail. Set ONLY when the user explicitly chose EVO; forwarded to the body as evo_explicit=true.',\r\n )\r\n .option(\r\n '--payment-group-id <id>',\r\n 'Optional caller-pre-generated payment group id; omit to let the platform generate one',\r\n )\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n )\r\n .option('--watch', 'Poll until a terminal batch status or timeout (NDJSON output)', false)\r\n .option(\r\n '--watch-interval <seconds>',\r\n 'Seconds between polls when --watch is set',\r\n String(DEFAULT_PAY_BATCH_WATCH_INTERVAL_SECONDS),\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n 'Max seconds to poll before giving up',\r\n String(DEFAULT_PAY_BATCH_WATCH_TIMEOUT_SECONDS),\r\n );\r\n\r\n // 挂 `--help --format json` verb schema(供工具发现 / Agent 本地读参,无需网络往返)。\r\n attachSchemaHelp(cmd, ordersPayBatchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // 必填 + shape 校验:在发起任何请求前完成 → PARAM_INVALID。\r\n const orderIds = parseOrderIds(need(opts.orderIds as string | undefined, 'order-ids'));\r\n\r\n // 幂等键解析:--yes 下缺失即硬错误(在任何请求前抛出)。\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'orders pay-batch',\r\n });\r\n\r\n // Watch 参数\r\n const watchEnabled = Boolean(opts.watch);\r\n const watchInterval = resolveSeconds(opts.watchInterval as string, DEFAULT_PAY_BATCH_WATCH_INTERVAL_SECONDS);\r\n const watchTimeout = resolveSeconds(opts.watchTimeout as string, DEFAULT_PAY_BATCH_WATCH_TIMEOUT_SECONDS);\r\n\r\n // Body 构造(薄透传):order_ids 必带;凭证 / evo_explicit / group / member 仅在提供时带上。\r\n const body: Record<string, unknown> = { order_ids: orderIds };\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n // 显式 EVO 选择信号:仅在置位时透传 evo_explicit=true;缺省不发(后端默认 false)。\r\n if (opts.evoExplicit) body.evo_explicit = true;\r\n if (opts.paymentGroupId !== undefined) body.payment_group_id = opts.paymentGroupId as string;\r\n // 归因标签:仅在显式传了非空 --member 时写入,缺省保持无归属。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n\r\n // 写前二次确认(除非 --yes)。这是真正动钱的一步:一次卡交互覆盖整趟合计总额\r\n // (银联/Visa 一次 passkey 或 EVO 一次 3DS)。合计总额由后端按权威价求和,CLI 端\r\n // 未知,故确认话术只声明订单笔数。提示走 stderr;拒绝映射 CLIENT_ABORTED(exit 5)。\r\n // 单发与 --watch 都适用(确认只在轮询开始前发生一次)。\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message:\r\n `Settle ${orderIds.length} order(s) in one aggregate payment? `\r\n + 'This moves money — a single charge covers the authoritative total of all listed orders '\r\n + '(banks/EVO see one transaction).',\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Aggregate payment aborted by user.');\r\n }\r\n }\r\n\r\n const path = '/orders/pay-batch';\r\n const headers = { 'Idempotency-Key': idempotencyKey };\r\n const auth = { type: 'api-key' as const, key: apiKey };\r\n\r\n if (!watchEnabled) {\r\n // 单发模式\r\n const spinner = format === 'json' ? null : createSpinner('Settling order batch...');\r\n\r\n const result = await deps.apiClient.post<PayBatchResponse>(path, auth, body, headers);\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<PayBatchResponse> = {\r\n data,\r\n text: () => formatPayBatch(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n } else {\r\n // Watch 模式:幂等重放复查同一批次,逐次输出 NDJSON,直到终态或超时。\r\n const deadline = Date.now() + watchTimeout * 1000;\r\n let lastRecord: unknown = null;\r\n\r\n for (;;) {\r\n const result = await deps.apiClient.post<PayBatchResponse>(path, auth, body, headers);\r\n\r\n if (result.success) {\r\n const data = result.data;\r\n lastRecord = data;\r\n ndjsonWriteLine(data);\r\n\r\n // 终态(settled / partially_settled / failed)→ 停止。非终态(授权/捕获中、\r\n // AUTHENTICATION_REQUIRED 等)→ 继续轮询:用户在 3DS 页外带完成认证后,\r\n // 后续一次幂等重放即结算。\r\n if (isBatchTerminal(data)) {\r\n return;\r\n }\r\n } else {\r\n // 业务错误(不可支付单 / 币种不一致 / 令牌绑定不符等)→ 直接 exit 1。\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n // 超时检查:下一次轮询将越过截止时间则收尾。\r\n if (Date.now() + watchInterval * 1000 >= deadline) {\r\n const timeoutLine = {\r\n watch_status: 'timeout',\r\n message: `Polling stopped after ${watchTimeout}s without reaching a terminal batch status.`,\r\n last_status: lastRecord,\r\n };\r\n ndjsonWriteLine(timeoutLine);\r\n return;\r\n }\r\n\r\n await realSleep(watchInterval * 1000);\r\n }\r\n }\r\n });\r\n}\r\n\r\n// ============================================================\r\n// Local input helper\r\n// ============================================================\r\n\r\n/** 必填标量取值:缺失即 PARAM_INVALID(在任何请求前抛出)。 */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, ordersGetPaymentGroupSchema } from '../verb-schema.js';\r\nimport { formatPayBatch, type PayBatchResponse } from './pay-batch.js';\r\n\r\n/** Platform caps the path segment at 64 chars; anything longer is rejected client-side. */\r\nconst PAYMENT_GROUP_ID_MAX = 64;\r\n\r\n/**\r\n * `orders get-payment-group` — read-only status of one aggregate settlement.\r\n *\r\n * `GET /orders/payment-groups/<payment_group_id>` with X-Api-Key. Returns the same\r\n * shape as `orders pay-batch` (settled / partially_settled / failed / uncertain, plus\r\n * per_order[]), so it is the way to check a batch after `pay-batch` without\r\n * re-sending the payment write. The platform scopes it to the caller's\r\n * organization; a group of another organization reads as not found.\r\n */\r\nexport function registerOrdersGetPaymentGroupCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('get-payment-group')\r\n .description('Get the status of an aggregate settlement created by `orders pay-batch` (read-only)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .requiredOption('--payment-group-id <id>', 'payment_group_id returned by `orders pay-batch`');\r\n\r\n attachSchemaHelp(cmd, ordersGetPaymentGroupSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const groupId = String(opts.paymentGroupId ?? '').trim();\r\n if (!groupId || groupId.length > PAYMENT_GROUP_ID_MAX) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `--payment-group-id must be 1-${PAYMENT_GROUP_ID_MAX} characters.`,\r\n );\r\n }\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching payment group...');\r\n const result = await deps.apiClient.get<PayBatchResponse>(\r\n `/orders/payment-groups/${encodeURIComponent(groupId)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const commandResult: CommandResult<PayBatchResponse> = {\r\n data,\r\n text: () => formatPayBatch(data),\r\n };\r\n await renderWithContext(commandResult, { format }, new ConfigManager());\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { SearchHotelResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelSearchSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/quote.ts and book.ts each define\r\n// their own need/num) rather than pulled from a shared helpers file.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 2.3 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Number-ify a coordinate flag and enforce its valid range. Missing,\r\n * non-finite, or out-of-range input maps to `PARAM_INVALID` (requirement 2.4)\r\n * before any request is sent. Coordinates are sent as numbers, never strings.\r\n */\r\nfunction coord(value: string | undefined, flag: string, min: number, max: number): number {\r\n const n = num(value, flag);\r\n if (n < min || n > max) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be between ${min} and ${max}.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Validate a supplied flag as a positive integer. `undefined` is allowed\r\n * (caller decides whether the flag is required). Non-finite or ≤ 0 → `PARAM_INVALID`.\r\n */\r\nfunction positiveInt(value: string | undefined, flag: string): number {\r\n const n = num(value, flag);\r\n if (!Number.isInteger(n) || n <= 0) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\r\n }\r\n return n;\r\n}\r\n\r\nconst YMD_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\r\n\r\n/**\r\n * Require and validate a stay date. The value must be a real `YYYY-MM-DD`\r\n * calendar date (e.g. `2026-02-30` is rejected); otherwise `PARAM_INVALID`\r\n * (requirement 2.5) before any request is sent. Returns the canonical string.\r\n */\r\nfunction stayDate(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n if (!YMD_RE.test(raw)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a YYYY-MM-DD date.`);\r\n }\r\n const [y, m, d] = raw.split('-').map(Number);\r\n const dt = new Date(Date.UTC(y, m - 1, d));\r\n if (dt.getUTCFullYear() !== y || dt.getUTCMonth() !== m - 1 || dt.getUTCDate() !== d) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a valid calendar date (YYYY-MM-DD).`);\r\n }\r\n return raw;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the search hits as a table for `--format table`. Each hotel is one\r\n * row; the indicative `lowest_price.amount` is a decimal currency unit (NOT\r\n * cents) — printed verbatim. An empty `hotels` list is a successful result, so\r\n * it renders an info line (never an error).\r\n *\r\n * Extended fields from enriched HotelSummary (city_name, score, main_image) are\r\n * included when present.\r\n */\r\nfunction formatSearch(data: SearchHotelResponse): string {\r\n const hotels = data.hotels ?? [];\r\n if (hotels.length === 0) {\r\n return Formatter.status('info', 'No hotels found for this area and dates');\r\n }\r\n\r\n const headers = ['Hotel ID', 'Name', 'Star', 'Distance (km)', 'From', 'Currency', 'City', 'Score', 'Image', 'Address'];\r\n const rows = hotels.map((h) => [\r\n String(h.hotel_id ?? '-'),\r\n String(h.hotel_name ?? '-'),\r\n String(h.star ?? '-'),\r\n String(h.distance_km ?? '-'),\r\n String(h.lowest_price?.amount ?? '-'),\r\n String(h.lowest_price?.currency ?? '-'),\r\n String(h.city_name ?? '-'),\r\n String(h.score ?? '-'),\r\n String(h.main_image ?? '-'),\r\n String(h.address ?? '-'),\r\n ]);\r\n\r\n return Formatter.table(headers, rows);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug search` — search hotels near a coordinate or within a\r\n * destination for a stay (§ search schema). Read-only (no idempotency key).\r\n *\r\n * Accepts exactly one location branch:\r\n * Branch A: --destination-id (alone, no lat/lng needed)\r\n * Branch B: --lat AND --lng (both required together)\r\n * Supplying both branches or neither → PARAM_INVALID before any request.\r\n *\r\n * Builds the `/hotel/search` body from flags (coordinates number-ified and\r\n * range-checked when coordinate branch, dates validated as `YYYY-MM-DD` with\r\n * `check-out` strictly after `check-in`, all before any request → `PARAM_INVALID`),\r\n * POSTs with the `X-Api-Key` auth, and renders `SearchHotelResponse` via\r\n * `renderWithContext` (json carries the profile/endpoint envelope). An empty\r\n * `hotels` list renders as a successful result (exit 0), not an error.\r\n */\r\nexport function registerHotelSearchCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('search')\r\n .description('Search hotels near a coordinate or within a destination for the given stay dates')\r\n // Location branch A: destination-id\r\n .option('--destination-id <id>', 'Destination ID (alternative to --lat/--lng)')\r\n // Location branch B: lat/lng\r\n .option('--lat <lat>', 'Latitude of the search center (-90 to 90)')\r\n .option('--lng <lng>', 'Longitude of the search center (-180 to 180)')\r\n // Common location/search params\r\n .option('--distance <km>', 'Search radius in kilometers', '20')\r\n .option('--check-in <date>', 'Check-in date (YYYY-MM-DD)')\r\n .option('--check-out <date>', 'Check-out date (YYYY-MM-DD, strictly after check-in)')\r\n .option('--adults <n>', 'Number of adults', '2')\r\n .option('--children <n>', 'Number of children', '0')\r\n .option('--room-num <n>', 'Number of rooms requested', '1')\r\n .option('--star <n>', 'Minimum hotel star rating filter (3/4/5)')\r\n .option('--keyword <text>', 'Optional hotel name keyword to narrow results')\r\n // Filter flags (each forwarded only when supplied)\r\n .option('--price-min <n>', 'Minimum price filter')\r\n .option('--price-max <n>', 'Maximum price filter')\r\n .option('--sort-by <field>', 'Sort field')\r\n .option('--page <n>', 'Page number (positive integer)', '1')\r\n .option('--page-size <n>', 'Results per page (positive integer)', '10')\r\n .option('--hotel-facility-codes <codes>', 'Hotel facility codes (comma-separated or JSON array)')\r\n .option('--room-facility-codes <codes>', 'Room facility codes (comma-separated or JSON array)')\r\n .option('--hotel-brand-codes <codes>', 'Hotel brand codes (comma-separated or JSON array)')\r\n .option('--plate-codes <codes>', 'Plate codes (comma-separated or JSON array)')\r\n .option('--hotel-label-ids <ids>', 'Hotel label IDs (comma-separated or JSON array)')\r\n .option('--hotel-sub-category-ids <ids>', 'Hotel sub-category IDs (comma-separated or JSON array)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n\r\n attachSchemaHelp(cmd, hotelSearchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // ---- Location branch validation (BEFORE any request) ----\r\n // Exactly one branch must be supplied:\r\n // Branch A: --destination-id (alone)\r\n // Branch B: --lat AND --lng (both required together)\r\n // Both branches OR neither → PARAM_INVALID.\r\n const hasDestination = opts.destinationId !== undefined;\r\n const hasLat = opts.lat !== undefined;\r\n const hasLng = opts.lng !== undefined;\r\n const hasCoordBranch = hasLat || hasLng;\r\n\r\n if (hasDestination && hasCoordBranch) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Supply either --destination-id OR --lat/--lng, not both.',\r\n );\r\n }\r\n\r\n if (!hasDestination && !hasCoordBranch) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Supply either --destination-id OR --lat/--lng (one location branch is required).',\r\n );\r\n }\r\n\r\n // Coordinate branch: both lat AND lng must be present, with valid ranges.\r\n if (hasCoordBranch && !(hasLat && hasLng)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n '--lat and --lng must both be provided together.',\r\n );\r\n }\r\n\r\n // ---- Date validation (common to both branches) ----\r\n const checkIn = stayDate(opts.checkIn as string | undefined, 'check-in');\r\n const checkOut = stayDate(opts.checkOut as string | undefined, 'check-out');\r\n // Both are validated YYYY-MM-DD, so a lexical compare is a correct date\r\n // order; check-out must be strictly after check-in.\r\n if (!(checkOut > checkIn)) {\r\n throw new CliError('PARAM_INVALID', '--check-out must be strictly after --check-in.');\r\n }\r\n\r\n // ---- Pagination validation (BEFORE any request) ----\r\n const page = positiveInt(opts.page as string | undefined, 'page');\r\n const pageSize = positiveInt(opts.pageSize as string | undefined, 'page-size');\r\n\r\n // ---- Build request body ----\r\n // Location branch: destination_id OR (lat, lng)\r\n const body: Record<string, unknown> = {};\r\n\r\n if (hasDestination) {\r\n body.destination_id = need(opts.destinationId as string | undefined, 'destination-id');\r\n } else {\r\n body.lat = coord(opts.lat as string | undefined, 'lat', -90, 90);\r\n body.lng = coord(opts.lng as string | undefined, 'lng', -180, 180);\r\n }\r\n\r\n // Common fields\r\n body.distance = num(opts.distance as string | undefined, 'distance');\r\n body.check_in = checkIn;\r\n body.check_out = checkOut;\r\n body.adults = num(opts.adults as string | undefined, 'adults');\r\n body.children = num(opts.children as string | undefined, 'children');\r\n body.room_num = num(opts.roomNum as string | undefined, 'room-num');\r\n\r\n // Optional filters — included only when supplied (omitted keys never enter\r\n // the body). --star is numeric when present; --keyword is free text.\r\n if (opts.star !== undefined) body.star = num(opts.star as string, 'star');\r\n if (opts.keyword !== undefined) body.keyword = opts.keyword as string;\r\n\r\n // Price filters (numeric when present)\r\n if (opts.priceMin !== undefined) body.price_min = num(opts.priceMin as string, 'price-min');\r\n if (opts.priceMax !== undefined) body.price_max = num(opts.priceMax as string, 'price-max');\r\n\r\n // Sort\r\n if (opts.sortBy !== undefined) body.sort_by = opts.sortBy as string;\r\n\r\n // Pagination (always included — has defaults)\r\n body.page = page;\r\n body.page_size = pageSize;\r\n\r\n // Opaque code array filters — forwarded as-is when supplied\r\n if (opts.hotelFacilityCodes !== undefined) body.hotel_facility_codes = opts.hotelFacilityCodes as string;\r\n if (opts.roomFacilityCodes !== undefined) body.room_facility_codes = opts.roomFacilityCodes as string;\r\n if (opts.hotelBrandCodes !== undefined) body.hotel_brand_codes = opts.hotelBrandCodes as string;\r\n if (opts.plateCodes !== undefined) body.plate_codes = opts.plateCodes as string;\r\n if (opts.hotelLabelIds !== undefined) body.hotel_label_ids = opts.hotelLabelIds as string;\r\n if (opts.hotelSubCategoryIds !== undefined) body.hotel_sub_category_ids = opts.hotelSubCategoryIds as string;\r\n\r\n const result = await deps.apiClient.post<SearchHotelResponse>(\r\n '/hotel/search',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<SearchHotelResponse> = {\r\n data,\r\n text: () => formatSearch(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { QuoteHotelResponse, HotelRate, PriceItem } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelQuoteSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/quote.ts and hotel-redaug/search.ts\r\n// each define their own need/num/stayDate) rather than pulled from a shared\r\n// helpers file. `quote` is read-only — no idempotency key.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 3.3 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\nconst YMD_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\r\n\r\n/**\r\n * Require and validate a stay date. The value must be a real `YYYY-MM-DD`\r\n * calendar date (e.g. `2026-02-30` is rejected); otherwise `PARAM_INVALID`\r\n * (requirement 3.4) before any request is sent. Returns the canonical string.\r\n */\r\nfunction stayDate(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n if (!YMD_RE.test(raw)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a YYYY-MM-DD date.`);\r\n }\r\n const [y, m, d] = raw.split('-').map(Number);\r\n const dt = new Date(Date.UTC(y, m - 1, d));\r\n if (dt.getUTCFullYear() !== y || dt.getUTCMonth() !== m - 1 || dt.getUTCDate() !== d) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a valid calendar date (YYYY-MM-DD).`);\r\n }\r\n return raw;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Compact per-night summary of a rate's `price_items`. Each night is\r\n * `<date>: <sale_price> (bf <n>)`; `sale_price` is a DECIMAL currency amount\r\n * (NOT cents) — printed verbatim. An empty breakdown renders as `-`.\r\n */\r\nfunction summarizePriceItems(items: PriceItem[] | undefined): string {\r\n if (!items || items.length === 0) return '-';\r\n return items\r\n .map((it) => `${it.sale_date}: ${it.sale_price} (bf ${it.breakfast_num})`)\r\n .join('; ');\r\n}\r\n\r\n/**\r\n * Render the bookable rates as a table for `--format table`. Each rate is one\r\n * row carrying the opaque `product_token` (printed verbatim — passed to `book`\r\n * unchanged), room name, the whole-stay `total_price.amount`+`currency` (DECIMAL\r\n * units, NOT cents — printed verbatim), and a per-night `price_items` summary.\r\n * An empty `rates` list is a successful result, so it renders an info line\r\n * (never an error).\r\n */\r\nfunction formatQuote(data: QuoteHotelResponse): string {\r\n const rates: HotelRate[] = data.rates ?? [];\r\n if (rates.length === 0) {\r\n return Formatter.status('info', 'No bookable rates for this hotel and dates');\r\n }\r\n\r\n const headers = ['Product Token', 'Room', 'Total', 'Currency', 'Per-night (price_items)'];\r\n const rows = rates.map((r) => [\r\n String(r.product_token ?? '-'),\r\n String(r.room_name ?? '-'),\r\n String(r.total_price?.amount ?? '-'),\r\n String(r.total_price?.currency ?? '-'),\r\n summarizePriceItems(r.price_items),\r\n ]);\r\n\r\n return Formatter.table(headers, rows);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug quote` — get real-time room types and bookable rates for one\r\n * hotel and stay (§ quote schema). Read-only (no idempotency key).\r\n *\r\n * Builds the `/hotel/quote` body from flags (`--hotel-id` required, dates\r\n * validated as `YYYY-MM-DD` with `check-out` strictly after `check-in`, numeric\r\n * guest/room flags finite — all before any request → `PARAM_INVALID`), POSTs\r\n * with the `X-Api-Key` auth, and renders `QuoteHotelResponse` via\r\n * `renderWithContext` (json carries the profile/endpoint envelope). Each rate's\r\n * `product_token`, `total_price.amount`/`currency` and `price_items` are decimal\r\n * units rendered verbatim. An empty `rates` list renders as a successful result\r\n * (exit 0), not an error.\r\n */\r\nexport function registerHotelQuoteCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('quote')\r\n .description('Get real-time room types and bookable rates for one hotel and stay')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--hotel-id <id>', 'Hotel chosen from search results (hotels[].hotel_id)')\r\n .option('--check-in <date>', 'Check-in date (YYYY-MM-DD, match search)')\r\n .option('--check-out <date>', 'Check-out date (YYYY-MM-DD, strictly after check-in)')\r\n .option('--adults <n>', 'Number of adults per room', '2')\r\n .option('--children <n>', 'Number of children per room', '0')\r\n .option('--room-num <n>', 'Number of rooms requested', '1')\r\n .option('--nationality <code>', 'Guest nationality (ISO country code)', 'CN');\r\n\r\n attachSchemaHelp(cmd, hotelQuoteSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build request body. All validation throws PARAM_INVALID BEFORE any\r\n // request: --hotel-id required; dates real YYYY-MM-DD with check-out\r\n // strictly after check-in; the numeric guest/room flags finite. snake_case\r\n // keys match the platform contract.\r\n const hotelId = need(opts.hotelId as string | undefined, 'hotel-id');\r\n\r\n const checkIn = stayDate(opts.checkIn as string | undefined, 'check-in');\r\n const checkOut = stayDate(opts.checkOut as string | undefined, 'check-out');\r\n // Both are validated YYYY-MM-DD, so a lexical compare is a correct date\r\n // order; check-out must be strictly after check-in.\r\n if (!(checkOut > checkIn)) {\r\n throw new CliError('PARAM_INVALID', '--check-out must be strictly after --check-in.');\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n hotel_id: hotelId,\r\n check_in: checkIn,\r\n check_out: checkOut,\r\n adults: num(opts.adults as string | undefined, 'adults'),\r\n children: num(opts.children as string | undefined, 'children'),\r\n room_num: num(opts.roomNum as string | undefined, 'room-num'),\r\n nationality: opts.nationality as string,\r\n };\r\n\r\n const result = await deps.apiClient.post<QuoteHotelResponse>(\r\n '/hotel/quote',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<QuoteHotelResponse> = {\r\n data,\r\n text: () => formatQuote(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { PriceItem, RoomGuest } from '../types/hotel.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, hotelCreateOrderSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\n\r\n// ============================================================\r\n// Structured-flag parser (pure builder — directly property-testable)\r\n// ============================================================\r\n\r\n/**\r\n * Parse and shape-validate `--price-items`.\r\n *\r\n * The raw flag MUST be a JSON array in which every element carries `sale_date`\r\n * (string), `sale_price` (number), and `breakfast_num` (number). Any deviation\r\n * — non-JSON, a non-array, or any element missing/mistyping a required field —\r\n * raises `PARAM_INVALID` before any request is issued.\r\n *\r\n * The parsed array is returned VERBATIM (the actual parsed objects, extra keys\r\n * untouched) and forwarded as-is in the request body: `sale_price` is a DECIMAL\r\n * currency amount and is never converted to/from minor units.\r\n *\r\n * Exported so tests and other verbs can import and exercise it directly.\r\n */\r\nexport function parsePriceItems(raw: string): PriceItem[] {\r\n const INVALID =\r\n '--price-items must be a JSON array of {sale_date (string), sale_price (number), breakfast_num (number)}.';\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n for (const el of parsed) {\r\n if (typeof el !== 'object' || el === null || Array.isArray(el)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n const item = el as Record<string, unknown>;\r\n if (\r\n typeof item.sale_date !== 'string' ||\r\n typeof item.sale_price !== 'number' ||\r\n typeof item.breakfast_num !== 'number'\r\n ) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n }\r\n\r\n // Forwarded verbatim — the parsed objects are returned unchanged.\r\n return parsed as PriceItem[];\r\n}\r\n\r\n/**\r\n * Parse and shape-validate `--room-guests`.\r\n *\r\n * Optional per-room primary guests, so several rooms can be booked under\r\n * different names. The raw flag MUST be a non-empty JSON array in which every\r\n * element carries `guest_name` (non-empty string). `room_index` is OPTIONAL:\r\n * callers list the names in room order and the 1-based index is filled in from\r\n * the array position; supplying it explicitly is allowed and then wins. Any\r\n * other deviation raises `PARAM_INVALID` before any request is issued.\r\n *\r\n * Omitting the flag entirely is the backward-compatible path: the platform then\r\n * reuses `guest_name` for every room.\r\n *\r\n * Elements are forwarded as-is apart from the filled-in `room_index` (extra\r\n * keys untouched); the platform validates `room_index` against `room_num` and\r\n * sends the names upstream.\r\n *\r\n * Exported so tests and other verbs can import and exercise it directly.\r\n */\r\nexport function parseRoomGuests(raw: string): RoomGuest[] {\r\n const INVALID =\r\n '--room-guests must be a JSON array of {guest_name (non-empty string), room_index (optional 1-based integer)}.';\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n if (!Array.isArray(parsed) || parsed.length === 0) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n return parsed.map((el, i) => {\r\n if (typeof el !== 'object' || el === null || Array.isArray(el)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n const item = el as Record<string, unknown>;\r\n if (typeof item.guest_name !== 'string' || item.guest_name.trim() === '') {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n // room_index is OPTIONAL: callers just list the names in room order and the\r\n // 1-based index is filled in here. Supplying it is still allowed (and then\r\n // wins), but 0 / negatives / non-integers are the classic off-by-one and are\r\n // rejected locally rather than after a round trip. The upper bound is left\r\n // to the platform (it validates against room_num) so the two never disagree.\r\n if (item.room_index === undefined) {\r\n return { ...item, room_index: i + 1 } as unknown as RoomGuest;\r\n }\r\n if (!Number.isInteger(item.room_index) || (item.room_index as number) < 1) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n // Other keys are forwarded untouched.\r\n return item as unknown as RoomGuest;\r\n });\r\n}\r\n\r\n/**\r\n * Parse and shape-validate `--tips` (客户自测点5 提示信息).\r\n *\r\n * The raw flag MUST be a JSON array of objects, each optionally carrying\r\n * `title` and `text` (strings). Snapshot of the chosen rate's tips, persisted\r\n * on the order for the order-detail page; NOT forwarded upstream.\r\n */\r\nexport function parseTips(raw: string): Array<{ title?: string; text?: string }> {\r\n const INVALID = '--tips must be a JSON array of {title (string, optional), text (string, optional)}.';\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n for (const el of parsed) {\r\n if (typeof el !== 'object' || el === null || Array.isArray(el)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n const item = el as Record<string, unknown>;\r\n if (\r\n (item.title !== undefined && typeof item.title !== 'string') ||\r\n (item.text !== undefined && typeof item.text !== 'string')\r\n ) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n }\r\n\r\n return parsed as Array<{ title?: string; text?: string }>;\r\n}\r\n\r\n/** 解析并校验订单取消条款快照;该对象只在平台落库,不发送给供应商。 */\r\nexport function parseCancellation(raw: string): Record<string, unknown> {\r\n const invalid = '--cancellation must be a JSON object.';\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', invalid);\r\n }\r\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', invalid);\r\n }\r\n return parsed as Record<string, unknown>;\r\n}\r\n\r\n// ============================================================\r\n// Response type\r\n// ============================================================\r\n\r\nexport interface CreateHotelOrderResponse {\r\n order_id: string;\r\n fc_order_code: string;\r\n order_status: string;\r\n total_amount: number;\r\n currency: string;\r\n rooms?: Array<{ room_index: string; guest_name: string }>;\r\n}\r\n\r\n// ============================================================\r\n// Input helpers (reused from book.ts pattern)\r\n// ============================================================\r\n\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\nconst YMD_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\r\n\r\nfunction stayDate(value: string | undefined, flag: string): string {\r\n const raw = need(value, flag);\r\n if (!YMD_RE.test(raw)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a YYYY-MM-DD date.`);\r\n }\r\n const [y, m, d] = raw.split('-').map(Number);\r\n const dt = new Date(Date.UTC(y, m - 1, d));\r\n if (dt.getUTCFullYear() !== y || dt.getUTCMonth() !== m - 1 || dt.getUTCDate() !== d) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a valid calendar date (YYYY-MM-DD).`);\r\n }\r\n return raw;\r\n}\r\n\r\n// ============================================================\r\n// Output helper\r\n// ============================================================\r\n\r\nfunction formatCreateOrder(data: CreateHotelOrderResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['FC order code', String(data.fc_order_code ?? '-')],\r\n ['Order status', String(data.order_status ?? '-')],\r\n ['Total amount', `${data.total_amount} ${data.currency}`],\r\n ];\r\n\r\n const out: string[] = [Formatter.keyValue(lines)];\r\n\r\n const rooms = data.rooms ?? [];\r\n if (rooms.length > 0) {\r\n const headers = ['Room index', 'Guest name'];\r\n const rows = rooms.map((r) => [String(r.room_index ?? '-'), String(r.guest_name ?? '-')]);\r\n out.push('', Formatter.table(headers, rows));\r\n }\r\n\r\n out.push(\r\n '',\r\n Formatter.status(\r\n 'info',\r\n `Order created with status AWAITING_PAYMENT — proceed with 'hotel-redaug pay-order --order-id ${data.order_id ?? '<order_id>'}' to settle.`,\r\n ),\r\n );\r\n\r\n return out.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug create-order` — create a hotel order without charging any\r\n * account. Calls `POST /hotel/create-order` with `Idempotency-Key` header.\r\n * On success: exit 0, prints the created order_id to stdout.\r\n *\r\n * This is the first step of the create-then-pay flow; the order enters\r\n * AWAITING_PAYMENT status and must be settled via `pay-order`. Locking a rate\r\n * is a real commitment (though not a charge), so the non-`--yes` path MUST\r\n * confirm (restating amount/currency/dates) before the write; `--yes` skips\r\n * it. A declined confirm maps to `CLIENT_ABORTED` (exit 5).\r\n */\r\nexport function registerHotelCreateOrderCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('create-order')\r\n .description('Create a hotel order without charging (lock inventory, await payment)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--product-token <token>', 'Chosen rate token from quote (rates[].product_token)')\r\n .option('--total-amount <amount>', 'Total stay price in decimal currency units (not cents)')\r\n .option('--currency <currency>', 'ISO 4217 currency code from the chosen rate')\r\n .option('--price-items <json>', 'Per-night price breakdown JSON array (copied verbatim from quote)')\r\n .option('--check-in <date>', 'Check-in date (YYYY-MM-DD, match quote)')\r\n .option('--check-out <date>', 'Check-out date (YYYY-MM-DD, strictly after check-in)')\r\n .option('--room-num <n>', 'Number of rooms (match quote)', '1')\r\n .option('--adults <n>', 'Adults per room (match quote)', '2')\r\n .option('--children <n>', 'Children per room (match quote)', '0')\r\n .option('--nationality <code>', 'Guest nationality (ISO country code)', 'CN')\r\n .option('--guest-name <name>', 'Primary guest name')\r\n .option(\r\n '--room-guests <json>',\r\n 'Optional per-room primary guests as a JSON array [{guest_name}], listed in room ' +\r\n 'order, for booking several rooms under different names. room_index is filled in ' +\r\n 'from the array position (1-based); pass it explicitly to override. Omit the flag ' +\r\n 'and every room reuses --guest-name.',\r\n )\r\n .option('--contact-name <name>', 'Booking contact name (may equal guest-name)')\r\n .option('--contact-phone <phone>', 'Booking contact phone number (digits)')\r\n .option('--contact-country-code <code>', \"Phone country calling code without '+'\", '86')\r\n .option('--contact-email <email>', 'Booking contact email')\r\n .option('--arrive-time <time>', 'Expected arrival time (HH:mm, hotel local time)')\r\n .option('--special-requests <text>', 'Free-text special requests (non-binding)')\r\n .option(\r\n '--tips <json>',\r\n \"客户自测点5 提示信息: the chosen quote rate's tips as a JSON array [{title,text}]. Stored on the order for the order-detail page ONLY — platform-local, not sent upstream.\",\r\n )\r\n .option('--hotel-name <name>', 'Hotel name (display-only, stored for order summary)')\r\n .option(\r\n '--cancellation <json>',\r\n 'Cancellation policy JSON from the chosen rate; stored on the order for cancellation gating and deadline display.',\r\n )\r\n .option(\r\n '--hotel-timezone <tz>',\r\n \"Hotel timezone from quote (for example 'UTC+8'); stored to evaluate cancellation deadlines in hotel-local time.\",\r\n )\r\n .option(\r\n '--bed-type <code>',\r\n \"Product bed-type code from the chosen quote rate's beds[].code (e.g. 'L000000' King / '1000000' Queen); forwarded verbatim to upstream createOrder bedType.\",\r\n )\r\n .option(\r\n '--payment-method-id <id>',\r\n 'Optional bound-card id (pay_per_call / EVO path). When set, the platform settles this order by pre-authorizing + capturing on that specific bound card. Omit to let the platform pick by billing_mode.',\r\n )\r\n .option(\r\n '--payment-token-id <id>',\r\n 'UPI Agent Pay: payment token id from an already-completed UnionPay network-token capture. When set, the platform skips EVO preauth/capture and only locks the order + records this credential (funds already charged).',\r\n )\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'EVO merchant transaction id of an already-authorised preauth (3DS challenge resume). ' +\r\n 'When set, the server reuses that authorization instead of creating a new one, ' +\r\n 'avoiding a second hold on the card (pay_per_call mode only).',\r\n )\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelCreateOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required + typed validation — ALL before any request → PARAM_INVALID.\r\n const productToken = need(opts.productToken as string | undefined, 'product-token');\r\n const totalAmount = num(opts.totalAmount as string | undefined, 'total-amount');\r\n const currency = need(opts.currency as string | undefined, 'currency');\r\n const priceItems = parsePriceItems(need(opts.priceItems as string | undefined, 'price-items'));\r\n\r\n const checkIn = stayDate(opts.checkIn as string | undefined, 'check-in');\r\n const checkOut = stayDate(opts.checkOut as string | undefined, 'check-out');\r\n if (!(checkOut > checkIn)) {\r\n throw new CliError('PARAM_INVALID', '--check-out must be strictly after --check-in.');\r\n }\r\n\r\n const guestName = need(opts.guestName as string | undefined, 'guest-name');\r\n const contactName = need(opts.contactName as string | undefined, 'contact-name');\r\n const contactPhone = need(opts.contactPhone as string | undefined, 'contact-phone');\r\n\r\n const body: Record<string, unknown> = {\r\n product_token: productToken,\r\n total_amount: totalAmount,\r\n currency,\r\n price_items: priceItems,\r\n check_in: checkIn,\r\n check_out: checkOut,\r\n room_num: num(opts.roomNum as string | undefined, 'room-num'),\r\n adults: num(opts.adults as string | undefined, 'adults'),\r\n children: num(opts.children as string | undefined, 'children'),\r\n nationality: opts.nationality as string,\r\n guest_name: guestName,\r\n contact_name: contactName,\r\n contact_phone: contactPhone,\r\n contact_country_code: opts.contactCountryCode as string,\r\n };\r\n\r\n // Optional fields — included only when supplied.\r\n // 每间房各自的住客名:不传则平台让所有房间沿用 guest_name(向后兼容)。\r\n if (opts.roomGuests !== undefined) body.room_guests = parseRoomGuests(opts.roomGuests as string);\r\n if (opts.contactEmail !== undefined) body.contact_email = opts.contactEmail as string;\r\n if (opts.arriveTime !== undefined) body.arrive_time = opts.arriveTime as string;\r\n if (opts.specialRequests !== undefined) body.special_requests = opts.specialRequests as string;\r\n // 提示信息快照(客户自测点5):解析并校验 tips JSON,传给平台落库、订单详情页展示。\r\n if (opts.tips !== undefined) body.tips = parseTips(opts.tips as string);\r\n if (opts.cancellation !== undefined) body.cancellation = parseCancellation(opts.cancellation as string);\r\n if (opts.hotelTimezone !== undefined) body.hotel_timezone = opts.hotelTimezone as string;\r\n if (opts.hotelName !== undefined) body.hotel_name = opts.hotelName as string;\r\n if (opts.bedType !== undefined) body.bed_type = opts.bedType as string;\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n // 3DS 挑战续单凭证:持卡人完成认证后带回该交易号,服务端复用那笔已授权的预授权,\r\n // 不再新发起一次(否则又拿到新挑战页且重复冻结资金)。\r\n if (opts.authorizedMerchantTransId) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 归因标签:只在调用方显式传了非空 --member 时写入,缺省订单保持无归属(见\r\n // doc/member-id-attribution-design.md 不变量 3)。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n\r\n // Confirm before the write unless --yes. This locks inventory at the quoted\r\n // rate — the user must have already picked this hotel/rate (from search +\r\n // quote), so the prompt restates what is being locked in before the call is\r\n // made. The prompt goes to stderr; declining maps to CLIENT_ABORTED (exit 5)\r\n // via the top-level envelope.\r\n if (!isYes) {\r\n const chargeNote = opts.paymentTokenId !== undefined\r\n ? 'Payment has already been captured via UPI Agent Pay; this only locks the room.'\r\n : 'This locks the rate but does NOT charge anything yet.';\r\n const confirmed = await confirm({\r\n message: `Create this hotel order for ${totalAmount} ${currency} (check-in ${checkIn}, check-out ${checkOut})? ${chargeNote}`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Order creation aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key resolution — under --yes a missing key is a hard error.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'hotel-redaug create-order',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Creating hotel order...');\r\n\r\n const result = await deps.apiClient.post<CreateHotelOrderResponse>(\r\n '/hotel/create-order',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CreateHotelOrderResponse> = {\r\n data,\r\n text: () => formatCreateOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { PRICE_ANNOTATION_FLAGS, applyPriceAnnotation } from '../price-annotation.js';\r\nimport { attachSchemaHelp, hotelPayOrderSchema } from '../verb-schema.js';\r\nimport {\r\n ndjsonWriteLine,\r\n realSleep,\r\n resolveSeconds,\r\n} from './watch.js';\r\n\r\n// ============================================================\r\n// Response type\r\n// ============================================================\r\n\r\nexport interface PayHotelOrderResponse {\r\n order_id: string;\r\n order_status: string;\r\n settlement_path?: string;\r\n pay_status?: string;\r\n total_amount?: number;\r\n currency?: string;\r\n billing_entry_id?: string;\r\n /** For the pay_per_call settlement path, this echoes the order_id (the EVO merchantTransID). */\r\n merchant_trans_id?: string;\r\n /** AUTHENTICATION_REQUIRED when the network-token authenticate path needs a 3DS step-up. */\r\n status?: string;\r\n /** 3DS/passkey challenge URL (present with status=AUTHENTICATION_REQUIRED). */\r\n three_ds_url?: string;\r\n /** Resume handle for the network-token 3DS path (feed back as --authorized-charge-no). */\r\n charge_no?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\n// ============================================================\r\n// Constants\r\n// ============================================================\r\n\r\n/** Default polling interval for --watch mode (seconds). */\r\nexport const DEFAULT_PAY_WATCH_INTERVAL_SECONDS = 5;\r\n/** Default polling timeout for --watch mode (seconds). */\r\nexport const DEFAULT_PAY_WATCH_TIMEOUT_SECONDS = 300;\r\n\r\n// ============================================================\r\n// Output helper\r\n// ============================================================\r\n\r\nfunction formatPayOrder(data: PayHotelOrderResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['Order status', String(data.order_status ?? '-')],\r\n ];\r\n if (data.settlement_path) lines.push(['Settlement path', String(data.settlement_path)]);\r\n if (data.pay_status) lines.push(['Pay status', String(data.pay_status)]);\r\n if (data.status) lines.push(['Status', String(data.status)]);\r\n if (data.total_amount != null && data.currency) {\r\n lines.push(['Amount', `${data.total_amount} ${data.currency}`]);\r\n }\r\n if (data.billing_entry_id) lines.push(['Billing entry', String(data.billing_entry_id)]);\r\n if (data.merchant_trans_id) lines.push(['Merchant trans ID', String(data.merchant_trans_id)]);\r\n // 网络令牌 3DS 挑战:透出续付句柄与挑战地址,供调用方打开认证页并回带续付。\r\n if (data.charge_no) lines.push(['Charge no', String(data.charge_no)]);\r\n if (data.three_ds_url) lines.push(['3DS URL', String(data.three_ds_url)]);\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Watch (polling) logic for pay-order\r\n// ============================================================\r\n\r\n/**\r\n * Terminal predicate for pay-order watch: PAID means done.\r\n * Any error response triggers exit 1 outside the loop (thrown as CliError).\r\n */\r\nfunction isPaymentTerminal(record: unknown): boolean {\r\n const status = (record as { order_status?: unknown }).order_status;\r\n return status === 'PAID';\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug pay-order` — settle an existing hotel order created via\r\n * `create-order`. Calls `POST /hotel/{order_id}/pay` with an `Idempotency-Key`\r\n * header and an empty body.\r\n *\r\n * - `--order-id` (required): the order to pay. The settlement path is decided\r\n * server-side by the order's billing_mode.\r\n * - `--payment-method-id` / `--payment-token-id` / `--authorized-merchant-trans-id`\r\n * (all optional): payment credentials forwarded to the pay body. Charging happens\r\n * in this step (platform create-order only locks inventory); omit to let the\r\n * platform settle by the developer default card. Token wins over method id\r\n * server-side; `--authorized-merchant-trans-id` resumes a 3DS challenge.\r\n * - `--idempotency-key` (required): forwarded as header.\r\n * - `--watch` / `--watch-interval` / `--watch-timeout`: polling mode that\r\n * retries on PAYMENT_NOT_COMPLETED until PAID or timeout.\r\n *\r\n * This is the step that actually moves money, so the non-`--yes` path MUST\r\n * confirm before the write; `--yes` skips it. A declined confirm maps to\r\n * `CLIENT_ABORTED` (exit 5). Applies to both the single-shot and `--watch`\r\n * paths (the confirm happens once, before polling begins).\r\n *\r\n * On success: exit 0, print settlement result.\r\n * On business error: exit 1, error code to stderr.\r\n * Watch mode: NDJSON output per poll iteration.\r\n */\r\nexport function registerHotelPayOrderCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('pay-order')\r\n .description('Settle an existing hotel order (path decided by billing_mode: monthly_settlement or pay_per_call)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Order ID to pay (from create-order response)')\r\n .option('--payment-method-id <id>', 'Optional bound-card id to charge (pay_per_call / EVO preauth)')\r\n .option('--payment-token-id <id>', 'Optional network-token id (unionpay/visa charge path)')\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'Resume an EVO-card 3DS challenge: merchant trans id of an already-authorised preauth',\r\n )\r\n .option(\r\n '--authenticate',\r\n 'Opt-in to require cardholder 3DS on the network-token direct charge (--payment-token-id, EVO/Mastercard). When a step-up is needed the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume with --authorized-charge-no. Default off = frictionless.',\r\n )\r\n .option(\r\n '--return-url <url>',\r\n 'Optional 3DS/passkey return URL for the network-token authenticate path (falls back to the platform EVO_3DS_RETURN_URL)',\r\n )\r\n .option(\r\n '--authorized-charge-no <no>',\r\n 'Resume a network-token 3DS challenge: charge_no returned by a prior AUTHENTICATION_REQUIRED response (settled via ChargeService.resume_token)',\r\n )\r\n .option(\r\n '--evo-explicit',\r\n '[方案 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side.',\r\n )\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n )\r\n .option('--original-amount-cents <cents>', PRICE_ANNOTATION_FLAGS['original-amount-cents'].description)\r\n .option('--discount-amount-cents <cents>', PRICE_ANNOTATION_FLAGS['discount-amount-cents'].description)\r\n .option('--watch', 'Poll until PAID or timeout (NDJSON output)', false)\r\n .option(\r\n '--watch-interval <seconds>',\r\n 'Seconds between polls when --watch is set',\r\n String(DEFAULT_PAY_WATCH_INTERVAL_SECONDS),\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n 'Max seconds to poll before giving up',\r\n String(DEFAULT_PAY_WATCH_TIMEOUT_SECONDS),\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelPayOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required: --order-id\r\n const orderId = opts.orderId as string | undefined;\r\n if (orderId === undefined) {\r\n throw new CliError('PARAM_INVALID', 'Missing required --order-id.');\r\n }\r\n\r\n // Idempotency key resolution\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'hotel-redaug pay-order',\r\n });\r\n\r\n // Watch mode params\r\n const watchEnabled = Boolean(opts.watch);\r\n const watchInterval = resolveSeconds(opts.watchInterval as string, DEFAULT_PAY_WATCH_INTERVAL_SECONDS);\r\n const watchTimeout = resolveSeconds(opts.watchTimeout as string, DEFAULT_PAY_WATCH_TIMEOUT_SECONDS);\r\n\r\n // Pay-order 携带支付凭证(扣款发生在本步骤):平台侧 create-order 只锁库存/锁价、\r\n // 分文不碰钱(lock-then-pay),扣款后移到这一步。全部可选——省略时平台按订单\r\n // billing_mode 自行分流(月结扣额度、现结选默认卡)。CLI 是薄透传层,不做必填校验。\r\n const body: Record<string, unknown> = {};\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n if (opts.authorizedMerchantTransId !== undefined) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 网络令牌支付时 3DS(opt-in):仅置位时透传 authenticate=true(平台默认 false=免摩擦);\r\n // return_url 可选(缺省平台回落 EVO_3DS_RETURN_URL);authorized_charge_no 是续付句柄。\r\n if (opts.authenticate) body.authenticate = true;\r\n if (opts.returnUrl !== undefined) body.return_url = opts.returnUrl as string;\r\n if (opts.authorizedChargeNo !== undefined) {\r\n body.authorized_charge_no = opts.authorizedChargeNo as string;\r\n }\r\n // 方案 B/R16 显式 EVO 选择信号:仅在置位时透传 evo_explicit=true;缺省则不发(平台默认 false)。\r\n if (opts.evoExplicit) body.evo_explicit = true;\r\n // 价格批注(原价 / 优惠,纯记录):落订单 auth_snapshot + 统一流水并在订单详情回显,\r\n // 不进网关报文、不参与权威价核验。\r\n applyPriceAnnotation(body, opts);\r\n\r\n // Confirm before the write unless --yes. This is the step that actually\r\n // moves money (settlement account debit for monthly_settlement, or EVO\r\n // verification for pay_per_call), decided server-side by billing_mode. The\r\n // prompt goes to stderr; declining maps to CLIENT_ABORTED (exit 5) via the\r\n // top-level envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Settle hotel order ${orderId}? This moves money via the order's configured billing mode (monthly_settlement or pay_per_call).`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Payment aborted by user.');\r\n }\r\n }\r\n\r\n const path = `/hotel/${encodeURIComponent(orderId)}/pay`;\r\n const headers = { 'Idempotency-Key': idempotencyKey };\r\n const auth = { type: 'api-key' as const, key: apiKey };\r\n\r\n if (!watchEnabled) {\r\n // Single-shot mode\r\n const spinner = format === 'json' ? null : createSpinner('Paying hotel order...');\r\n\r\n const result = await deps.apiClient.post<PayHotelOrderResponse>(\r\n path,\r\n auth,\r\n body,\r\n headers,\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<PayHotelOrderResponse> = {\r\n data,\r\n text: () => formatPayOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n } else {\r\n // Watch mode: poll until PAID or timeout, output NDJSON per iteration\r\n const deadline = Date.now() + watchTimeout * 1000;\r\n let lastRecord: unknown = null;\r\n\r\n for (;;) {\r\n const result = await deps.apiClient.post<PayHotelOrderResponse>(\r\n path,\r\n auth,\r\n body,\r\n headers,\r\n );\r\n\r\n if (result.success) {\r\n const data = result.data;\r\n lastRecord = data;\r\n ndjsonWriteLine(data);\r\n\r\n if (isPaymentTerminal(data)) {\r\n return;\r\n }\r\n } else {\r\n // Business error — check if it's PAYMENT_NOT_COMPLETED (retryable in watch)\r\n const errorCode = (result as any).code ?? (result as any).errorCode;\r\n const errorCodeStr = String(errorCode);\r\n\r\n if (errorCodeStr === 'PAYMENT_NOT_COMPLETED' || errorCodeStr === '1933') {\r\n // Retryable: output the error as NDJSON line and continue\r\n const errorLine = {\r\n watch_status: 'pending',\r\n error_code: errorCodeStr === '1933' ? 'PAYMENT_NOT_COMPLETED' : errorCodeStr,\r\n message: (result as any).errorMessage ?? 'Payment not yet completed',\r\n };\r\n lastRecord = errorLine;\r\n ndjsonWriteLine(errorLine);\r\n } else {\r\n // Non-retryable business error → exit 1\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n }\r\n\r\n // Check timeout\r\n if (Date.now() + watchInterval * 1000 >= deadline) {\r\n const timeoutLine = {\r\n watch_status: 'timeout',\r\n message: `Polling stopped after ${watchTimeout}s without reaching PAID status.`,\r\n last_status: lastRecord,\r\n };\r\n ndjsonWriteLine(timeoutLine);\r\n return;\r\n }\r\n\r\n await realSleep(watchInterval * 1000);\r\n }\r\n }\r\n });\r\n}\r\n","import type { ApiClient } from '@agenzo/cli-core';\r\nimport { CliError } from '@agenzo/cli-core';\r\nimport type { GetCheckoutResponse, GetHotelOrderResponse } from '../types/hotel.js';\r\nimport { ndjsonWriteLine, realSleep, resolveSeconds } from '../ride-elife/watch.js';\r\n\r\n/**\r\n * NDJSON status-polling for the hotel long-running reads `hotel-redaug get\r\n * --watch` (Requirement 5.4-5.6) and `hotel-redaug get-checkout --watch`\r\n * (Requirement 8.4-8.5). Merchant-domain logic — stays in the app per\r\n * requirement 15.x (NOT pushed down to cli-core), mirroring `ride-elife/watch.ts`.\r\n *\r\n * The watch stream is a line stream: each poll result is written as ONE\r\n * independent, compact JSON line on stdout. It is deliberately NOT routed\r\n * through `renderWithContext`, so the profile/endpoint envelope is never\r\n * wrapped around the stream (Requirement 11.4 — an agent consumes it with a\r\n * line reader).\r\n *\r\n * The polling engine is split from its I/O so it can be unit/PBT-tested with a\r\n * fake clock and shortened constants (Requirement 15.5): `fetchStatus`,\r\n * `writeLine`, `sleep`, `now`, `isTerminal` and `lastStatusOf` are all\r\n * injected. Unlike `ride-elife` (single verb), the hotel engine serves two\r\n * verbs with different terminal semantics, so the terminal predicate and the\r\n * \"last status\" accessor are injected seams rather than hard-coded.\r\n *\r\n * `resolveSeconds`, `realSleep` and `ndjsonWriteLine` are reused verbatim from\r\n * the ride watch module (which already exports them) and re-exported here so\r\n * the hotel verb modules can pull the whole watch surface from this single,\r\n * self-contained module.\r\n */\r\n\r\nexport { ndjsonWriteLine, realSleep, resolveSeconds };\r\n\r\n// ============================================================\r\n// Defaults (per the verb-schema `polling` blocks)\r\n// ============================================================\r\n\r\n/** `get` schema `polling.recommended_interval_seconds`. */\r\nexport const DEFAULT_ORDER_WATCH_INTERVAL_SECONDS = 5;\r\n/** `get-checkout` schema `polling.recommended_interval_seconds`. */\r\nexport const DEFAULT_CHECKOUT_WATCH_INTERVAL_SECONDS = 10;\r\n/** Safety cap so `--watch` can never poll forever (shared by both verbs). */\r\nexport const DEFAULT_WATCH_TIMEOUT_SECONDS = 600;\r\n\r\n// ============================================================\r\n// Terminal predicates + constants — order status (`get`)\r\n// ============================================================\r\n\r\n/**\r\n * Terminal `order_status_code` set (schema `polling.terminal_statuses`). Once\r\n * the order reaches one of these, `--watch` stops polling. 3 = Confirmed,\r\n * 4 = Cancelled, 5 = Completed.\r\n */\r\nexport const HOTEL_TERMINAL_ORDER_CODES: ReadonlySet<number> = new Set([3, 4, 5]);\r\n/** In-progress `order_status_code` set (schema `polling.in_progress_statuses`). 2 = Processing. */\r\nexport const HOTEL_IN_PROGRESS_ORDER_CODES: ReadonlySet<number> = new Set([2]);\r\n/**\r\n * Terminal `order_status` STRING set — the local-cache fallback path omits\r\n * `order_status_code`, so the string is the robust signal there. CASE-SENSITIVE.\r\n */\r\nexport const HOTEL_TERMINAL_ORDER_STATUS: ReadonlySet<string> = new Set([\r\n 'CONFIRMED',\r\n 'CANCELLED',\r\n 'COMPLETED',\r\n]);\r\n\r\n/** Read the integer `order_status_code` off a poll result (provider path only). */\r\nexport function orderStatusCodeOf(record: unknown): number | undefined {\r\n const code = (record as { order_status_code?: unknown }).order_status_code;\r\n return typeof code === 'number' ? code : undefined;\r\n}\r\n\r\n/** Read the std `order_status` STRING off a poll result. */\r\nexport function orderStatusOf(record: unknown): string | undefined {\r\n const status = (record as { order_status?: unknown }).order_status;\r\n return typeof status === 'string' ? status : undefined;\r\n}\r\n\r\n/**\r\n * Pure terminal-state predicate for `get` (exported for direct unit/PBT\r\n * testing). True when `order_status_code ∈ {3,4,5}` OR `order_status ∈\r\n * {CONFIRMED, CANCELLED, COMPLETED}` — robust across the provider path (carries\r\n * both the int and the string) and the local-cache fallback (string only). A\r\n * missing/unknown status is never terminal, so polling continues until a known\r\n * terminal status or the timeout.\r\n */\r\nexport function isTerminalOrderStatus(record: unknown): boolean {\r\n const code = orderStatusCodeOf(record);\r\n if (code !== undefined && HOTEL_TERMINAL_ORDER_CODES.has(code)) {\r\n return true;\r\n }\r\n const status = orderStatusOf(record);\r\n return status !== undefined && HOTEL_TERMINAL_ORDER_STATUS.has(status);\r\n}\r\n\r\n/**\r\n * Most recent order status for the timeout line: the human-readable\r\n * `order_status` string when present, else the integer `order_status_code`,\r\n * else null.\r\n */\r\nexport function lastOrderStatusOf(record: unknown): string | number | null {\r\n return orderStatusOf(record) ?? orderStatusCodeOf(record) ?? null;\r\n}\r\n\r\n// ============================================================\r\n// Terminal predicates + constants — refund status (`get-checkout`)\r\n// ============================================================\r\n\r\n/** Terminal `refund_status` set (schema `polling.terminal_statuses`). */\r\nexport const CHECKOUT_TERMINAL_REFUND: ReadonlySet<string> = new Set([\r\n 'approved',\r\n 'rejected',\r\n 'refunded',\r\n]);\r\n/** In-progress `refund_status` set (schema `polling.in_progress_statuses`). */\r\nexport const CHECKOUT_IN_PROGRESS_REFUND: ReadonlySet<string> = new Set(['pending']);\r\n\r\n/** Read the `refund_status` STRING off a check-out poll result. */\r\nexport function refundStatusOf(record: unknown): string | undefined {\r\n const status = (record as { refund_status?: unknown }).refund_status;\r\n return typeof status === 'string' ? status : undefined;\r\n}\r\n\r\n/**\r\n * Pure terminal-state predicate for `get-checkout` (exported for direct\r\n * unit/PBT testing). True when `refund_status ∈ {approved, rejected,\r\n * refunded}`. A missing/unknown status is never terminal.\r\n */\r\nexport function isTerminalRefundStatus(record: unknown): boolean {\r\n const status = refundStatusOf(record);\r\n return status !== undefined && CHECKOUT_TERMINAL_REFUND.has(status);\r\n}\r\n\r\n/** Most recent refund status for the timeout line, or null when absent. */\r\nexport function lastRefundStatusOf(record: unknown): string | number | null {\r\n return refundStatusOf(record) ?? null;\r\n}\r\n\r\n// ============================================================\r\n// Engine (pure, fully injected)\r\n// ============================================================\r\n\r\n/** The final NDJSON line emitted when polling gives up before a terminal status. */\r\nexport interface HotelWatchTimeoutLine {\r\n watch_status: 'timeout';\r\n message: string;\r\n last_status: string | number | null;\r\n}\r\n\r\n/** I/O + clock + predicate seams the polling engine depends on (all injectable for tests). */\r\nexport interface HotelWatchDeps {\r\n /** Fetch one status snapshot (throws to abort the whole stream). */\r\n fetchStatus: () => Promise<unknown>;\r\n /** Write one NDJSON record as a single compact line. */\r\n writeLine: (record: unknown) => void;\r\n /** Resolve after `ms` (real timer in prod; fake clock in tests). */\r\n sleep: (ms: number) => Promise<void>;\r\n /** Current epoch millis (real `Date.now` in prod; fake clock in tests). */\r\n now: () => number;\r\n /** Verb-specific terminal-state predicate. */\r\n isTerminal: (record: unknown) => boolean;\r\n /** Verb-specific accessor for the timeout line's `last_status`. */\r\n lastStatusOf: (record: unknown) => string | number | null;\r\n}\r\n\r\n/** Interval / timeout budget for one watch run, in milliseconds. */\r\nexport interface HotelWatchOptions {\r\n intervalMs: number;\r\n timeoutMs: number;\r\n}\r\n\r\n/**\r\n * Poll `fetchStatus`, writing each result as an NDJSON line, until the record\r\n * reaches a terminal status (per the injected `isTerminal`) or the timeout\r\n * elapses. On timeout the FINAL line is `{ watch_status: 'timeout', ... }`\r\n * (Requirements 5.5 / 8.5).\r\n *\r\n * Termination: every iteration either returns (terminal status) or, when the\r\n * next poll would land at/after the deadline, emits the timeout line and\r\n * returns. With a monotonically advancing clock (real time, or a fake clock\r\n * advanced by `sleep`) the deadline is always reached, so the loop is\r\n * guaranteed to terminate for any status sequence. Loop shape is identical to\r\n * `ride-elife`'s `runWatch`.\r\n */\r\nexport async function runHotelWatch(\r\n deps: HotelWatchDeps,\r\n opts: HotelWatchOptions,\r\n): Promise<void> {\r\n const deadline = deps.now() + opts.timeoutMs;\r\n for (;;) {\r\n const record = await deps.fetchStatus();\r\n deps.writeLine(record);\r\n\r\n if (deps.isTerminal(record)) {\r\n return;\r\n }\r\n\r\n if (deps.now() + opts.intervalMs >= deadline) {\r\n const timeoutLine: HotelWatchTimeoutLine = {\r\n watch_status: 'timeout',\r\n message: `Polling stopped after ${opts.timeoutMs / 1000}s without reaching a terminal status.`,\r\n last_status: deps.lastStatusOf(record),\r\n };\r\n deps.writeLine(timeoutLine);\r\n return;\r\n }\r\n\r\n await deps.sleep(opts.intervalMs);\r\n }\r\n}\r\n\r\n// ============================================================\r\n// Production wirings (live endpoints, real timers, system clock)\r\n// ============================================================\r\n\r\n/**\r\n * Production wiring for `hotel-redaug get --watch`: bind the polling engine to\r\n * a live `ApiClient` (order-status endpoint + api-key auth), the compact NDJSON\r\n * stdout writer, real timers and the system clock. A network/backend failure on\r\n * any poll surfaces as a `CliError` to the top-level handler, exactly like the\r\n * single-shot path. The order is terminal at `order_status_code ∈ {3,4,5}`\r\n * (or `order_status ∈ {CONFIRMED, CANCELLED, COMPLETED}`).\r\n */\r\nexport async function watchOrderStatus(\r\n apiClient: ApiClient,\r\n apiKey: string,\r\n orderId: string,\r\n opts: { intervalSeconds: number; timeoutSeconds: number },\r\n): Promise<void> {\r\n const path = `/hotel/${encodeURIComponent(orderId)}/status`;\r\n await runHotelWatch(\r\n {\r\n fetchStatus: async () => {\r\n const result = await apiClient.get<GetHotelOrderResponse>(path, {\r\n type: 'api-key',\r\n key: apiKey,\r\n });\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n return result.data;\r\n },\r\n writeLine: ndjsonWriteLine,\r\n sleep: realSleep,\r\n now: () => Date.now(),\r\n isTerminal: isTerminalOrderStatus,\r\n lastStatusOf: lastOrderStatusOf,\r\n },\r\n {\r\n intervalMs: opts.intervalSeconds * 1000,\r\n timeoutMs: opts.timeoutSeconds * 1000,\r\n },\r\n );\r\n}\r\n\r\n/**\r\n * Production wiring for `hotel-redaug get-checkout --watch`: bind the polling\r\n * engine to a live `ApiClient` (checkout-status endpoint + api-key auth), the\r\n * compact NDJSON stdout writer, real timers and the system clock. A poll\r\n * failure surfaces as a `CliError` to the top-level handler. The refund is\r\n * terminal at `refund_status ∈ {approved, rejected, refunded}`.\r\n */\r\nexport async function watchCheckoutStatus(\r\n apiClient: ApiClient,\r\n apiKey: string,\r\n taskOrderCode: string,\r\n opts: { intervalSeconds: number; timeoutSeconds: number },\r\n): Promise<void> {\r\n const path = `/hotel/checkout/${encodeURIComponent(taskOrderCode)}`;\r\n await runHotelWatch(\r\n {\r\n fetchStatus: async () => {\r\n const result = await apiClient.get<GetCheckoutResponse>(path, {\r\n type: 'api-key',\r\n key: apiKey,\r\n });\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n return result.data;\r\n },\r\n writeLine: ndjsonWriteLine,\r\n sleep: realSleep,\r\n now: () => Date.now(),\r\n isTerminal: isTerminalRefundStatus,\r\n lastStatusOf: lastRefundStatusOf,\r\n },\r\n {\r\n intervalMs: opts.intervalSeconds * 1000,\r\n timeoutMs: opts.timeoutSeconds * 1000,\r\n },\r\n );\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { GetHotelOrderResponse } from '../types/hotel.js';\r\nimport {\r\n DEFAULT_ORDER_WATCH_INTERVAL_SECONDS,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n resolveSeconds,\r\n watchOrderStatus,\r\n} from './watch.js';\r\nimport { attachSchemaHelp, hotelGetSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/get.ts and the sibling\r\n// hotel-redaug/quote.ts and search.ts each define their own need) rather than\r\n// pulled from a shared helpers file. `get` is read-only — no idempotency key.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 5.2 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary, non-watch path only)\r\n// ============================================================\r\n\r\n/**\r\n * Render a single hotel order as a key/value block for `--format table`.\r\n * `order_status` is the std STRING (PROCESSING|CONFIRMED|CANCELLED|COMPLETED|\r\n * INIT); `order_status_code` is the integer mirror (2/3/4/5) shown only when\r\n * present (the provider path carries it; the local-cache fallback omits it).\r\n * `hotel_confirm_no` is populated once the order reaches CONFIRMED (3) and is\r\n * null while PROCESSING (2). `total_amount` is a DECIMAL currency unit (NOT\r\n * cents), always paired with `currency` (sourced from the local record on\r\n * both the provider and local-cache paths) so an amount is never shown\r\n * without its unit. `rooms` / `settlement_path` / `created_at` / `updated_at`\r\n * plus the booking-detail fields (guest / contact / rooms booked / arrive\r\n * time / special requests) surface the order detail persisted at create-order\r\n * time — modeled on what a booking-confirmation view shows, not the raw\r\n * create-order inputs (occupancy counts / nationality are excluded).\r\n */\r\nfunction formatGetOrder(data: GetHotelOrderResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['FC Order Code', String(data.fc_order_code ?? '-')],\r\n ['Status', String(data.order_status ?? '-')],\r\n ];\r\n if (data.order_status_code !== undefined) {\r\n lines.push(['Status code', String(data.order_status_code)]);\r\n }\r\n if (data.hotel_confirm_no !== undefined && data.hotel_confirm_no !== null) {\r\n lines.push(['Hotel confirm no', String(data.hotel_confirm_no)]);\r\n }\r\n if (data.hotel_name) lines.push(['Hotel', String(data.hotel_name)]);\r\n if (data.room_name) lines.push(['Room', String(data.room_name)]);\r\n if (data.check_in) lines.push(['Check-in', String(data.check_in)]);\r\n if (data.check_out) lines.push(['Check-out', String(data.check_out)]);\r\n if (data.total_amount !== undefined && data.total_amount !== null) {\r\n const currency = data.currency ? ` ${data.currency}` : '';\r\n lines.push(['Total amount', `${String(data.total_amount)}${currency}`]);\r\n }\r\n if (data.settlement_path) lines.push(['Settlement path', String(data.settlement_path)]);\r\n if (data.rooms && data.rooms.length > 0) {\r\n lines.push([\r\n 'Rooms',\r\n data.rooms.map((r) => `${r.room_index}:${r.guest_name}`).join(', '),\r\n ]);\r\n }\r\n if (data.room_num !== undefined && data.room_num !== null) {\r\n lines.push(['Rooms booked', String(data.room_num)]);\r\n }\r\n if (data.guest?.name) lines.push(['Guest', String(data.guest.name)]);\r\n if (data.contact?.name) {\r\n const phone = data.contact.phone\r\n ? ` (+${data.contact.country_code ?? ''} ${data.contact.phone})`\r\n : '';\r\n lines.push(['Contact', `${data.contact.name}${phone}`]);\r\n }\r\n if (data.arrive_time) lines.push(['Arrive time', String(data.arrive_time)]);\r\n if (data.special_requests) lines.push(['Special requests', String(data.special_requests)]);\r\n if (data.channel_state) lines.push(['Channel state', String(data.channel_state)]);\r\n if (data.created_at) lines.push(['Created at', String(data.created_at)]);\r\n if (data.updated_at) lines.push(['Updated at', String(data.updated_at)]);\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug get` — query a hotel order status by id (§ get schema).\r\n * Read-only (no idempotency key); path built from `--order-id` ONLY (the\r\n * platform status endpoint `/hotel/{order_id}/status` consumes no supplier\r\n * reference, so `--fc-order-code` is intentionally not accepted here).\r\n *\r\n * Two modes (branching mirrors `ride-elife/get.ts`):\r\n * - Non-`--watch`: a single `GET /hotel/<order_id>/status` → `CommandResult` +\r\n * `renderWithContext` (json carries the profile/endpoint envelope). Renders\r\n * `order_status` (string), `order_status_code` (int, when present),\r\n * `hotel_confirm_no`, and the other key fields.\r\n * - `--watch`: hands off to `watchOrderStatus` (watch.ts), which polls until a\r\n * terminal status (`order_status_code ∈ {3,4,5}` or `order_status ∈\r\n * {CONFIRMED, CANCELLED, COMPLETED}`) or timeout, writing each result as ONE\r\n * NDJSON line on stdout. The watch stream is NOT wrapped in the\r\n * profile/endpoint envelope (it is a line stream); on timeout the final line\r\n * is `{ watch_status: 'timeout', ... }`.\r\n *\r\n * Required-flag validation (`--order-id`) throws `PARAM_INVALID` BEFORE any\r\n * request. Named `registerHotelGetCommand` to avoid clashing with the\r\n * `ride-elife` `registerRideGetCommand` when both are imported into `index.ts`.\r\n */\r\nexport function registerHotelGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('get')\r\n .description('Retrieve a hotel order status by id (repeatable for polling)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Our order reference (coOrderCode) returned by `hotel-redaug create-order`')\r\n .option('--watch', 'Poll until a terminal status, emitting one NDJSON line per update')\r\n .option(\r\n '--watch-interval <seconds>',\r\n `Seconds between polls when --watch is set (default ${DEFAULT_ORDER_WATCH_INTERVAL_SECONDS})`,\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n `Max seconds to poll before giving up (default ${DEFAULT_WATCH_TIMEOUT_SECONDS})`,\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelGetSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n // Required-flag validation BEFORE any request → PARAM_INVALID. The path is\r\n // built from --order-id ONLY (no --fc-order-code).\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n\r\n // --watch: NDJSON line stream (no profile/endpoint envelope). The stream\r\n // itself is the progress, so no spinner/notify is emitted.\r\n if (opts.watch) {\r\n await watchOrderStatus(deps.apiClient, apiKey, orderId, {\r\n intervalSeconds: resolveSeconds(\r\n opts.watchInterval as string | undefined,\r\n DEFAULT_ORDER_WATCH_INTERVAL_SECONDS,\r\n ),\r\n timeoutSeconds: resolveSeconds(\r\n opts.watchTimeout as string | undefined,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n ),\r\n });\r\n return;\r\n }\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching hotel order status...');\r\n\r\n const result = await deps.apiClient.get<GetHotelOrderResponse>(\r\n `/hotel/${encodeURIComponent(orderId)}/status`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<GetHotelOrderResponse> = {\r\n data,\r\n text: () => formatGetOrder(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { CancelHotelResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelCancelSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/cancel.ts and the sibling\r\n// hotel-redaug/book.ts each define their own need) rather than pulled from a\r\n// shared helpers file.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 6.3 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render a cancellation result as a key/value block for `--format table`.\r\n *\r\n * The platform returns one of TWO shapes (modeled on\r\n * `order_mapping.format_cancel` / `format_cancel_pending`), and this formatter\r\n * handles BOTH:\r\n * - CONFIRMED shape — a `cancellation` breakdown (`cancellation_fee`,\r\n * `reversal_amount`, `currency`) and/or a flat `cancellation_fee`, plus a\r\n * `refund_amount`.\r\n * - ACCEPTED-BUT-PENDING shape — `cancel_status` is `'cancel_pending'` with an\r\n * upstream `cancel_result` acknowledgement (no fee/refund settled yet).\r\n *\r\n * Amounts are decimal currency units (NOT cents) — printed verbatim. A closing\r\n * info line conveys the acceptance-is-not-proof contract (requirement 6.5): a\r\n * successful response is acceptance only, so the Agent MUST poll `get` until\r\n * `order_status=CANCELLED` (code 4) to confirm the cancellation actually took\r\n * effect.\r\n */\r\nfunction formatCancel(data: CancelHotelResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['Order status', String(data.order_status ?? '-')],\r\n ];\r\n\r\n // Accepted-but-pending shape: surface the pending marker so the operator sees\r\n // the cancellation was only accepted, not yet observed as CANCELLED.\r\n if (data.cancel_status !== undefined) {\r\n lines.push(['Cancel status', String(data.cancel_status)]);\r\n }\r\n\r\n // Confirmed shape: prefer the structured `cancellation` breakdown, falling\r\n // back to the flat `cancellation_fee` when only that is present.\r\n if (data.cancellation) {\r\n const c = data.cancellation;\r\n const cur = c.currency ? ` ${c.currency}` : '';\r\n if (c.cancellation_fee !== undefined) {\r\n lines.push(['Cancellation fee', `${c.cancellation_fee}${cur}`]);\r\n }\r\n if (c.reversal_amount !== undefined) {\r\n lines.push(['Reversal amount', `${c.reversal_amount}${cur}`]);\r\n }\r\n } else if (data.cancellation_fee !== undefined && data.cancellation_fee !== null) {\r\n lines.push(['Cancellation fee', String(data.cancellation_fee)]);\r\n }\r\n\r\n if (data.refund_amount !== undefined && data.refund_amount !== null) {\r\n lines.push(['Refund amount', String(data.refund_amount)]);\r\n }\r\n\r\n const out: string[] = [Formatter.keyValue(lines)];\r\n\r\n out.push(\r\n '',\r\n Formatter.status(\r\n 'info',\r\n `A successful response is acceptance only, NOT proof of cancellation — poll 'hotel-redaug get --order-id ${data.order_id ?? '<order_id>'}' until order_status=CANCELLED (code 4) to confirm.`,\r\n ),\r\n );\r\n\r\n return out.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug cancel` — cancel an entire hotel order within its cancellation\r\n * policy (§ cancel schema). Write op (W/Y) — a cancellation fee may apply.\r\n *\r\n * `POST /hotel/<order-id>/cancel` with `X-Api-Key` auth, the resolved\r\n * `Idempotency-Key` header (key forwarded verbatim, never in the body), and a\r\n * snake_case body carrying `fc_order_code` (and `reason` when supplied).\r\n * Required-flag validation (`--order-id`, `--fc-order-code`) raises\r\n * `PARAM_INVALID` before any request is sent. There is NO interactive cancel\r\n * confirmation prompt (it was removed so the command never blocks on stdin);\r\n * cancel proceeds directly. A missing `--idempotency-key` under `--yes` throws\r\n * `PARAM_IDEMPOTENCY_KEY_REQUIRED` before any request, otherwise it is prompted.\r\n *\r\n * Renders `CancelHotelResponse` (both the confirmed and the accepted-but-pending\r\n * shapes) via `renderWithContext` (json carries the profile/endpoint envelope);\r\n * the progress spinner goes to stderr and stays silent in json mode. A\r\n * successful response is ACCEPTANCE ONLY — the Agent must poll `get` until\r\n * `order_status=CANCELLED` (code 4) to confirm (requirement 6.5).\r\n */\r\nexport function registerHotelCancelCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('cancel')\r\n .description('Cancel a whole hotel order within its policy (a cancellation fee may apply)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Our order reference (coOrderCode) to cancel (book.response.order_id)')\r\n .option('--fc-order-code <code>', 'Supplier order reference (book.response.fc_order_code)')\r\n .option('--reason <text>', 'Cancellation reason')\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelCancelSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required input throws PARAM_INVALID before any request is sent (mirrors\r\n // the sibling book/get commands). snake_case keys match the platform\r\n // contract; --order-id is the URL path, --fc-order-code rides in the body.\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n const fcOrderCode = need(opts.fcOrderCode as string | undefined, 'fc-order-code');\r\n\r\n const body: Record<string, unknown> = { fc_order_code: fcOrderCode };\r\n // Optional reason — included only when supplied (an omitted key never\r\n // enters the body). --idempotency-key is NEVER in the body.\r\n if (opts.reason !== undefined) body.reason = opts.reason as string;\r\n\r\n // No interactive cancel confirmation — cancel proceeds directly (the extra\r\n // \"A cancellation fee may apply\" y/N prompt was removed so the command never\r\n // blocks on stdin in non-interactive/automation contexts).\r\n\r\n // Idempotency key (requirement 13.1-13.6): resolved before the request via\r\n // the reused merchant-cli policy. Under --yes a missing key is a hard error\r\n // and no request is sent. The key is sent as a header, never in the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'hotel-redaug cancel',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Cancelling hotel order...');\r\n\r\n const result = await deps.apiClient.post<CancelHotelResponse>(\r\n `/hotel/${encodeURIComponent(orderId)}/cancel`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CancelHotelResponse> = {\r\n data,\r\n text: () => formatCancel(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { CheckoutHotelResponse, CheckoutRoom } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelCheckoutSchema } from '../verb-schema.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/cancel.ts and the sibling\r\n// hotel-redaug/book.ts and cancel.ts each define their own need/num) rather\r\n// than pulled from a shared helpers file.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 7.3 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. Used for\r\n * `--refund-type` (an upstream refund-handling code; default 1).\r\n */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Structured-flag parser (pure builder — directly property-testable)\r\n// ============================================================\r\n\r\n/**\r\n * Parse and shape-validate `--checkout-rooms` (requirement 7.4, design Property 3).\r\n *\r\n * The raw flag MUST be a JSON array in which every element carries `room_index`\r\n * (string), `guest_name` (string), and `cancel_check_in_date` (string). Any\r\n * deviation — non-JSON, a non-array, or any element missing/mistyping a required\r\n * field — raises `PARAM_INVALID` before any request is issued.\r\n *\r\n * `room_index` and `guest_name` come VERBATIM from the `book` response\r\n * `rooms[]`; `cancel_check_in_date` is the check-in date of the night(s) being\r\n * dropped. The parsed array is returned VERBATIM (the actual parsed objects,\r\n * extra keys untouched) and forwarded as-is in the request body.\r\n *\r\n * Exported so the task-6 property suite can import and exercise it directly.\r\n */\r\nexport function parseCheckoutRooms(raw: string): CheckoutRoom[] {\r\n const INVALID =\r\n '--checkout-rooms must be a JSON array of {room_index (string), guest_name (string), cancel_check_in_date (string)}.';\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n\r\n for (const el of parsed) {\r\n if (typeof el !== 'object' || el === null || Array.isArray(el)) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n const room = el as Record<string, unknown>;\r\n if (\r\n typeof room.room_index !== 'string' ||\r\n typeof room.guest_name !== 'string' ||\r\n typeof room.cancel_check_in_date !== 'string'\r\n ) {\r\n throw new CliError('PARAM_INVALID', INVALID);\r\n }\r\n }\r\n\r\n // Forwarded verbatim — the parsed objects are returned unchanged.\r\n return parsed as CheckoutRoom[];\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render a check-out application result as a key/value block for\r\n * `--format table`. The synchronous response is an ACCEPTANCE only: it returns a\r\n * `task_order_code` while the supplier decides asynchronously. A closing info\r\n * line conveys the async contract (requirement 7.6): poll `get-checkout` with\r\n * the `task_order_code` until a terminal refund status.\r\n */\r\nfunction formatCheckout(data: CheckoutHotelResponse): string {\r\n const lines: [string, string][] = [\r\n ['Order ID', String(data.order_id ?? '-')],\r\n ['Task order code', String(data.task_order_code ?? '-')],\r\n ];\r\n if (data.apply_status !== undefined && data.apply_status !== null) {\r\n lines.push(['Apply status', String(data.apply_status)]);\r\n }\r\n if (data.checkout_status !== undefined) {\r\n lines.push(['Checkout status', String(data.checkout_status)]);\r\n }\r\n\r\n const out: string[] = [Formatter.keyValue(lines)];\r\n\r\n out.push(\r\n '',\r\n Formatter.status(\r\n 'info',\r\n `Check-out is ASYNC — this response is acceptance only, NOT proof of refund. Poll 'hotel-redaug get-checkout --task-order-code ${data.task_order_code ?? '<task_order_code>'}' until refund_status is approved/rejected/refunded.`,\r\n ),\r\n );\r\n\r\n return out.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug checkout` — request a partial check-out or an out-of-policy\r\n * cancellation (§ checkout schema). Write op (W/Y) — an APPLICATION the property\r\n * must approve; charges/refund are decided asynchronously.\r\n *\r\n * `POST /hotel/<order-id>/checkout` with `X-Api-Key` auth, the resolved\r\n * `Idempotency-Key` header (key forwarded verbatim, never in the body), and a\r\n * snake_case body `{ fc_order_code, reason, refund_type, checkout_rooms }`.\r\n * `--order-id` is the URL path; `--fc-order-code` rides in the body. All flag\r\n * validation — required fields (`--order-id`, `--fc-order-code`, `--reason`,\r\n * `--checkout-rooms`), the `--checkout-rooms` JSON shape, and numeric\r\n * `--refund-type` — raises `PARAM_INVALID` before any request is sent. `--yes`\r\n * skips the confirm; a declined confirm maps to `CLIENT_ABORTED` (exit 5); a\r\n * missing `--idempotency-key` under `--yes` throws\r\n * `PARAM_IDEMPOTENCY_KEY_REQUIRED` before any request, otherwise it is prompted.\r\n *\r\n * Renders `CheckoutHotelResponse` via `renderWithContext` (json carries the\r\n * profile/endpoint envelope); the progress spinner goes to stderr and stays\r\n * silent in json mode. The synchronous response is ACCEPTANCE ONLY — the Agent\r\n * must poll `get-checkout` until a terminal refund status (requirement 7.6).\r\n * Named `registerHotelCheckoutCommand` to avoid clashing with the `ride-elife`\r\n * registrars when both are imported into `index.ts`.\r\n */\r\nexport function registerHotelCheckoutCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('checkout')\r\n .description('Request a partial check-out or an out-of-policy cancellation (async; the property must approve)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-id <id>', 'Our order reference (coOrderCode) for the URL path (book.response.order_id)')\r\n .option('--fc-order-code <code>', 'Supplier order reference of the booking to change (book.response.fc_order_code)')\r\n .option('--reason <text>', 'Why the partial check-out / out-of-policy cancellation is requested')\r\n .option(\r\n '--checkout-rooms <json>',\r\n 'Rooms to check out of as a JSON array of {room_index, guest_name, cancel_check_in_date} (room_index/guest_name copied verbatim from book.response.rooms[])',\r\n )\r\n .option('--refund-type <type>', 'Requested refund handling (upstream refund-type code)', '1')\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelCheckoutSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Required + typed validation — ALL before any request → PARAM_INVALID.\r\n // snake_case keys match the platform contract. --order-id is the URL path;\r\n // --fc-order-code rides in the body.\r\n const orderId = need(opts.orderId as string | undefined, 'order-id');\r\n const fcOrderCode = need(opts.fcOrderCode as string | undefined, 'fc-order-code');\r\n const reason = need(opts.reason as string | undefined, 'reason');\r\n const checkoutRooms = parseCheckoutRooms(need(opts.checkoutRooms as string | undefined, 'checkout-rooms'));\r\n const refundType = num(opts.refundType as string | undefined, 'refund-type');\r\n\r\n const body: Record<string, unknown> = {\r\n fc_order_code: fcOrderCode,\r\n reason,\r\n refund_type: refundType,\r\n checkout_rooms: checkoutRooms,\r\n };\r\n\r\n // Confirm before the write unless --yes. A check-out application may incur\r\n // charges and must be approved by the property, so the prompt makes that\r\n // explicit. The prompt goes to stderr; declining maps to CLIENT_ABORTED\r\n // (exit 5) via the top-level envelope.\r\n if (!isYes) {\r\n const confirmed = await confirm({\r\n message: `Request check-out / out-of-policy cancellation for order ${orderId} (${checkoutRooms.length} room(s))? The property must approve and charges may apply.`,\r\n default: false,\r\n });\r\n if (!confirmed) {\r\n throw new CliError('CLIENT_ABORTED', 'Check-out application aborted by user.');\r\n }\r\n }\r\n\r\n // Idempotency key (requirement 13.1-13.6): resolved before the request via\r\n // the reused merchant-cli policy. Under --yes a missing key is a hard error\r\n // and no request is sent. The key is sent as a header, never in the body.\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'hotel-redaug checkout',\r\n });\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Submitting check-out application...');\r\n\r\n const result = await deps.apiClient.post<CheckoutHotelResponse>(\r\n `/hotel/${encodeURIComponent(orderId)}/checkout`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<CheckoutHotelResponse> = {\r\n data,\r\n text: () => formatCheckout(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { GetCheckoutResponse } from '../types/hotel.js';\r\nimport {\r\n DEFAULT_CHECKOUT_WATCH_INTERVAL_SECONDS,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n resolveSeconds,\r\n watchCheckoutStatus,\r\n} from './watch.js';\r\nimport { attachSchemaHelp, hotelGetCheckoutSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/get.ts and the sibling\r\n// hotel-redaug/get.ts and quote.ts each define their own need) rather than\r\n// pulled from a shared helpers file. `get-checkout` is read-only — no\r\n// idempotency key.\r\n\r\n/**\r\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\r\n * (requirement 8.2 / design §4.4) — a catalog code (exit 1), mirroring the\r\n * `ride-elife` convention; `PARAM_REQUIRED` is intentionally not used (it is\r\n * not in the cli-core error catalog).\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary, non-watch path only)\r\n// ============================================================\r\n\r\n/**\r\n * Render a single check-out application as a key/value block for\r\n * `--format table`. `refund_status` is the application/refund status string\r\n * (pending | approved | rejected | refunded); `refund` is the final refund\r\n * (amount + currency), populated only once `refund_status` is approved or\r\n * refunded. `refund.amount` is a DECIMAL currency unit (NOT cents) — printed\r\n * verbatim.\r\n */\r\nfunction formatGetCheckout(data: GetCheckoutResponse): string {\r\n const lines: [string, string][] = [\r\n ['Task order code', String(data.task_order_code ?? '-')],\r\n ['Refund status', String(data.refund_status ?? '-')],\r\n ];\r\n if (data.refund !== undefined && data.refund !== null) {\r\n lines.push(['Refund amount', String(data.refund.amount)]);\r\n lines.push(['Refund currency', String(data.refund.currency)]);\r\n }\r\n\r\n return Formatter.keyValue(lines);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug get-checkout` — poll a check-out application by task order code\r\n * (§ get-checkout schema). Read-only (no idempotency key); path built from\r\n * `--task-order-code` only.\r\n *\r\n * Two modes (branching mirrors `hotel-redaug/get.ts`):\r\n * - Non-`--watch`: a single `GET /hotel/checkout/<task_order_code>` →\r\n * `CommandResult` + `renderWithContext` (json carries the profile/endpoint\r\n * envelope). Renders `task_order_code`, `refund_status`, and `refund`\r\n * (amount + currency, decimal units).\r\n * - `--watch`: hands off to `watchCheckoutStatus` (watch.ts), which polls\r\n * until a terminal refund status (`refund_status ∈ {approved, rejected,\r\n * refunded}`) or timeout, writing each result as ONE NDJSON line on stdout.\r\n * The watch stream is NOT wrapped in the profile/endpoint envelope (it is a\r\n * line stream); on timeout the final line is `{ watch_status: 'timeout',\r\n * ... }`.\r\n *\r\n * Required-flag validation (`--task-order-code`) throws `PARAM_INVALID` BEFORE\r\n * any request. Named `registerHotelGetCheckoutCommand` to avoid clashing with\r\n * the `ride-elife` registrars when both are imported into `index.ts`.\r\n */\r\nexport function registerHotelGetCheckoutCommand(\r\n parent: Command,\r\n deps: { apiClient: ApiClient },\r\n): void {\r\n const cmd = parent\r\n .command('get-checkout')\r\n .description('Retrieve a check-out application status and refund outcome (repeatable for polling)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option(\r\n '--task-order-code <code>',\r\n 'Check-out application id returned by `hotel-redaug checkout`',\r\n )\r\n .option('--watch', 'Poll until a terminal status, emitting one NDJSON line per update')\r\n .option(\r\n '--watch-interval <seconds>',\r\n `Seconds between polls when --watch is set (default ${DEFAULT_CHECKOUT_WATCH_INTERVAL_SECONDS})`,\r\n )\r\n .option(\r\n '--watch-timeout <seconds>',\r\n `Max seconds to poll before giving up (default ${DEFAULT_WATCH_TIMEOUT_SECONDS})`,\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelGetCheckoutSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n // Required-flag validation BEFORE any request → PARAM_INVALID. The path is\r\n // built from --task-order-code only.\r\n const taskOrderCode = need(opts.taskOrderCode as string | undefined, 'task-order-code');\r\n\r\n // --watch: NDJSON line stream (no profile/endpoint envelope). The stream\r\n // itself is the progress, so no spinner/notify is emitted.\r\n if (opts.watch) {\r\n await watchCheckoutStatus(deps.apiClient, apiKey, taskOrderCode, {\r\n intervalSeconds: resolveSeconds(\r\n opts.watchInterval as string | undefined,\r\n DEFAULT_CHECKOUT_WATCH_INTERVAL_SECONDS,\r\n ),\r\n timeoutSeconds: resolveSeconds(\r\n opts.watchTimeout as string | undefined,\r\n DEFAULT_WATCH_TIMEOUT_SECONDS,\r\n ),\r\n });\r\n return;\r\n }\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner =\r\n format === 'json' ? null : createSpinner('Fetching check-out application status...');\r\n\r\n const result = await deps.apiClient.get<GetCheckoutResponse>(\r\n `/hotel/checkout/${encodeURIComponent(taskOrderCode)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<GetCheckoutResponse> = {\r\n data,\r\n text: () => formatGetCheckout(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n createSpinner,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { ListHotelOrdersResponse, HotelOrderListItem } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelListOrdersSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\n\r\n// ============================================================\r\n// Input helpers (hotel-domain — query assembly stays in app per req 15.3)\r\n// ============================================================\r\n//\r\n// Defined locally (mirroring how ride-elife/list-orders.ts and the sibling\r\n// hotel-redaug verbs each define their own helpers) rather than pulled from a\r\n// shared helpers file. `list-orders` is read-only — no idempotency key.\r\n\r\nconst DEFAULT_PAGE = '1';\r\nconst DEFAULT_PAGE_SIZE = '20';\r\n\r\n/**\r\n * Number-ify a pagination flag. Non-finite / non-integer / non-positive input\r\n * maps to `PARAM_INVALID` (catalog code, exit 1) BEFORE any request is sent\r\n * (requirement 9.3) — mirroring the `ride-elife/list-orders.ts` convention.\r\n * Returns the canonical string form to be passed through as a query parameter.\r\n */\r\nfunction positiveInt(value: string, flag: string): string {\r\n const n = Number(value);\r\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\r\n }\r\n return String(n);\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table summary)\r\n// ============================================================\r\n\r\n/**\r\n * Render the hotel order list as a table for `--format table`. Each order is\r\n * one row; the price column pairs `price_amount` with `price_currency` as a\r\n * DECIMAL currency amount (NOT cents) — printed verbatim. An empty `orders`\r\n * list is a successful result, so it renders an info line (never an error).\r\n */\r\nfunction formatOrders(data: ListHotelOrdersResponse): string {\r\n const orders: HotelOrderListItem[] = data.orders ?? [];\r\n if (orders.length === 0) {\r\n return Formatter.status('info', 'No hotel orders found');\r\n }\r\n\r\n const headers = ['Order ID', 'FC Order Code', 'Status', 'Check-in', 'Check-out', 'Price', 'Payment'];\r\n const rows = orders.map((o) => [\r\n String(o.order_id ?? '-'),\r\n String(o.fc_order_code ?? '-'),\r\n String(o.status ?? '-'),\r\n String(o.check_in ?? '-'),\r\n String(o.check_out ?? '-'),\r\n o.price_amount != null ? `${o.price_amount} ${o.price_currency ?? ''}`.trim() : '-',\r\n String(o.payment_status ?? '-'),\r\n ]);\r\n\r\n const summary: [string, string][] = [\r\n ['Total', String(data.total ?? '-')],\r\n ['Page', String(data.page ?? '-')],\r\n ['Page size', String(data.page_size ?? '-')],\r\n ];\r\n\r\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(summary)}`;\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug list-orders` — list the developer's hotel orders with optional\r\n * status filtering and pagination (§ list-orders schema). Read-only (no\r\n * idempotency key).\r\n *\r\n * Passes `--page`(default 1) / `--page-size`(default 20) / `--status` through\r\n * as query parameters to `GET /hotel/orders` with the `X-Api-Key` auth, and\r\n * renders `ListHotelOrdersResponse` via `renderWithContext` (json carries the\r\n * profile/endpoint envelope). `page`/`page-size` are validated as positive\r\n * integers (invalid → `PARAM_INVALID` before any request); `status` is\r\n * forwarded if and only if `--status` was supplied (omitted entirely when\r\n * absent → all statuses, requirement 9.4). The progress line is emitted through\r\n * the spinner so it goes to stderr and stays silent in json mode.\r\n */\r\nexport function registerHotelListOrdersCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('list-orders')\r\n .description('List the developer\\'s hotel orders with optional status filtering and pagination')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--status <status>', 'Filter by order status (omitted entirely when absent → all statuses)')\r\n .option('--page <page>', 'Page number', DEFAULT_PAGE)\r\n .option('--page-size <size>', 'Page size', DEFAULT_PAGE_SIZE)\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n\r\n attachSchemaHelp(cmd, hotelListOrdersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Build query params. page/page-size are validated as positive integers\r\n // (invalid → PARAM_INVALID before any request); status is forwarded\r\n // verbatim if and only if --status was supplied. Sent as a query string,\r\n // never a body.\r\n const params: Record<string, string> = {\r\n page: positiveInt((opts.page as string | undefined) ?? DEFAULT_PAGE, 'page'),\r\n page_size: positiveInt((opts.pageSize as string | undefined) ?? DEFAULT_PAGE_SIZE, 'page-size'),\r\n };\r\n if (opts.status !== undefined) params.status = opts.status as string;\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) params.member_id = member;\r\n\r\n // Animated spinner: visible in table mode, silent in json mode.\r\n const spinner = format === 'json' ? null : createSpinner('Fetching orders...');\r\n\r\n const result = await deps.apiClient.get<ListHotelOrdersResponse>(\r\n '/hotel/orders',\r\n { type: 'api-key', key: apiKey },\r\n params,\r\n );\r\n\r\n spinner?.stop();\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<ListHotelOrdersResponse> = {\r\n data,\r\n text: () => formatOrders(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { FindDestinationResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelFindDestinationSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (local — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n\r\n/**\r\n * Require a non-empty flag value. Missing or empty input maps to\r\n * `PARAM_INVALID` before any request is issued.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || value.trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table formatter)\r\n// ============================================================\r\n\r\n/**\r\n * Render destinations as a table for `--format table`. An empty\r\n * `destinations[]` is a successful result (exit 0), not an error.\r\n */\r\nfunction formatFindDestination(data: FindDestinationResponse): string {\r\n const destinations = data.destinations ?? [];\r\n if (destinations.length === 0) {\r\n return Formatter.status('info', 'No destinations found for this keyword');\r\n }\r\n\r\n const headers = ['Destination ID', 'Type', 'Name', 'City Name', 'City Code', 'Country', 'Lat', 'Lng'];\r\n const rows = destinations.map((d) => [\r\n String(d.destination_id ?? '-'),\r\n String(d.type ?? '-'),\r\n String(d.name ?? '-'),\r\n String(d.city_name ?? '-'),\r\n String(d.city_code ?? '-'),\r\n String(d.country_name ?? '-'),\r\n String(d.lat ?? '-'),\r\n String(d.lng ?? '-'),\r\n ]);\r\n\r\n return Formatter.table(headers, rows);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug find-destination` — search for a destination by keyword\r\n * (§ find-destination schema). Read-only (no idempotency key, no\r\n * confirmation).\r\n *\r\n * Validates `--keyword` is present and non-empty before any request\r\n * (→ `PARAM_INVALID`), POSTs to `/hotel/find-destination` with `X-Api-Key`\r\n * auth, and renders `FindDestinationResponse` via `renderWithContext`. An\r\n * empty `destinations[]` renders as a successful result (exit 0).\r\n */\r\nexport function registerHotelFindDestinationCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('find-destination')\r\n .description('Search for a hotel destination by keyword (city, landmark, airport, etc.)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--keyword <text>', 'Destination search keyword (required)')\r\n .option('--data-type <type>', 'Optional data type filter');\r\n\r\n attachSchemaHelp(cmd, hotelFindDestinationSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Validate BEFORE any request: --keyword required AND non-empty\r\n const keyword = need(opts.keyword as string | undefined, 'keyword');\r\n\r\n // Build request body (snake_case keys match platform contract).\r\n // Omit data_type when absent.\r\n const body: Record<string, unknown> = { keyword };\r\n if (opts.dataType !== undefined) {\r\n body.data_type = opts.dataType as string;\r\n }\r\n\r\n const result = await deps.apiClient.post<FindDestinationResponse>(\r\n '/hotel/find-destination',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<FindDestinationResponse> = {\r\n data,\r\n text: () => formatFindDestination(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { HotelFiltersResponse, FacilityOption, FilterOption } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelFiltersSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (local — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n\r\n/**\r\n * Require a non-empty flag value. Missing or empty input maps to\r\n * `PARAM_INVALID` before any request is issued.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || value.trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\r\nfunction num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/**\r\n * Number-ify a coordinate flag and enforce its valid range. Missing,\r\n * non-finite, or out-of-range input maps to `PARAM_INVALID` (requirement 20.2)\r\n * before any request is sent.\r\n */\r\nfunction coord(value: string | undefined, flag: string, min: number, max: number): number {\r\n const n = num(value, flag);\r\n if (n < min || n > max) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be between ${min} and ${max}.`);\r\n }\r\n return n;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table formatter)\r\n// ============================================================\r\n\r\n/**\r\n * Render a single filter group as a labelled section. Each item shows\r\n * code, name, and count (plus type for facility groups). The code values\r\n * map directly to the corresponding search filter flags.\r\n */\r\nfunction renderGroup(title: string, items: FilterOption[], isFacility = false): string {\r\n if (items.length === 0) return '';\r\n\r\n const headers = isFacility\r\n ? ['Code', 'Name', 'Count', 'Type']\r\n : ['Code', 'Name', 'Count'];\r\n\r\n const rows = items.map((item) => {\r\n const base = [\r\n String(item.code ?? '-'),\r\n String(item.name ?? '-'),\r\n String(item.count ?? '-'),\r\n ];\r\n if (isFacility) {\r\n base.push(String((item as FacilityOption).type ?? '-'));\r\n }\r\n return base;\r\n });\r\n\r\n return `\\n[${title}]\\n${Formatter.table(headers, rows)}`;\r\n}\r\n\r\n/**\r\n * Render all hotel filter groups for `--format table`. Groups: stars, brands,\r\n * groups, labels, sub_categories, hotel_facilities, room_facilities. Each\r\n * item's code can be passed to the corresponding `search` filter flag.\r\n */\r\nfunction formatFilters(data: HotelFiltersResponse): string {\r\n const sections = [\r\n renderGroup('Stars (→ search --star)', data.stars ?? []),\r\n renderGroup('Brands (→ search --hotel-brand-codes)', data.brands ?? []),\r\n renderGroup('Groups', data.groups ?? []),\r\n renderGroup('Labels (→ search --hotel-label-ids)', data.labels ?? []),\r\n renderGroup('Sub-Categories (→ search --hotel-sub-category-ids)', data.sub_categories ?? []),\r\n renderGroup('Hotel Facilities (→ search --hotel-facility-codes)', data.hotel_facilities ?? [], true),\r\n renderGroup('Room Facilities (→ search --room-facility-codes)', data.room_facilities ?? [], true),\r\n ].filter(Boolean);\r\n\r\n if (sections.length === 0) {\r\n return Formatter.status('info', 'No filter options available for this location');\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug hotel-filters` — retrieve available filter options for a\r\n * location (§ hotel-filters schema). Read-only (no idempotency key, no\r\n * confirmation).\r\n *\r\n * Accepts exactly one location branch: `--destination-id` XOR (`--lat` AND\r\n * `--lng`). Supplying both branches or neither is `PARAM_INVALID` before any\r\n * request. The coordinate branch additionally validates lat∈[-90,90] and\r\n * lng∈[-180,180]. `--distance` (default 20) is always included in the body.\r\n *\r\n * The response groups filter options (stars, brands, groups, labels,\r\n * sub_categories, hotel_facilities, room_facilities) whose codes map directly\r\n * to the corresponding `search` filter flags.\r\n */\r\nexport function registerHotelFiltersCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('hotel-filters')\r\n .description('Get available filter options for hotel search at a given location (codes map to search filters)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--destination-id <id>', 'Destination ID (alternative to --lat/--lng)')\r\n .option('--lat <lat>', 'Latitude (-90 to 90, requires --lng)')\r\n .option('--lng <lng>', 'Longitude (-180 to 180, requires --lat)')\r\n .option('--distance <km>', 'Search radius in kilometers', '20');\r\n\r\n attachSchemaHelp(cmd, hotelFiltersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // ---- Location branch validation (BEFORE any request) ----\r\n // Exactly one branch must be supplied:\r\n // Branch A: --destination-id (alone)\r\n // Branch B: --lat AND --lng (both required together)\r\n // Both branches OR neither → PARAM_INVALID.\r\n const hasDestination = opts.destinationId !== undefined;\r\n const hasLat = opts.lat !== undefined;\r\n const hasLng = opts.lng !== undefined;\r\n const hasCoordBranch = hasLat || hasLng;\r\n\r\n if (hasDestination && hasCoordBranch) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Supply either --destination-id OR --lat/--lng, not both.',\r\n );\r\n }\r\n\r\n if (!hasDestination && !hasCoordBranch) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n 'Supply either --destination-id OR --lat/--lng (one location branch is required).',\r\n );\r\n }\r\n\r\n // Coordinate branch: both lat AND lng must be present, with valid ranges.\r\n if (hasCoordBranch && !(hasLat && hasLng)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n '--lat and --lng must both be provided together.',\r\n );\r\n }\r\n\r\n // Build request body (snake_case keys match platform contract).\r\n const body: Record<string, unknown> = {};\r\n\r\n if (hasDestination) {\r\n body.destination_id = need(opts.destinationId as string | undefined, 'destination-id');\r\n } else {\r\n body.lat = coord(opts.lat as string | undefined, 'lat', -90, 90);\r\n body.lng = coord(opts.lng as string | undefined, 'lng', -180, 180);\r\n }\r\n\r\n // --distance always included (default 20)\r\n body.distance = num(opts.distance as string | undefined, 'distance');\r\n\r\n const result = await deps.apiClient.post<HotelFiltersResponse>(\r\n '/hotel/filters',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<HotelFiltersResponse> = {\r\n data,\r\n text: () => formatFilters(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { ListCitiesResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelListCitiesSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (local — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n\r\n/**\r\n * Require a non-empty flag value. Missing or empty input maps to\r\n * `PARAM_INVALID` before any request is issued.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || value.trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n// ============================================================\r\n// Output helper (table formatter)\r\n// ============================================================\r\n\r\n/**\r\n * Render cities as a table for `--format table`. An empty `cities[]` is\r\n * a successful result (exit 0), not an error.\r\n */\r\nfunction formatListCities(data: ListCitiesResponse): string {\r\n const cities = data.cities ?? [];\r\n if (cities.length === 0) {\r\n return Formatter.status('info', 'No cities found for this country');\r\n }\r\n\r\n const headers = ['City Code', 'City Name', 'Destination ID', 'Lat', 'Lng', 'Country', 'Time Zone'];\r\n const rows = cities.map((c) => [\r\n String(c.city_code ?? '-'),\r\n String(c.city_name ?? '-'),\r\n String(c.destination_id ?? '-'),\r\n String(c.lat ?? '-'),\r\n String(c.lng ?? '-'),\r\n String(c.country_name ?? '-'),\r\n String(c.time_zone ?? '-'),\r\n ]);\r\n\r\n return Formatter.table(headers, rows);\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug list-cities` — list cities for a given country code\r\n * (§ list-cities schema). Read-only (no idempotency key, no confirmation).\r\n *\r\n * Validates `--country` is present and non-empty before any request\r\n * (→ `PARAM_INVALID`), POSTs to `/hotel/cities` with `X-Api-Key` auth,\r\n * and renders `ListCitiesResponse` via `renderWithContext`. An empty\r\n * `cities[]` renders as a successful result (exit 0).\r\n */\r\nexport function registerHotelListCitiesCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('list-cities')\r\n .description('List cities available for hotel booking in a given country')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--country <code>', 'ISO country code (required)');\r\n\r\n attachSchemaHelp(cmd, hotelListCitiesSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Validate BEFORE any request: --country required AND non-empty\r\n const country = need(opts.country as string | undefined, 'country');\r\n\r\n // Build request body (snake_case keys match platform contract).\r\n // Flag is --country, body field is country_code.\r\n const body: Record<string, unknown> = { country_code: country };\r\n\r\n const result = await deps.apiClient.post<ListCitiesResponse>(\r\n '/hotel/cities',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<ListCitiesResponse> = {\r\n data,\r\n text: () => formatListCities(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport {\r\n ApiClient,\r\n ConfigManager,\r\n PromptEngine,\r\n Formatter,\r\n resolveFormat,\r\n CliError,\r\n renderWithContext,\r\n} from '@agenzo/cli-core';\r\nimport type { CommandResult } from '@agenzo/cli-core';\r\nimport type { HotelDetailResponse } from '../types/hotel.js';\r\nimport { attachSchemaHelp, hotelDetailSchema } from '../verb-schema.js';\r\n\r\n// ============================================================\r\n// Input helpers (local — body assembly stays in app per req 15.3)\r\n// ============================================================\r\n\r\n/**\r\n * Require a non-empty flag value. Missing or empty input maps to\r\n * `PARAM_INVALID` before any request is issued.\r\n */\r\nfunction need(value: string | undefined, flag: string): string {\r\n if (value === undefined || value.trim() === '') {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Parse `--settings` (comma-separated or JSON array string) into a string[].\r\n * Validation of allowed codes happens server-side (provider); this is pure\r\n * parsing, no whitelist duplicated here.\r\n */\r\nfunction parseSettings(value: string | undefined): string[] | undefined {\r\n if (value === undefined || value.trim() === '') {\r\n return undefined;\r\n }\r\n const trimmed = value.trim();\r\n if (trimmed.startsWith('[')) {\r\n try {\r\n const parsed = JSON.parse(trimmed);\r\n if (Array.isArray(parsed) && parsed.every((v) => typeof v === 'string')) {\r\n return parsed;\r\n }\r\n } catch {\r\n // fall through to comma-split below\r\n }\r\n throw new CliError('PARAM_INVALID', 'Invalid --settings JSON array.');\r\n }\r\n return trimmed\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter((s) => s.length > 0);\r\n}\r\n\r\n// ============================================================\r\n// Output helpers (table formatter)\r\n// ============================================================\r\n\r\n/**\r\n * Render hotel detail as a key/value block + facilities table + images table.\r\n * Images table is empty when `--with-images false`.\r\n */\r\nfunction formatHotelDetail(data: HotelDetailResponse): string {\r\n const lines: string[] = [];\r\n\r\n // Key/value block\r\n const kvPairs: [string, string][] = [\r\n ['Hotel ID', String(data.hotel_id ?? '-')],\r\n ['Hotel Name', String(data.hotel_name ?? '-')],\r\n ['English Name', String(data.hotel_eng_name ?? '-')],\r\n ['Star', String(data.star ?? '-')],\r\n ['Address', String(data.address ?? '-')],\r\n ['Intro', String(data.intro ?? '-')],\r\n ['Telephone', String(data.telephone ?? '-')],\r\n ['Country', String(data.country_name ?? '-')],\r\n ['Province', String(data.province_name ?? '-')],\r\n ['City', String(data.city_name ?? '-')],\r\n ['District', String(data.district_name ?? '-')],\r\n ['Business Area', String(data.business_name ?? '-')],\r\n ['Latitude', String(data.lat ?? '-')],\r\n ['Longitude', String(data.lng ?? '-')],\r\n ['Check-in Time', String(data.check_in_time ?? '-')],\r\n ['Check-out Time', String(data.check_out_time ?? '-')],\r\n ['Room Count', String(data.room_num ?? '-')],\r\n ];\r\n\r\n lines.push(Formatter.keyValue(kvPairs));\r\n\r\n // Special check-in instructions — MUST be shown to the user when present\r\n // (upstream data provider does not accept liability for booking issues\r\n // caused by this not being displayed). Only non-null when --settings\r\n // included 'hotelTextPolicies'.\r\n if (data.special_instructions) {\r\n lines.push('');\r\n lines.push(Formatter.status('warning', `Special Check-in Instructions: ${data.special_instructions}`));\r\n }\r\n\r\n // Facilities table\r\n const facilities = data.facilities ?? [];\r\n if (facilities.length > 0) {\r\n lines.push('');\r\n lines.push('Facilities:');\r\n const facHeaders = ['Name', 'Type'];\r\n const facRows = facilities.map((f) => [\r\n String(f.name ?? '-'),\r\n String(f.type ?? '-'),\r\n ]);\r\n lines.push(Formatter.table(facHeaders, facRows));\r\n } else {\r\n lines.push('');\r\n lines.push(Formatter.status('info', 'No facilities listed'));\r\n }\r\n\r\n // Images table\r\n const images = data.images ?? [];\r\n if (images.length > 0) {\r\n lines.push('');\r\n lines.push('Images:');\r\n const imgHeaders = ['URL', 'Is Main'];\r\n const imgRows = images.map((img) => [\r\n String(img.url ?? '-'),\r\n String(img.is_main ?? false),\r\n ]);\r\n lines.push(Formatter.table(imgHeaders, imgRows));\r\n } else {\r\n lines.push('');\r\n lines.push(Formatter.status('info', 'No images available'));\r\n }\r\n\r\n // Rooms table — static room-type info (area/floor/beds/occupancy) + a\r\n // per-room image count. room_id is the SAME id space as quote's\r\n // roomItems[].roomId, so this can be related to quote's live rates.\r\n const rooms = data.rooms ?? [];\r\n if (rooms.length > 0) {\r\n lines.push('');\r\n lines.push('Rooms:');\r\n const roomHeaders = ['Room ID', 'Room Name', 'Area', 'Floor', 'Max Person', 'Beds', 'Images'];\r\n const roomRows = rooms.map((r) => {\r\n const bedsStr = (r.beds ?? [])\r\n .map((b) => `${b.name ?? '-'}${b.num ? ` x${b.num}` : ''}`)\r\n .join(', ') || '-';\r\n return [\r\n String(r.room_id ?? '-'),\r\n String(r.room_name ?? '-'),\r\n String(r.area_sqm ?? '-'),\r\n String(r.floor ?? '-'),\r\n String(r.max_person ?? '-'),\r\n bedsStr,\r\n String((r.images ?? []).length),\r\n ];\r\n });\r\n lines.push(Formatter.table(roomHeaders, roomRows));\r\n lines.push(\r\n '',\r\n Formatter.status(\r\n 'info',\r\n 'room_id matches quote\\'s roomItems[].roomId — use it to relate a room here to its live rate in quote.',\r\n ),\r\n );\r\n } else {\r\n lines.push('');\r\n lines.push(Formatter.status('info', 'No room-type details available'));\r\n }\r\n\r\n // Review scores — only present when --settings included 'comment'.\r\n const comments = data.comment ?? [];\r\n if (comments.length > 0) {\r\n lines.push('');\r\n lines.push('Review Scores:');\r\n const headers = ['Channel', 'Average Score'];\r\n const rows = comments.map((c) => [String(c.channel ?? '-'), String(c.average_score ?? '-')]);\r\n lines.push(Formatter.table(headers, rows));\r\n }\r\n\r\n // Certificates/qualifications — only present when --settings included 'hotelCertificates'.\r\n const certs = data.hotel_certificates ?? [];\r\n if (certs.length > 0) {\r\n lines.push('');\r\n lines.push('Certificates:');\r\n const headers = ['Name', 'Unify Code'];\r\n const rows = certs.map((c) => [String(c.certification_name ?? '-'), String(c.unify_code ?? '-')]);\r\n lines.push(Formatter.table(headers, rows));\r\n }\r\n\r\n // Text policies (hotelPolicy/instructions/mandatoryFees/etc) — only present when\r\n // --settings included 'hotelTextPolicies'. specialInstructions is shown separately\r\n // above (must-display), so it is excluded here to avoid duplication.\r\n const textPolicies = (data.hotel_text_policies ?? []).filter(\r\n (p) => p.code !== 'specialInstructions',\r\n );\r\n if (textPolicies.length > 0) {\r\n lines.push('');\r\n lines.push('Hotel Policies:');\r\n const headers = ['Policy', 'Text'];\r\n const rows = textPolicies.map((p) => [String(p.code_name ?? p.code ?? '-'), String(p.text ?? '-')]);\r\n lines.push(Formatter.table(headers, rows));\r\n }\r\n\r\n return lines.join('\\n');\r\n}\r\n\r\n// ============================================================\r\n// Command registration\r\n// ============================================================\r\n\r\n/**\r\n * `hotel-redaug hotel-detail` — get detailed information about a specific hotel\r\n * (§ hotel-detail schema). Read-only (no idempotency key, no confirmation).\r\n *\r\n * Validates `--hotel-id` is present and non-empty before any request\r\n * (→ `PARAM_INVALID`), POSTs to `/hotel/detail` with `X-Api-Key` auth,\r\n * and renders `HotelDetailResponse` via `renderWithContext`. When\r\n * `--with-images false`, the body sends `with_images: false` and the\r\n * platform returns an empty `images[]`.\r\n */\r\nexport function registerHotelDetailCommand(parent: Command, deps: { apiClient: ApiClient }): void {\r\n const cmd = parent\r\n .command('hotel-detail')\r\n .description('Get detailed information about a specific hotel (facilities, images, etc.)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--hotel-id <id>', 'Hotel ID (required)')\r\n .option('--with-images [value]', 'Include hotel images (default: true)', true)\r\n .option(\r\n '--settings <list>',\r\n 'Optional on-demand upstream fields, comma-separated or JSON array ' +\r\n '(hotelFacilityNew, breakfast, importantNotices, parking, chargingParking, ' +\r\n 'hotelCertificates, comment, hotelMeetingInfos, hotelVideoInfos, hotelTextPolicies, ' +\r\n 'hotelStructuredPolicies.childPolicy, hotelStructuredPolicies.extraBedPolicy, ' +\r\n 'hotelStructuredPolicies.petPolicy). Pass hotelTextPolicies to get special_instructions.',\r\n );\r\n\r\n attachSchemaHelp(cmd, hotelDetailSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n\r\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\r\n message: 'API Key:',\r\n type: 'password',\r\n });\r\n\r\n // Validate BEFORE any request: --hotel-id required AND non-empty\r\n const hotelId = need(opts.hotelId as string | undefined, 'hotel-id');\r\n\r\n // Resolve --with-images boolean. Commander parses boolean-like options:\r\n // --with-images / --with-images true → true (default)\r\n // --with-images false → 'false' (string)\r\n const rawWithImages = opts.withImages;\r\n const withImages = rawWithImages !== 'false' && rawWithImages !== false;\r\n\r\n const settings = parseSettings(opts.settings as string | undefined);\r\n\r\n // Build request body (snake_case keys match platform contract).\r\n const body: Record<string, unknown> = {\r\n hotel_id: hotelId,\r\n with_images: withImages,\r\n };\r\n if (settings !== undefined) {\r\n body.settings = settings;\r\n }\r\n\r\n const result = await deps.apiClient.post<HotelDetailResponse>(\r\n '/hotel/detail',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n\r\n if (!result.success) {\r\n throw CliError.fromApi(result, { auth: 'api-key' });\r\n }\r\n\r\n const data = result.data;\r\n\r\n const configManager = new ConfigManager();\r\n const commandResult: CommandResult<HotelDetailResponse> = {\r\n data,\r\n text: () => formatHotelDetail(data),\r\n };\r\n\r\n await renderWithContext(commandResult, { format }, configManager);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\n\r\nconst SKILL_TEXT = `\r\n---\r\nname: hotel-redaug\r\ndescription: Search, create orders, and manage international hotel reservations via the Redaug provider. Two-step create-then-pay flow supporting monthly_settlement and pay_per_call (EVO) billing modes. Use when the user wants to find hotels, check room prices/availability, make a hotel booking, or view/cancel/modify an existing hotel order. Not for flights, rides, or domestic-only stays.\r\n---\r\n\r\n# hotel-redaug — Agent Skill\r\n\r\nYou orchestrate hotel bookings through CLI verbs. This guide covers HOW to chain\r\nthe verbs and pass data between them. For exact flags and field types, read the\r\nschema (\\`services get svc_01J0HT5REDAUG0001 --api-key <key> --format json\\`) or\r\nrun \\`hotel-redaug <verb> --help\\`.\r\n\r\n## Prerequisites\r\n\r\n- API key with merchant scope\r\n- Two billing modes supported (set on the developer, not chosen per-call):\r\n - **monthly_settlement**: developer has a settlement account with sufficient balance\r\n - **pay_per_call**: developer collects payment from their end-user via EVO; the user pays using the create-order \\`order_id\\` as the EVO merchantTransID, and the platform verifies by querying EVO for that order_id (the pay-order response reports settlement_path \"pay_per_call\")\r\n- BILLING_MODE_MISMATCH means the order billing_mode is not one of the two modes above\r\n- Pass --api-key <key> --format json on every call; add --yes on writes\r\n\r\n## Workflow\r\n\r\n1. Resolve location\r\n - find-destination --keyword \"<place>\" → lat/lng or destination_id\r\n - list-cities --country <code> → destination_id\r\n - (Need exactly one of these for search.)\r\n\r\n2. Search hotels\r\n - Pass ONE location branch (coordinates OR destination_id) + dates + guests\r\n - Optional: hotel-filters first to get valid filter codes, then pass to search\r\n\r\n3. Choose a hotel (MANDATORY unless the user already named one exact hotel)\r\n - MUST present the candidates to the user (name, address/distance, star/score if useful)\r\n and get an explicit pick — never auto-select by distance or price alone, even for an\r\n open-ended request like \"book me something near the Bund\"\r\n - hotel-detail <hotel-id> for the shortlisted/chosen hotel is OPTIONAL AT THIS STEP for\r\n the hotel-level info (address/intro/hotel photos) — the candidate list above is enough\r\n to pick a HOTEL. But you WILL need hotel-detail's rooms[] at step 4 below to describe\r\n ROOMS, so in practice call it once the user has picked (or shortlisted) a hotel, before\r\n moving to quote — don't make two round trips when one will do\r\n\r\n4. Quote + show room options (ALWAYS call hotel-detail here — this is the mandatory part)\r\n - quote the chosen hotel + same dates/guests → rates[]\r\n - Empty rates[] = no availability → stop, tell the user\r\n - Each rate carries the inputs for create-order: product_token, total_price, price_items\r\n - quote's rates[].room_name is only a bare one-line label with NO area/beds/photos. MUST\r\n call hotel-detail on the same hotel_id (if not already called in step 3) and match its\r\n rooms[] to quote's rates by room_name — do this proactively, BEFORE presenting rate\r\n options, not only if the user asks for more detail. The room is the actual product being\r\n booked, so the user picking a rate MUST see area_sqm, floor, beds, and images alongside\r\n rate_plan_name/breakfast/free_cancellation/total_price+currency — never present rate\r\n options as a bare list of room_name + price only.\r\n - MUST present the combined rate+room options and get the user's explicit pick of which\r\n rate to book — same rule as step 3, and now with real room detail attached, not optional\r\n\r\n5. Create order (lock inventory, no charge) — MUST NOT run until step 3+4 confirmation happened\r\n - create-order: forward quote outputs VERBATIM (product_token, amount, currency, price_items)\r\n - Collect from user: guest_name, contact_name, contact_phone\r\n - Generate a unique idempotency-key\r\n - Response → save order_id + fc_order_code + total_amount + currency\r\n - Order status: AWAITING_PAYMENT (no money charged yet)\r\n\r\n6. BRANCH ON BILLING_MODE — decide THIS before calling pay-order, not inside it\r\n - You (the developer/Agent) know your own billing_mode; the order does not expose it.\r\n a) monthly_settlement → skip straight to step 7 (pay-order). Nothing to do here.\r\n b) pay_per_call → STOP. Do NOT call pay-order yet.\r\n - Drive YOUR OWN EVO payment integration now, using the order_id from step 5 AS THE\r\n EVO merchantTransID (this is the id you pass to your EVO payment call — not a new\r\n or random id).\r\n - Wait for the end-user to actually complete that EVO payment for total_amount+currency.\r\n - Only once EVO shows the payment as complete, proceed to step 7 — pay-order is what\r\n tells the platform \"go verify and settle this\", it does NOT itself collect payment.\r\n\r\n7. Pay order (settle the locked order) — MUST confirm with the user before calling this\r\n - Before calling: show the user total_amount + currency from create-order and which\r\n billing path applies, and get explicit go-ahead — pay-order is the step that actually\r\n moves money (for pay_per_call, confirm the EVO payment from step 6 was completed first)\r\n - pay-order --order-id <order_id from create-order> (that's the only identifier needed)\r\n - Billing path determined server-side by developer's billing_mode:\r\n a) monthly_settlement:\r\n - Platform deducts from settlement account → calls upstream payOrder\r\n b) pay_per_call:\r\n - Requires step 6 to have already happened (user paid via EVO under this order_id).\r\n Calling pay-order now just makes the platform query EVO for that order_id and\r\n verify exact amount/currency — it does NOT initiate the EVO payment itself.\r\n There is no merchant-transaction-id flag: the EVO key IS the order_id, so a\r\n foreign already-paid EVO transaction cannot be substituted.\r\n - If EVO not yet confirmed → PAYMENT_NOT_COMPLETED; use --watch to poll\r\n - On success → order status becomes PAID\r\n\r\n8. Confirm (upstream confirmation is async)\r\n - Poll get --order-id until CONFIRMED (success) or CANCELLED (failed)\r\n - Do not report success before CONFIRMED\r\n\r\n9. Post-booking (only when the user asks)\r\n - cancel: order_id + fc_order_code + reason\r\n - checkout: partial leave-early → then poll get-checkout with task_order_code\r\n - list-orders: view all orders\r\n\r\n## Data passing (where each value comes from)\r\n\r\n- product_token : quote → create-order (opaque; never fabricate or edit)\r\n- price_items : quote → create-order (JSON array; copy exactly)\r\n- order_id : create-order → pay-order / get / cancel\r\n- fc_order_code : create-order → cancel / checkout\r\n- order_id (again): for pay_per_call it IS the EVO merchantTransID — YOU (the developer/Agent)\r\n use it to drive your own EVO payment call BEFORE pay-order (see step 6); pay-order itself\r\n takes no separate merchant-transaction-id, it only verifies the payment already made\r\n- task_order_code : checkout → get-checkout\r\n\r\n## Billing modes (chosen server-side by billing_mode)\r\n\r\npay-order takes only --order-id; there is NO merchant-transaction-id flag. The platform\r\nroutes purely by the order's billing_mode:\r\n\r\n| Developer billing_mode | Behavior |\r\n|------------------------|----------|\r\n| monthly_settlement | Deducts settlement balance → payOrder |\r\n| pay_per_call | Platform queries EVO for the order_id → verify exact amount/currency → payOrder (response settlement_path is \"pay_per_call\") |\r\n| anything else | ERROR: BILLING_MODE_MISMATCH (only the two modes above are valid) |\r\n\r\n## pay_per_call flow — the EVO merchantTransID IS the order_id\r\n\r\n1. create-order returns order_id + total_amount + currency (no EVO credentials in response)\r\n2. YOU drive your own EVO payment integration now, passing the order_id as the EVO\r\n merchantTransID, and get the user to pay total_amount+currency\r\n (the shared EVO parameters are onboarded separately, out of band — pay-order does not do\r\n this step for you)\r\n3. ONLY once that EVO payment is complete, call pay-order --order-id <order_id>\r\n (no other identifier)\r\n4. Platform queries EVO for that order_id: paid + exact amount/currency match → payOrder → PAID\r\n5. If not yet paid → PAYMENT_NOT_COMPLETED; use --watch to auto-poll\r\n6. Why order_id (not an arbitrary id): it binds the payment to this exact order, so a caller\r\n cannot present some other already-paid EVO transaction of the same amount.\r\n\r\n## Invariants\r\n\r\n- search: exactly one location branch (both or neither = error)\r\n- Never create-order without a fresh quote (tokens expire)\r\n- Never claim \"booked\" until get returns CONFIRMED\r\n- create-order and pay-order are separate steps; create-order does NOT charge\r\n- pay-order depends on create-order's output (order_id)\r\n- Write verbs (create-order/pay-order/cancel/checkout) always need --idempotency-key and --yes\r\n- IMPORTANT: --yes only skips this CLI's own interactive TTY prompt (needed because the Agent\r\n runs non-interactively). It is NOT a substitute for showing the user the hotel/rate/price and\r\n getting their decision in the chat UI. Passing --yes does not remove the confirmation steps in\r\n step 3/4 (choose hotel + rate) or step 7 (confirm before pay-order) above.\r\n- After a cancel call returns successfully (including the cancel_status='cancel_pending' shape),\r\n do NOT call cancel again for the same order — poll get instead. A pending acknowledgement is\r\n success, not failure.\r\n\r\n## Errors\r\n\r\n- RESOURCE_NOT_FOUND (find-destination) → platform 404 for this keyword, distinct from an\r\n empty destinations[] (which is a normal no-match, not an error). Do not keep retrying the\r\n keyword — fall back to the coordinate branch (search/hotel-filters --lat/--lng) if you can\r\n geocode the place or already know its coordinates; otherwise ask the user for a city or a\r\n more specific landmark.\r\n- BILLING_MODE_MISMATCH → order billing_mode is not monthly_settlement or pay_per_call\r\n- ACCOUNT_INSUFFICIENT_BALANCE → settlement account needs top-up; inform user\r\n- PAYMENT_NOT_COMPLETED → EVO not confirmed yet; retry (--watch) or wait\r\n- PAYMENT_NOT_FOUND → no EVO transaction for that ID; verify with user\r\n- PAYMENT_AMOUNT_MISMATCH → EVO amount/currency ≠ order; user must pay correct amount\r\n- PAYORDER_FAILED → upstream payOrder failed; money refunded, safe to retry\r\n- PAYORDER_FAILED_AFTER_PAYMENT → EVO confirmed but payOrder failed; needs reconciliation\r\n- UPSTREAM_ERROR → transient provider issue; wait and retry once\r\n- PARAM_INVALID → bad argument; run <verb> --help and correct it\r\n- empty rates[] → no rooms; suggest other dates or hotels\r\n`.trim();\r\n\r\n/**\r\n * \\`hotel-redaug skill\\` — output the usage guide for AI Agents.\r\n *\r\n * Pure read-only command: no API call, no state change. Prints a structured\r\n * skill document that teaches an Agent how to orchestrate hotel-redaug verbs.\r\n * Detailed parameter specs live in the schema (services get) and per-verb --help.\r\n */\r\nexport function registerHotelSkillCommand(parent: Command): void {\r\n parent\r\n .command('skill')\r\n .description('Print the hotel-redaug usage guide (orchestration flow, data passing, rules)')\r\n .action(() => {\r\n console.log(SKILL_TEXT);\r\n });\r\n}\r\n","/**\r\n * Shared input/output helpers for the flight-flink command group.\r\n *\r\n * Mirrors the ride-elife / hotel-redaug conventions: required-flag validation\r\n * maps to `PARAM_INVALID` (catalog code, exit 1); JSON array flags are parsed +\r\n * shape-checked before any request; results render via renderWithContext.\r\n */\r\nimport { CliError, Formatter, PromptEngine } from '@agenzo/cli-core';\r\nimport type { ApiClient, CommandResult } from '@agenzo/cli-core';\r\nimport { ConfigManager, resolveFormat, renderWithContext } from '@agenzo/cli-core';\r\n\r\nexport type Deps = { apiClient: ApiClient };\r\n\r\n/** Require a flag value; missing → PARAM_INVALID. */\r\nexport function need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Parse a numeric flag; non-number → PARAM_INVALID. */\r\nexport function num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/** Parse a JSON-array flag; non-JSON / non-array → PARAM_INVALID. Returned verbatim. */\r\nexport function jsonArray(raw: string, flag: string): unknown[] {\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a JSON array.`);\r\n }\r\n if (!Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a JSON array.`);\r\n }\r\n return parsed;\r\n}\r\n\r\n/** Resolve the API key (flag or interactive password prompt). */\r\nexport function resolveApiKey(flag: string | undefined): Promise<string> {\r\n return PromptEngine.resolveInput(flag, { message: 'API Key:', type: 'password' });\r\n}\r\n\r\n/** Render a success result: JSON envelope in json mode, pretty text otherwise. */\r\nexport async function render<T>(\r\n data: T,\r\n format: string | undefined,\r\n text: (d: T) => string,\r\n): Promise<void> {\r\n const resolved = resolveFormat(format);\r\n const result: CommandResult<T> = { data, text: () => text(data) };\r\n await renderWithContext(result, { format: resolved }, new ConfigManager());\r\n}\r\n\r\n/** Compact key/value renderer for arbitrary record data. */\r\nexport function kv(data: Record<string, unknown>): string {\r\n const lines: [string, string][] = Object.entries(data).map(([k, v]) => [\r\n k,\r\n typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v ?? '-'),\r\n ]);\r\n return Formatter.keyValue(lines);\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightFindAirportSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink find-airport` — resolve free-text into city/airport candidates. */\r\nexport function registerFindAirportCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('find-airport')\r\n .description('Resolve free-text into city/airport candidates')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--keyword <text>', 'Free-text place/airport/city name');\r\n attachSchemaHelp(cmd, flightFindAirportSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const keyword = need(opts.keyword as string | undefined, 'keyword');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Resolving airports...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/find-airport',\r\n { type: 'api-key', key: apiKey },\r\n { keyword },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n JSON.stringify(d.airports ?? d, null, 2),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightListAirportsSchema } from '../verb-schema.js';\r\nimport { type Deps, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink list-airports` — paged airport dictionary. */\r\nexport function registerListAirportsCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-airports')\r\n .description('Paged airport dictionary')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--page <n>', 'Page (1-based)', '1')\r\n .option('--page-size <n>', 'Items per page (1-100)', '20')\r\n .option('--keyword <text>', 'Optional name filter');\r\n attachSchemaHelp(cmd, flightListAirportsSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body: Record<string, unknown> = {\r\n page: num(opts.page as string | undefined, 'page'),\r\n page_size: num(opts.pageSize as string | undefined, 'page-size'),\r\n };\r\n if (opts.keyword !== undefined) body.keyword = opts.keyword as string;\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching airports...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/airports',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightListAirlinesSchema } from '../verb-schema.js';\r\nimport { type Deps, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink list-airlines` — paged airline dictionary. */\r\nexport function registerListAirlinesCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-airlines')\r\n .description('Paged airline dictionary')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--page <n>', 'Page (1-based)', '1')\r\n .option('--page-size <n>', 'Items per page (1-100)', '20')\r\n .option('--keyword <text>', 'Optional name filter');\r\n attachSchemaHelp(cmd, flightListAirlinesSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body: Record<string, unknown> = {\r\n page: num(opts.page as string | undefined, 'page'),\r\n page_size: num(opts.pageSize as string | undefined, 'page-size'),\r\n };\r\n if (opts.keyword !== undefined) body.keyword = opts.keyword as string;\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching airlines...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/airlines',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightListNationalitiesSchema } from '../verb-schema.js';\r\nimport { type Deps, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink list-nationalities` — nationality list (no params). */\r\nexport function registerListNationalitiesCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-nationalities')\r\n .description('Nationality list')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n attachSchemaHelp(cmd, flightListNationalitiesSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching nationalities...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/nationalities',\r\n { type: 'api-key', key: apiKey },\r\n {},\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { SearchFlightResponse } from '../types/flight.js';\r\nimport { attachSchemaHelp, flightSearchSchema } from '../verb-schema.js';\r\nimport { type Deps, jsonArray, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink search` — search flights (one-way/round-trip/multi-city, journeyId relay). */\r\nexport function registerSearchCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('search')\r\n .description('Search flights (one-way/round-trip/multi-city, journeyId relay)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--trip-type <n>', '1=one-way, 2=round-trip, 3=multi-city')\r\n .option('--journeys <json>', 'JSON array of {date, origin, destination, origin_type?, destination_type?}')\r\n .option('--cabin-class <c>', 'economy | premium_economy | business | first', 'economy')\r\n .option('--adult-num <n>', 'Adults (1-9)', '1')\r\n .option('--child-num <n>', 'Children (0-9)', '0')\r\n .option('--infant-num <n>', 'Infants (0-9)', '0')\r\n .option('--airline <code>', 'Airline 2-letter code filter')\r\n .option('--transfer-number <n>', '0=any,1=direct,2=1 stop,3=2 stops', '0')\r\n .option('--journey-id <json>', \"Relay: the chosen offer's next_journey_ids, verbatim (round-trip/multi-city)\");\r\n attachSchemaHelp(cmd, flightSearchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const body: Record<string, unknown> = {\r\n trip_type: num(opts.tripType as string | undefined, 'trip-type'),\r\n journeys: jsonArray(need(opts.journeys as string | undefined, 'journeys'), 'journeys'),\r\n cabin_class: opts.cabinClass as string,\r\n adult_num: num(opts.adultNum as string | undefined, 'adult-num'),\r\n child_num: num(opts.childNum as string | undefined, 'child-num'),\r\n infant_num: num(opts.infantNum as string | undefined, 'infant-num'),\r\n transfer_number: num(opts.transferNumber as string | undefined, 'transfer-number'),\r\n };\r\n if (opts.airline !== undefined) body.airline = opts.airline as string;\r\n if (opts.journeyId !== undefined) {\r\n body.journey_id = jsonArray(opts.journeyId as string, 'journey-id');\r\n }\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Searching flights...');\r\n const result = await deps.apiClient.post<SearchFlightResponse>(\r\n '/flight/search',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightMoreOffersSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink more-offers` — more fare offers for a priceKey. */\r\nexport function registerMoreOffersCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('more-offers')\r\n .description('More fare offers for a priceKey (carried by product_token)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--product-token <token>', 'Opaque token from search');\r\n attachSchemaHelp(cmd, flightMoreOffersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const productToken = need(opts.productToken as string | undefined, 'product-token');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching offers...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/more-offers',\r\n { type: 'api-key', key: apiKey },\r\n { product_token: productToken },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { VerifyFlightResponse } from '../types/flight.js';\r\nimport { attachSchemaHelp, flightVerifySchema } from '../verb-schema.js';\r\nimport { type Deps, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink verify` — pre-booking price verification. */\r\nexport function registerVerifyCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('verify')\r\n .description('Verify the latest price before booking; returns the authoritative product_token')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--product-token <token>', 'Opaque token from search')\r\n // 任务 4「价格变了自动刷新」:以下 5 个全部可选,缺省不下发(请求体与加入前逐字相同)。\r\n // previous-total-price:选中那一轮 offer 的总价;带上它,供应商 1002/1950 时平台会按\r\n // token 自解行程重搜一次找回同一班,响应带回 previous_total_price 供确认卡显示 原价→新价。\r\n // 其余 4 个仅重搜时使用(token 里没有舱位/乘客数),保证找回用户原本选定的那档产品。\r\n .option('--previous-total-price <n>', 'Total price of the selected offer; enables the one-shot re-search refresh on supplier 1002/1950')\r\n .option('--cabin-class <c>', 'Cabin class to re-search with (economy | premium_economy | business | first)')\r\n .option('--adult-num <n>', 'Adults to re-search with (1-9)')\r\n .option('--child-num <n>', 'Children to re-search with (0-9)')\r\n .option('--infant-num <n>', 'Infants to re-search with (0-9)');\r\n attachSchemaHelp(cmd, flightVerifySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const productToken = need(opts.productToken as string | undefined, 'product-token');\r\n\r\n const body: Record<string, unknown> = { product_token: productToken };\r\n if (opts.previousTotalPrice !== undefined) {\r\n body.previous_total_price = num(opts.previousTotalPrice as string, 'previous-total-price');\r\n }\r\n if (opts.cabinClass !== undefined) body.cabin_class = opts.cabinClass as string;\r\n if (opts.adultNum !== undefined) body.adult_num = num(opts.adultNum as string, 'adult-num');\r\n if (opts.childNum !== undefined) body.child_num = num(opts.childNum as string, 'child-num');\r\n if (opts.infantNum !== undefined) body.infant_num = num(opts.infantNum as string, 'infant-num');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Verifying price...');\r\n const result = await deps.apiClient.post<VerifyFlightResponse>(\r\n '/flight/verify',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n Formatter.keyValue([\r\n ['Product token', String(d.product_token ?? '-')],\r\n ['Total price', `${d.total_price ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ['Price changed', String(d.price_changed)],\r\n // 刷新路径:平台带回选中时的原价,人读 output 里直接看出 原价 → 新价。\r\n ...(d.previous_total_price != null\r\n ? ([['Previous total price', String(d.previous_total_price)]] as [string, string][])\r\n : []),\r\n ]),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { CreateFlightOrderResponse } from '../types/flight.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightCreateOrderSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { type Deps, jsonArray, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/**\r\n * `flight-flink create-order` — create a flight order without charging (locks the\r\n * fare). Calls POST /flight/create-order with an Idempotency-Key header. The order\r\n * enters AWAITING_PAYMENT and must be settled via pay-order. Non-`--yes` path\r\n * confirms (restating amount) before the write; a declined confirm → CLIENT_ABORTED.\r\n */\r\nexport function registerCreateOrderCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('create-order')\r\n .description('Create a flight order without charging (locks the fare, await payment)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--product-token <token>', 'Authoritative rate token from verify')\r\n .option('--total-amount <amount>', 'Verified total price in decimal units')\r\n .option('--currency <currency>', 'ISO 4217 currency code')\r\n .option('--trip-type <n>', '1/2/3', '1')\r\n .option('--contact-name <name>', 'Booking contact name')\r\n .option('--contact-region <code>', \"Contact phone country code (no '+')\")\r\n .option('--contact-phone <phone>', 'Booking contact phone')\r\n .option('--contact-email <email>', 'Booking contact email')\r\n .option(\r\n '--passengers <json>',\r\n 'JSON array of passengers (gender/id_type are strings). A passenger may be just ' +\r\n '{\"traveller_token\":\"tvp_...\",\"type\":\"adult\"} from token-cli travellers list.',\r\n )\r\n .option('--save-travellers', 'Save the fully filled passengers as frequent travellers (only when the user asked)')\r\n .option('--payment-method-id <id>', 'Optional bound-card id (pay_per_call only)')\r\n .option('--payment-token-id <id>', 'Optional UPI network-token id (unionpay charge path)')\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'EVO merchant transaction id of an already-authorised preauth (3DS challenge resume). ' +\r\n 'When set, the server reuses that authorization instead of creating a new one, ' +\r\n 'avoiding a second hold on the card (pay_per_call mode only).',\r\n )\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION)\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightCreateOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const productToken = need(opts.productToken as string | undefined, 'product-token');\r\n const totalAmount = num(opts.totalAmount as string | undefined, 'total-amount');\r\n const currency = need(opts.currency as string | undefined, 'currency');\r\n const body: Record<string, unknown> = {\r\n product_token: productToken,\r\n total_amount: totalAmount,\r\n currency,\r\n trip_type: num(opts.tripType as string | undefined, 'trip-type'),\r\n contact_name: need(opts.contactName as string | undefined, 'contact-name'),\r\n contact_region: need(opts.contactRegion as string | undefined, 'contact-region'),\r\n contact_phone: need(opts.contactPhone as string | undefined, 'contact-phone'),\r\n contact_email: need(opts.contactEmail as string | undefined, 'contact-email'),\r\n passengers: jsonArray(need(opts.passengers as string | undefined, 'passengers'), 'passengers'),\r\n };\r\n // 常用旅客:只在用户要求保存时才带,缺省不出现在请求体里(老调用方逐字不变)。\r\n if (opts.saveTravellers) body.save_travellers = true;\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n // UPI(unionpay) 扣款路径:透传已 ACTIVE 的 network token id;platform create-order\r\n // 据 payment_token_id 非空走 ChargeService 实扣(跳过 EVO 预授权/捕获)。\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n // 3DS 挑战续单凭证:持卡人完成认证后带回该交易号,服务端复用那笔已授权的预授权,\r\n // 不再新发起一次(否则又拿到新挑战页且重复冻结资金)。\r\n if (opts.authorizedMerchantTransId) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 归因标签(可选):非空才写入,缺省保持无归属。\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) body.member_id = member;\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Create this flight order for ${totalAmount} ${currency}? This locks the fare but does NOT charge yet.`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Order creation aborted by user.');\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink create-order',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Creating flight order...');\r\n const result = await deps.apiClient.post<CreateFlightOrderResponse>(\r\n '/flight/create-order',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n [\r\n Formatter.keyValue([\r\n ['Order no', String(d.order_no ?? '-')],\r\n ['Upstream order no', String(d.upstream_order_no ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Total amount', `${d.total_amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ]),\r\n Formatter.status(\r\n 'info',\r\n `Order created (AWAITING_PAYMENT) — settle with 'flight-flink pay-order --order-no ${d.order_no ?? '<order_no>'}'.`,\r\n ),\r\n ].join('\\n\\n'),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { PayFlightOrderResponse } from '../types/flight.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { PRICE_ANNOTATION_FLAGS, applyPriceAnnotation } from '../price-annotation.js';\r\nimport { attachSchemaHelp, flightPayOrderSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/**\r\n * `flight-flink pay-order` — settle a created order by --order-no (triggers upstream\r\n * ticketing). AWAITING_PAYMENT → PAID. Non-`--yes` path confirms before the write.\r\n */\r\nexport function registerPayOrderCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('pay-order')\r\n .description('Settle a created order by --order-no (triggers ticketing)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference from create-order')\r\n .option('--payment-method-id <id>', 'Optional bound-card id to charge (pay_per_call only)')\r\n .option('--payment-token-id <id>', 'Optional network-token id (unionpay/visa charge path)')\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'Resume an EVO-card 3DS challenge: merchant trans id of an already-authorised preauth',\r\n )\r\n .option(\r\n '--authenticate',\r\n 'Opt-in to require cardholder 3DS on the network-token direct charge (--payment-token-id, EVO/Mastercard). When a step-up is needed the response is AUTHENTICATION_REQUIRED with three_ds_url + charge_no; resume with --authorized-charge-no. Default off = frictionless.',\r\n )\r\n .option(\r\n '--return-url <url>',\r\n 'Optional 3DS/passkey return URL for the network-token authenticate path (falls back to the platform EVO_3DS_RETURN_URL)',\r\n )\r\n .option(\r\n '--authorized-charge-no <no>',\r\n 'Resume a network-token 3DS challenge: charge_no returned by a prior AUTHENTICATION_REQUIRED response (settled via ChargeService.resume_token)',\r\n )\r\n .option(\r\n '--evo-explicit',\r\n '[方案 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side.',\r\n )\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header')\r\n .option(\r\n '--original-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['original-amount-cents'].description,\r\n )\r\n .option(\r\n '--discount-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['discount-amount-cents'].description,\r\n );\r\n attachSchemaHelp(cmd, flightPayOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const orderNo = need(opts.orderNo as string | undefined, 'order-no');\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Pay and ticket order ${orderNo}? This settles the order and issues tickets.`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Payment aborted by user.');\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink pay-order',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Paying flight order...');\r\n // 支付凭证在 pay 而非 create-order:平台侧 create-order 只锁座位/锁价、分文不碰钱,\r\n // 扣款发生在这一步。全部可选 —— 省略时平台按订单 billing_mode 自行分流(月结扣额度、\r\n // 现结选默认卡)。CLI 是薄透传层,不做必填校验。\r\n const body: Record<string, unknown> = {};\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n if (opts.authorizedMerchantTransId !== undefined) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 网络令牌支付时 3DS(opt-in):仅置位时透传 authenticate=true;return_url 可选(缺省平台\r\n // 回落 EVO_3DS_RETURN_URL);authorized_charge_no 是续付句柄。\r\n if (opts.authenticate) body.authenticate = true;\r\n if (opts.returnUrl !== undefined) body.return_url = opts.returnUrl as string;\r\n if (opts.authorizedChargeNo !== undefined) {\r\n body.authorized_charge_no = opts.authorizedChargeNo as string;\r\n }\r\n // 方案 B/R16 显式 EVO 选择信号:仅在置位时透传 evo_explicit=true;缺省则不发(平台默认 false)。\r\n if (opts.evoExplicit) body.evo_explicit = true;\r\n // 价格批注(原价 / 优惠,纯记录):落订单 auth_snapshot + 统一流水并在订单详情回显,\r\n // 不进网关报文、不参与权威价核验。\r\n applyPriceAnnotation(body, opts);\r\n const result = await deps.apiClient.post<PayFlightOrderResponse>(\r\n `/flight/${encodeURIComponent(orderNo)}/pay`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => {\r\n const rows: [string, string][] = [\r\n ['Order no', String(d.order_no ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Amount', `${d.amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ];\r\n // 网络令牌 3DS 挑战:透出续付句柄与挑战地址,供调用方打开认证页并回带续付。\r\n if (d.charge_no) rows.push(['Charge no', String(d.charge_no)]);\r\n if (d.three_ds_url) rows.push(['3DS URL', String(d.three_ds_url)]);\r\n return Formatter.keyValue(rows);\r\n });\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { GetFlightOrderResponse } from '../types/flight.js';\r\nimport { attachSchemaHelp, flightGetOrderSchema } from '../verb-schema.js';\r\nimport { type Deps, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\nconst TERMINAL = new Set(['TICKETED', 'CANCELLED', 'FAILED']);\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((r) => setTimeout(r, ms));\r\n}\r\n\r\n/**\r\n * `flight-flink get-order` — query order status by --order-no. Read-only. With\r\n * --watch, polls until a terminal status (TICKETED/CANCELLED/FAILED) or timeout,\r\n * emitting one NDJSON line per update.\r\n */\r\nexport function registerGetOrderCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('get-order')\r\n .description('Query a flight order status by id (poll ticketing 5→8)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--watch', 'Poll until a terminal status, one NDJSON line per update')\r\n .option('--watch-interval <seconds>', 'Seconds between polls', '5')\r\n .option('--watch-timeout <seconds>', 'Max seconds to poll', '600');\r\n attachSchemaHelp(cmd, flightGetOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const orderNo = need(opts.orderNo as string | undefined, 'order-no');\r\n const path = `/flight/${encodeURIComponent(orderNo)}/status`;\r\n const auth = { type: 'api-key' as const, key: apiKey };\r\n\r\n if (opts.watch) {\r\n const interval = num(opts.watchInterval as string | undefined, 'watch-interval') * 1000;\r\n const timeoutMs = num(opts.watchTimeout as string | undefined, 'watch-timeout') * 1000;\r\n const deadline = Date.now() + timeoutMs;\r\n for (;;) {\r\n const r = await deps.apiClient.get<GetFlightOrderResponse>(path, auth);\r\n if (!r.success) throw CliError.fromApi(r, { auth: 'api-key' });\r\n process.stdout.write(`${JSON.stringify(r.data)}\\n`);\r\n if (TERMINAL.has(String(r.data.status))) return;\r\n if (Date.now() + interval >= deadline) {\r\n process.stdout.write(`${JSON.stringify({ watch_status: 'timeout', order_no: orderNo })}\\n`);\r\n return;\r\n }\r\n await sleep(interval);\r\n }\r\n }\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching flight order status...');\r\n const result = await deps.apiClient.get<GetFlightOrderResponse>(path, auth);\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n Formatter.keyValue([\r\n ['Order no', String(d.order_no ?? '-')],\r\n ['Upstream order no', String(d.upstream_order_no ?? '-')],\r\n ['PNR', String(d.pnr ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Total amount', `${d.total_amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ]),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { CancelFlightResponse } from '../types/flight.js';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightCancelOrderSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/**\r\n * `flight-flink cancel-order` — cancel an un-ticketed order by --order-no (with\r\n * refund). A ticketed order is rejected upstream. Non-`--yes` path confirms first.\r\n */\r\nexport function registerCancelOrderCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('cancel-order')\r\n .description('Cancel an un-ticketed flight order (with refund)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--reason <text>', 'Optional cancellation reason')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightCancelOrderSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const orderNo = need(opts.orderNo as string | undefined, 'order-no');\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Cancel order ${orderNo}? This requests cancellation and a refund.`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Cancellation aborted by user.');\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink cancel-order',\r\n });\r\n\r\n const body: Record<string, unknown> = {};\r\n if (opts.reason !== undefined) body.reason = opts.reason as string;\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Cancelling flight order...');\r\n const result = await deps.apiClient.post<CancelFlightResponse>(\r\n `/flight/${encodeURIComponent(orderNo)}/cancel`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) =>\r\n Formatter.keyValue([\r\n ['Order no', String(d.order_no ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Refund amount', `${d.refund_amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ]),\r\n );\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport type { ListFlightOrdersResponse } from '../types/flight.js';\r\nimport { attachSchemaHelp, flightListOrdersSchema } from '../verb-schema.js';\r\nimport { MEMBER_OPTION_DESCRIPTION, memberIdOf } from '../member.js';\r\nimport { type Deps, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink list-orders` — list the developer's flight orders (local read). */\r\nexport function registerListOrdersCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-orders')\r\n .description(\"List the developer's flight orders (local read, no upstream call)\")\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--status <status>', 'Optional status filter')\r\n .option('--page <n>', 'Page (1-based)', '1')\r\n .option('--page-size <n>', 'Items per page (1-100)', '20')\r\n .option('--member <id>', MEMBER_OPTION_DESCRIPTION);\r\n attachSchemaHelp(cmd, flightListOrdersSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const params = new URLSearchParams();\r\n if (opts.status !== undefined) params.set('status', opts.status as string);\r\n const member = memberIdOf(opts);\r\n if (member !== undefined) params.set('member_id', member);\r\n params.set('page', String(num(opts.page as string | undefined, 'page')));\r\n params.set('page_size', String(num(opts.pageSize as string | undefined, 'page-size')));\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching flight orders...');\r\n const result = await deps.apiClient.get<ListFlightOrdersResponse>(\r\n `/flight/orders?${params.toString()}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => {\r\n const rows = (d.orders ?? []).map((o) => [\r\n String(o.order_no ?? '-'),\r\n String(o.status ?? '-'),\r\n `${o.total_amount ?? '-'} ${o.currency ?? ''}`.trim(),\r\n ]);\r\n return Formatter.table(['Order no', 'Status', 'Amount'], rows);\r\n });\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightChangeSearchSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink change-search` — search rebook-eligible flights for an order. */\r\nexport function registerChangeSearchCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-search')\r\n .description('Search rebook-eligible flights for an order')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--date <date>', 'Target change date YYYY-MM-DD')\r\n .option('--passenger <code>', 'passengerCode')\r\n .option('--segment-id <ids>', 'Comma-separated segment ids')\r\n .option('--cabin-class <c>', 'Cabin class', 'economy');\r\n attachSchemaHelp(cmd, flightChangeSearchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body = {\r\n order_no: need(opts.orderNo as string | undefined, 'order-no'),\r\n date: need(opts.date as string | undefined, 'date'),\r\n passenger: need(opts.passenger as string | undefined, 'passenger'),\r\n segment_id: need(opts.segmentId as string | undefined, 'segment-id'),\r\n cabin_class: opts.cabinClass as string,\r\n };\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Searching change options...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/change/search',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightChangeApplySchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink change-apply` — submit a change request (pending review). */\r\nexport function registerChangeApplyCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-apply')\r\n .description('Submit a change request (returns change_order_no, pending review)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--passenger <code>', 'passengerCode')\r\n .option('--segment-id <ids>', 'Comma-separated segment ids')\r\n .option('--product-token <token>', 'Change priceKey token')\r\n .option('--contact-name <name>', 'Contact name')\r\n .option('--contact-region <code>', 'Contact region')\r\n .option('--contact-phone <phone>', 'Contact phone')\r\n .option('--contact-email <email>', 'Contact email')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightChangeApplySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body = {\r\n order_no: need(opts.orderNo as string | undefined, 'order-no'),\r\n passenger: need(opts.passenger as string | undefined, 'passenger'),\r\n segment_id: need(opts.segmentId as string | undefined, 'segment-id'),\r\n product_token: need(opts.productToken as string | undefined, 'product-token'),\r\n contact_name: need(opts.contactName as string | undefined, 'contact-name'),\r\n contact_region: need(opts.contactRegion as string | undefined, 'contact-region'),\r\n contact_phone: need(opts.contactPhone as string | undefined, 'contact-phone'),\r\n contact_email: need(opts.contactEmail as string | undefined, 'contact-email'),\r\n };\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Submit a change request for order ${body.order_no}?`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Change request aborted by user.');\r\n }\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink change-apply',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Submitting change request...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/change/apply',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightChangeDetailSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink change-detail` — change request detail by --change-order-no. */\r\nexport function registerChangeDetailCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-detail')\r\n .description('Change request detail by change order number')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--change-order-no <id>', 'Change order number');\r\n attachSchemaHelp(cmd, flightChangeDetailSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const changeOrderNo = need(opts.changeOrderNo as string | undefined, 'change-order-no');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching change detail...');\r\n const result = await deps.apiClient.get<Record<string, unknown>>(\r\n `/flight/change/${encodeURIComponent(changeOrderNo)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightChangeCancelSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink change-cancel` — cancel a change request (immediate terminal). */\r\nexport function registerChangeCancelCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-cancel')\r\n .description('Cancel a change request (immediate terminal)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--change-order-no <id>', 'Change order number')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightChangeCancelSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const changeOrderNo = need(opts.changeOrderNo as string | undefined, 'change-order-no');\r\n\r\n if (!isYes) {\r\n const ok = await confirm({ message: `Cancel change request ${changeOrderNo}?`, default: false });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Change cancellation aborted by user.');\r\n }\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink change-cancel',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Cancelling change request...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n `/flight/change/${encodeURIComponent(changeOrderNo)}/cancel`,\r\n { type: 'api-key', key: apiKey },\r\n {},\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, Formatter, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { PRICE_ANNOTATION_FLAGS, applyPriceAnnotation } from '../price-annotation.js';\r\nimport { attachSchemaHelp, flightChangePaySchema } from '../verb-schema.js';\r\nimport { type Deps, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/**\r\n * `flight-flink change-pay` — pay a change request's fee and trigger upstream change\r\n * ticketing. Charges the change fee like a normal order (UPI network-token when\r\n * --payment-token-id is given, else EVO), then calls flink pay(type=1) for the change\r\n * order. Calls POST /flight/change/{change_order_no}/pay with an Idempotency-Key header.\r\n * Non-`--yes` path confirms (restating amount) before the write.\r\n * --authorized-merchant-trans-id re-enters this verb after a 3DS challenge: no second\r\n * authorization is made — the platform reuses the already-authorised preauth, captures it\r\n * and finishes ticketing.\r\n */\r\nexport function registerChangePayCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('change-pay')\r\n .description('Pay a change request fee (like a normal order) and trigger change ticketing')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--change-order-no <id>', 'Change order number')\r\n .option('--order-no <id>', 'Original order reference (ownership check)')\r\n .option('--amount <amount>', 'Change fee total in decimal units (change-detail price_total)')\r\n .option('--currency <currency>', 'ISO 4217 currency code', 'USD')\r\n .option('--payment-method-id <id>', 'Optional bound-card id (EVO path)')\r\n .option('--payment-token-id <id>', 'Optional UPI network-token id (unionpay charge path)')\r\n .option(\r\n '--authorized-merchant-trans-id <id>',\r\n 'Resume a 3DS challenge: merchant trans id of the already-authorised preauth',\r\n )\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header')\r\n .option(\r\n '--original-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['original-amount-cents'].description,\r\n )\r\n .option(\r\n '--discount-amount-cents <cents>',\r\n PRICE_ANNOTATION_FLAGS['discount-amount-cents'].description,\r\n );\r\n attachSchemaHelp(cmd, flightChangePaySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const changeOrderNo = need(opts.changeOrderNo as string | undefined, 'change-order-no');\r\n const orderNo = need(opts.orderNo as string | undefined, 'order-no');\r\n const amount = num(opts.amount as string | undefined, 'amount');\r\n const currency = need(opts.currency as string | undefined, 'currency');\r\n const body: Record<string, unknown> = {\r\n order_no: orderNo,\r\n amount,\r\n currency,\r\n };\r\n if (opts.paymentMethodId !== undefined) body.payment_method_id = opts.paymentMethodId as string;\r\n // UPI(unionpay) 扣款路径:透传已 ACTIVE 的 network token id;platform change-pay\r\n // 据 payment_token_id 非空走 ChargeService 实扣(跳过 EVO 预授权/捕获)。\r\n if (opts.paymentTokenId !== undefined) body.payment_token_id = opts.paymentTokenId as string;\r\n // 3DS 挑战续付凭证:改签费现结走 EVO 预授权 + 捕获。预授权遇 EVO 要求持卡人认证时资金\r\n // 尚未冻结,平台返回挑战;前端带用户认证完成后用这个参数重入 change-pay,平台复用那笔\r\n // 已认证通过的预授权再 capture,不再新发起一次授权(否则每轮都在卡上多冻结一笔)。\r\n if (opts.authorizedMerchantTransId !== undefined) {\r\n body.authorized_merchant_trans_id = opts.authorizedMerchantTransId as string;\r\n }\r\n // 价格批注(原价 / 优惠,纯记录):改签扣款额仍是上游权威 price_total,这两个值只落\r\n // 改签单的 payment_snapshot + 统一流水,不进网关报文、不参与那道权威价交叉校验。\r\n applyPriceAnnotation(body, opts);\r\n\r\n if (!isYes) {\r\n // 续单路径上钱已经扣过了,别再跟操作员说「charges the customer」。\r\n const isResume = opts.authorizedMerchantTransId !== undefined;\r\n const message = isResume\r\n ? `Resume change fee ${amount} ${currency} for change order ${changeOrderNo}? The card is already authorised; this captures it and triggers change ticketing.`\r\n : `Pay change fee ${amount} ${currency} for change order ${changeOrderNo}? This charges the customer and triggers change ticketing.`;\r\n const ok = await confirm({ message, default: false });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Change payment aborted by user.');\r\n }\r\n\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink change-pay',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Paying change request...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n `/flight/change/${encodeURIComponent(changeOrderNo)}/pay`,\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => {\r\n // 3DS 挑战:平台把它放在 `challenge` 键下(内含自己的 `status`),顶层没有\r\n // payment_status。照原样按已扣款渲染会打出一张几乎全是 '-' 的表,并且告诉操作员\r\n // 「Change fee charged」——而这笔连预授权都还没冻结成功。\r\n const challenge = (d.challenge ?? null) as Record<string, unknown> | null;\r\n if (challenge) {\r\n return [\r\n Formatter.keyValue([\r\n ['Change order no', String(challenge.change_order_no ?? '-')],\r\n ['Status', String(challenge.status ?? '-')],\r\n ['Amount', `${challenge.amount ?? '-'} ${challenge.currency ?? ''}`.trim()],\r\n ['Authentication URL', String(challenge.three_ds_url ?? '-')],\r\n ['Merchant trans id', String(challenge.merchant_trans_id ?? '-')],\r\n ]),\r\n Formatter.status(\r\n 'warning',\r\n 'Not charged yet — the card requires 3-D Secure and the funds are not held. '\r\n + 'Open the authentication URL, then re-run change-pay with '\r\n + '--authorized-merchant-trans-id <merchant trans id>.',\r\n ),\r\n ].join('\\n\\n');\r\n }\r\n return [\r\n Formatter.keyValue([\r\n ['Change order no', String(d.change_order_no ?? '-')],\r\n ['Status', String(d.status ?? '-')],\r\n ['Amount', `${d.amount ?? '-'} ${d.currency ?? ''}`.trim()],\r\n ['Payment status', String(d.payment_status ?? '-')],\r\n ]),\r\n Formatter.status('info', 'Change fee charged; change ticketing triggered. Poll change-detail until SUCCESS.'),\r\n ].join('\\n\\n');\r\n });\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightRefundApplySchema } from '../verb-schema.js';\r\nimport { type Deps, need, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink refund-apply` — submit a refund request (pending review). */\r\nexport function registerRefundApplyCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('refund-apply')\r\n .description('Submit a refund request (returns refund_order_no, pending review)')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--order-no <id>', 'Our order reference')\r\n .option('--passenger <code>', 'passengerCode')\r\n .option('--segment-id <ids>', 'Comma-separated segment ids')\r\n .option('--reason-type <n>', 'Refund reason type code')\r\n .option('--reason <text>', 'Free-text reason')\r\n .option('--contact-name <name>', 'Contact name')\r\n .option('--contact-region <code>', 'Contact region')\r\n .option('--contact-phone <phone>', 'Contact phone')\r\n .option('--contact-email <email>', 'Contact email')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightRefundApplySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const body: Record<string, unknown> = {\r\n order_no: need(opts.orderNo as string | undefined, 'order-no'),\r\n passenger: need(opts.passenger as string | undefined, 'passenger'),\r\n segment_id: need(opts.segmentId as string | undefined, 'segment-id'),\r\n reason_type: num(opts.reasonType as string | undefined, 'reason-type'),\r\n contact_name: need(opts.contactName as string | undefined, 'contact-name'),\r\n contact_region: need(opts.contactRegion as string | undefined, 'contact-region'),\r\n contact_phone: need(opts.contactPhone as string | undefined, 'contact-phone'),\r\n contact_email: need(opts.contactEmail as string | undefined, 'contact-email'),\r\n };\r\n if (opts.reason !== undefined) body.reason = opts.reason as string;\r\n\r\n if (!isYes) {\r\n const ok = await confirm({\r\n message: `Submit a refund request for order ${body.order_no}?`,\r\n default: false,\r\n });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Refund request aborted by user.');\r\n }\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink refund-apply',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Submitting refund request...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/flight/refund/apply',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, flightRefundDetailSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink refund-detail` — refund request detail by --refund-order-no. */\r\nexport function registerRefundDetailCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('refund-detail')\r\n .description('Refund request detail by refund order number')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--refund-order-no <id>', 'Refund order number');\r\n attachSchemaHelp(cmd, flightRefundDetailSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const refundOrderNo = need(opts.refundOrderNo as string | undefined, 'refund-order-no');\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching refund detail...');\r\n const result = await deps.apiClient.get<Record<string, unknown>>(\r\n `/flight/refund/${encodeURIComponent(refundOrderNo)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { confirm } from '@inquirer/prompts';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { resolveIdempotencyKey } from '../idempotency.js';\r\nimport { attachSchemaHelp, flightRefundConfirmSchema } from '../verb-schema.js';\r\nimport { type Deps, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `flight-flink refund-confirm` — confirm (\"1\") or cancel (\"2\") a refund. */\r\nexport function registerRefundConfirmCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('refund-confirm')\r\n .description('Confirm (\"1\") or cancel (\"2\") a refund')\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--refund-order-no <id>', 'Refund order number')\r\n .option('--confirm <flag>', '\"1\" confirm / \"2\" cancel')\r\n .option('--idempotency-key <key>', 'Forwarded verbatim as the Idempotency-Key header');\r\n attachSchemaHelp(cmd, flightRefundConfirmSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const isYes = Boolean(opts.yes);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n const refundOrderNo = need(opts.refundOrderNo as string | undefined, 'refund-order-no');\r\n const confirmFlag = need(opts.confirm as string | undefined, 'confirm');\r\n if (confirmFlag !== '1' && confirmFlag !== '2') {\r\n throw new CliError('PARAM_INVALID', '--confirm must be \"1\" (confirm) or \"2\" (cancel).');\r\n }\r\n\r\n if (!isYes) {\r\n const action = confirmFlag === '1' ? 'confirm' : 'cancel';\r\n const ok = await confirm({ message: `${action} refund ${refundOrderNo}?`, default: false });\r\n if (!ok) throw new CliError('CLIENT_ABORTED', 'Refund confirmation aborted by user.');\r\n }\r\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\r\n yes: isYes,\r\n commandPath: 'flight-flink refund-confirm',\r\n });\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Processing refund confirmation...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n `/flight/refund/${encodeURIComponent(refundOrderNo)}/confirm`,\r\n { type: 'api-key', key: apiKey },\r\n { confirm: confirmFlag },\r\n { 'Idempotency-Key': idempotencyKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\n\r\nconst SKILL_TEXT = `\r\n---\r\nname: flight-flink\r\ndescription: Search, book, and manage international flight reservations. Two-step create-then-pay ticketing with journeyId relay for round-trip/multi-city, plus change (rebooking) and refund flows. Use when the user wants to find flights, verify a fare, book a ticket, or view/cancel/change/refund an existing flight order. Not for hotels or rides.\r\n---\r\n\r\n# flight-flink — Agent Skill\r\n\r\nYou orchestrate flight bookings through CLI verbs. This guide covers HOW to chain\r\nverbs and pass data between them. For exact flags and field types, read the schema\r\n(\\`flight-flink <verb> --help --format json\\`).\r\n\r\n## Prerequisites\r\n- API key with merchant scope. Pass --api-key <key> --format json on every call; add --yes on writes.\r\n- Billing is decided server-side by the developer's billing_mode (monthly_settlement or pay_per_call).\r\n\r\n## Workflow (book)\r\n1. find-airport --keyword \"<place>\" → resolve to IATA city/airport codes\r\n2. search --trip-type <1|2|3> --journeys '<json>'\r\n - journeys ALWAYS carries ALL legs, on every call including relay calls.\r\n - Round-trip/multi-city: keep searching until is_final_leg is true. Each round, present the\r\n candidates, let the USER pick one, and pass THAT candidate's next_journey_ids verbatim as\r\n --journey-id on the next search. Never assemble the list yourself (the top-level journey_ids\r\n is flattened across all candidates) and never send more ids than there are legs — it is\r\n rejected, because upstream would otherwise silently answer with the FIRST leg's candidates.\r\n - Only offers where price_key_ready is true carry a real product_token. Earlier-leg candidates\r\n are NOT bare flight rows: total_sale_price is already the WHOLE-TRIP total and\r\n paired_segment_ids names the legs upstream paired with it, so you can show the full\r\n itinerary and real total from the first round — they just are not bookable yet.\r\n - A relay search returning ZERO offers means the journey ids went stale OR that leg sold out\r\n (upstream reports both as an empty list). Restart from leg 1 for fresh ids.\r\n - Code<->type consistency: tag each code with its matching type — an AIRPORT code (e.g. NRT)\r\n uses type 2, a CITY code (e.g. TYO) uses type 1. Mislabeling (e.g. NRT with type 1, since NRT\r\n is an airport whose city is TYO) is rejected with code 400 \"destination not exist\".\r\n find-airport returns the correct type per candidate (city hit → type 1 with children airports;\r\n airport hit → type 2) — pass code + type together verbatim.\r\n3. verify --product-token <token from search>\r\n - Returns the authoritative product_token + price_changed. If price_changed, re-confirm\r\n the new price with the user before booking. Pass the RETURNED token to create-order.\r\n4. create-order --product-token <verify token> --total-amount <verify total> --currency <cur>\r\n --contact-* --passengers '<json>' --idempotency-key <k>\r\n - Locks the fare, NO charge. Order status → AWAITING_PAYMENT. Save order_no.\r\n - passengers: gender/id_type are STRINGS (\"1\"/\"2\"); child/infant require adult_passenger_name.\r\n5. pay-order --order-no <order_no> --idempotency-key <k>\r\n - Settles + triggers ticketing. Status → PAID.\r\n6. get-order --order-no <order_no> [--watch]\r\n - Ticketing is asynchronous. Poll until TICKETED (ticket_infos populated). Do NOT\r\n report success before TICKETED. Single-passenger orders ticket in ~100-110s;\r\n multi-passenger orders (adult+child+infant) take longer (150s+) — widen --watch-timeout\r\n for multi-passenger bookings; still TICKETING past 150s is normal, not a failure.\r\n\r\n## Change (rebooking)\r\n- change-search → change-apply (returns change_order_no) → change-detail\r\n- Confirm branch: pay-order the change order (settlement). Cancel branch: change-cancel.\r\n\r\n## Refund\r\n- refund-apply (returns refund_order_no) → refund-detail → refund-confirm --confirm 1 (confirm)\r\n or --confirm 2 (cancel). Cancel takes effect immediately.\r\n\r\n## Cancel (un-ticketed order)\r\n- cancel-order --order-no <order_no> --idempotency-key <k> → CANCELLED + refund.\r\n A ticketed order is rejected upstream — use refund-apply instead.\r\n\r\n## Data passing\r\n- product_token : search → verify → create-order (opaque; never fabricate or edit; verify's token wins)\r\n- order_no : create-order → pay-order / get-order / cancel-order\r\n- next_journey_ids : chosen offer → next search's --journey-id (relay for round-trip/multi-city)\r\n- change_order_no / refund_order_no : *-apply → *-detail / *-confirm / pay-order (change)\r\n\r\n## Invariants\r\n- Never create-order without a fresh verify (tokens/prices change).\r\n- Never claim \"booked\" until get-order returns TICKETED.\r\n- create-order and pay-order are separate steps; create-order does NOT charge.\r\n- Write verbs (create-order/pay-order/cancel-order/change-apply/change-cancel/refund-apply/\r\n refund-confirm) always need --idempotency-key; reuse the SAME key when retrying the same intent.\r\n- --yes only skips this CLI's interactive prompt (for non-interactive Agents); it does NOT\r\n remove the requirement to confirm the flight/fare/price with the user in the chat UI.\r\n\r\n## Errors\r\n- INVALID_ARGUMENT → bad argument; run <verb> --help and correct it.\r\n- PRICE_CHANGED → price changed since verify; re-verify and confirm the new price.\r\n- ORDER_CREATE_FAILED → upstream create failed; funds released. Safe to retry with same key.\r\n- PAYMENT_FAILED → settlement/payment failed; check balance/method and retry.\r\n- NOT_FOUND → no such order for this key/owner. Do NOT retry blindly.\r\n- IDEMPOTENCY_CONFLICT → same key reused with different params; use a fresh key.\r\n- UPSTREAM_ERROR → transient; retry once after a short wait.\r\n`.trim();\r\n\r\n/** \\`flight-flink skill\\` — print the usage guide for AI Agents (read-only). */\r\nexport function registerFlightSkillCommand(parent: Command): void {\r\n parent\r\n .command('skill')\r\n .description('Print the flight-flink usage guide (orchestration flow, data passing, rules)')\r\n .action(() => {\r\n console.log(SKILL_TEXT);\r\n });\r\n}\r\n","/**\r\n * Shared input/output helpers for the data-aisa command group.\r\n *\r\n * Mirrors the flight-flink / hotel-redaug conventions: required-flag validation\r\n * maps to `PARAM_INVALID` (catalog code, exit 1); JSON flags are parsed +\r\n * shape-checked before any request; results render via renderWithContext.\r\n *\r\n * This group is READ-ONLY and fully non-interactive by design: the only prompt\r\n * form allowed here is `resolveApiKey` (and even that returns immediately when\r\n * the flag is present, which is how the orchestrator always drives the CLI).\r\n */\r\nimport { CliError, Formatter, PromptEngine } from '@agenzo/cli-core';\r\nimport type { ApiClient, CommandResult } from '@agenzo/cli-core';\r\nimport { ConfigManager, resolveFormat, renderWithContext } from '@agenzo/cli-core';\r\nimport { IDEMPOTENCY_KEY_PATTERN, IDEMPOTENCY_KEY_RULE } from '../idempotency.js';\r\n\r\nexport type Deps = { apiClient: ApiClient };\r\n\r\n/** Require a flag value; missing → PARAM_INVALID. */\r\nexport function need(value: string | undefined, flag: string): string {\r\n if (value === undefined) {\r\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Parse a numeric flag; non-number → PARAM_INVALID. */\r\nexport function num(value: string | undefined, flag: string): number {\r\n const n = Number(need(value, flag));\r\n if (!Number.isFinite(n)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\r\n }\r\n return n;\r\n}\r\n\r\n/** Parse a JSON-object flag; non-JSON / non-object / array → PARAM_INVALID. Returned verbatim. */\r\nexport function jsonObject(raw: string, flag: string): Record<string, unknown> {\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a JSON object.`);\r\n }\r\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\r\n throw new CliError('PARAM_INVALID', `--${flag} must be a JSON object.`);\r\n }\r\n return parsed as Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Validate an idempotency key and return it VERBATIM (R36): the raw flag value\r\n * itself must match the §6.1 format `[A-Za-z0-9_-]{1,128}`, and whatever passes\r\n * is forwarded byte-for-byte as the `Idempotency-Key` header.\r\n *\r\n * Deliberately not the write verbs' `normalizeIdempotencyKey`: that one trims\r\n * first, so ` k-1 ` would pass and go out as `k-1`. Here surrounding whitespace\r\n * is a malformed key → `PARAM_INVALID`, never a silent correction. The write\r\n * commands keep their own behavior untouched; only the pattern/rule constants\r\n * are shared so the format stays single-sourced.\r\n */\r\nexport function verbatimIdempotencyKey(raw: string, flag: string): string {\r\n if (!IDEMPOTENCY_KEY_PATTERN.test(raw)) {\r\n throw new CliError(\r\n 'PARAM_INVALID',\r\n `Invalid --${flag}: \"${raw}\". ${IDEMPOTENCY_KEY_RULE}`,\r\n );\r\n }\r\n return raw;\r\n}\r\n\r\n/** Resolve the API key (flag or interactive password prompt). */\r\nexport function resolveApiKey(flag: string | undefined): Promise<string> {\r\n return PromptEngine.resolveInput(flag, { message: 'API Key:', type: 'password' });\r\n}\r\n\r\n/** Render a success result: JSON envelope in json mode, pretty text otherwise. */\r\nexport async function render<T>(\r\n data: T,\r\n format: string | undefined,\r\n text: (d: T) => string,\r\n): Promise<void> {\r\n const resolved = resolveFormat(format);\r\n const result: CommandResult<T> = { data, text: () => text(data) };\r\n await renderWithContext(result, { format: resolved }, new ConfigManager());\r\n}\r\n\r\n/** Compact key/value renderer for arbitrary record data. */\r\nexport function kv(data: Record<string, unknown>): string {\r\n const lines: [string, string][] = Object.entries(data).map(([k, v]) => [\r\n k,\r\n typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v ?? '-'),\r\n ]);\r\n return Formatter.keyValue(lines);\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, dataListCategoriesSchema } from '../verb-schema.js';\r\nimport { type Deps, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `data-aisa list-categories` — the data categories and how many capabilities each holds. */\r\nexport function registerDataListCategoriesCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('list-categories')\r\n .description(\r\n 'List the data categories and how many capabilities each one holds. Free (answered from the bundled index, no upstream call), read-only.',\r\n )\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\r\n attachSchemaHelp(cmd, dataListCategoriesSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching data categories...');\r\n const result = await deps.apiClient.get<Record<string, unknown>>('/data/categories', {\r\n type: 'api-key',\r\n key: apiKey,\r\n });\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, dataSearchSchema } from '../verb-schema.js';\r\nimport { type Deps, num, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `data-aisa search` — find a data capability by keyword (free, read-only). */\r\nexport function registerDataSearchCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('search')\r\n .description(\r\n 'Find a data capability by keyword. Free (answered from the bundled index, no upstream call), read-only. Returns operationId + method + path + tags + summary + price_usd for each hit.',\r\n )\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option(\r\n '--keyword <kw>',\r\n \"What to look for, e.g. 'crypto price' or 'reddit'. Space- or comma-separated tokens; omitted returns the first --limit capabilities as examples.\",\r\n )\r\n .option('--limit <n>', 'How many hits to return (1-50)', '15');\r\n attachSchemaHelp(cmd, dataSearchSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n // ApiClient.get takes Record<string,string>, so every query param is\r\n // stringified here. `--keyword` has no default: it is only sent when given.\r\n // `--limit` carries commander's '15' default, so it is always sent.\r\n const params: Record<string, string> = {};\r\n if (opts.keyword !== undefined) params.keyword = String(opts.keyword);\r\n if (opts.limit !== undefined) {\r\n params.limit = String(num(opts.limit as string | undefined, 'limit'));\r\n }\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Searching data capabilities...');\r\n const result = await deps.apiClient.get<Record<string, unknown>>(\r\n '/data/search',\r\n { type: 'api-key', key: apiKey },\r\n params,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => JSON.stringify(d, null, 2));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, dataDescribeSchema } from '../verb-schema.js';\r\nimport { type Deps, kv, need, render, resolveApiKey } from './_helpers.js';\r\n\r\n/** `data-aisa describe` — one capability's parameter spec + unit price (free, read-only). */\r\nexport function registerDataDescribeCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('describe')\r\n .description(\r\n \"Read one capability's parameter spec, usage hint and unit price before calling it. Free (answered from the bundled index, no upstream call), read-only.\",\r\n )\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--operation-id <id>', 'Which capability to describe — an operationId returned by search, verbatim');\r\n attachSchemaHelp(cmd, dataDescribeSchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const operationId = need(opts.operationId as string | undefined, 'operation-id');\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching capability spec...');\r\n const result = await deps.apiClient.get<Record<string, unknown>>(\r\n `/data/describe/${encodeURIComponent(operationId)}`,\r\n { type: 'api-key', key: apiKey },\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => kv(d));\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { CliError, createSpinner, resolveFormat } from '@agenzo/cli-core';\r\nimport { attachSchemaHelp, dataQuerySchema } from '../verb-schema.js';\r\nimport {\r\n type Deps,\r\n jsonObject,\r\n kv,\r\n need,\r\n render,\r\n resolveApiKey,\r\n verbatimIdempotencyKey,\r\n} from './_helpers.js';\r\n\r\n/**\r\n * `data-aisa query` — run one capability and return its data. Charged per call,\r\n * READ-ONLY: it fetches data and nothing else.\r\n *\r\n * `--idempotency-key` is OPTIONAL here (unlike the write verbs of the booking\r\n * groups): when it is absent the header is simply not sent and the request goes\r\n * out as usual — no prompt, no error, and the CLI never generates a key. That is\r\n * why this command deliberately uses neither the write-verb key resolver nor its\r\n * trimming normalizer, but `verbatimIdempotencyKey`: the value given must itself\r\n * match the format and is forwarded byte-for-byte (R36).\r\n */\r\nexport function registerDataQueryCommand(parent: Command, deps: Deps): void {\r\n const cmd = parent\r\n .command('query')\r\n .description(\r\n 'Run one capability and return its data. Charged per call. READ-ONLY: it fetches data and nothing else.',\r\n )\r\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\r\n .option('--operation-id <id>', 'Which capability to run — an operationId returned by search, verbatim')\r\n .option(\r\n '--params <json>',\r\n \"The capability's parameters as a JSON object keyed by the parameter names from describe. Passed through as a whole; unknown keys are dropped.\",\r\n )\r\n .option(\r\n '--idempotency-key <key>',\r\n 'Optional de-duplication key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated, and omitting it is fine',\r\n );\r\n attachSchemaHelp(cmd, dataQuerySchema);\r\n\r\n cmd.action(async () => {\r\n const opts = cmd.optsWithGlobals();\r\n const format = resolveFormat(opts.format as string | undefined);\r\n const operationId = need(opts.operationId as string | undefined, 'operation-id');\r\n\r\n const body: Record<string, unknown> = { operation_id: operationId };\r\n // The parsed object goes into the body verbatim — never stringified and\r\n // never rewritten field by field.\r\n if (opts.params !== undefined) {\r\n body.params = jsonObject(opts.params as string, 'params');\r\n }\r\n\r\n let idempotencyKey: string | undefined;\r\n if (opts.idempotencyKey !== undefined) {\r\n // Validated as given, never trimmed/rewritten: a key that does not match\r\n // the format is PARAM_INVALID instead of being silently corrected.\r\n idempotencyKey = verbatimIdempotencyKey(opts.idempotencyKey as string, 'idempotency-key');\r\n }\r\n // Header only — the key never enters the request body.\r\n const extraHeaders = idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : undefined;\r\n\r\n const apiKey = await resolveApiKey(opts.apiKey as string | undefined);\r\n\r\n const spinner = format === 'json' ? null : createSpinner('Fetching data...');\r\n const result = await deps.apiClient.post<Record<string, unknown>>(\r\n '/data/query',\r\n { type: 'api-key', key: apiKey },\r\n body,\r\n extraHeaders,\r\n );\r\n spinner?.stop();\r\n if (!result.success) throw CliError.fromApi(result, { auth: 'api-key' });\r\n await render(result.data, opts.format as string | undefined, (d) => kv(d));\r\n });\r\n}\r\n"],"mappings":"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","names":["readFile","writeFile","mkdir","chmod","join","homedir","join","homedir","mkdir","chmod","readFile","writeFile","render","need","num","confirm","need","num","phone","seatCount","confirm","confirm","need","confirm","need","phone","confirm","need","confirm","confirm","need","num","confirm","need","need","render","DEFAULT_PAGE","DEFAULT_PAGE_SIZE","positiveInt","formatOrders","confirm","need","confirm","need","num","positiveInt","need","num","YMD_RE","stayDate","formatQuote","confirm","need","num","YMD_RE","stayDate","formatCreateOrder","confirm","confirm","DEFAULT_WATCH_TIMEOUT_SECONDS","formatPayOrder","confirm","need","formatGetOrder","phone","DEFAULT_WATCH_TIMEOUT_SECONDS","need","formatCancel","confirm","need","num","confirm","need","DEFAULT_WATCH_TIMEOUT_SECONDS","DEFAULT_PAGE","DEFAULT_PAGE_SIZE","positiveInt","formatOrders","need","need","num","coord","need","need","need","num","render","need","render","num","render","num","render","render","num","need","render","need","render","need","num","render","confirm","need","num","confirm","render","confirm","need","confirm","render","need","num","render","confirm","need","confirm","render","registerListOrdersCommand","num","render","need","render","confirm","need","confirm","render","need","render","confirm","need","confirm","render","confirm","need","num","confirm","render","confirm","need","num","confirm","render","need","render","confirm","need","confirm","render","SKILL_TEXT","need","num","resolveApiKey","render","resolveApiKey","render","resolveApiKey","num","render","need","resolveApiKey","render","need","resolveApiKey","render","registerListOrdersCommand"]}