@agenzo/merchant-cli 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +21 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -143,7 +143,7 @@ agenzo-merchant-cli ride-elife cancel --api-key "$API_KEY" --yes \
|
|
|
143
143
|
|
|
144
144
|
merchant-cli **没有任何 host / config 命令**,不治理环境。它复用 `@agenzo/cli-core` 的 `ConfigManager` 默认配置(即 `agenzo-admin-cli` 统一治理的环境,默认落盘 `~/.agenzo-admin-cli/`):
|
|
145
145
|
|
|
146
|
-
- 为 `ApiClient` 提供 `baseUrl`(host + `/api/
|
|
146
|
+
- 为 `ApiClient` 提供 `baseUrl`(host + `/api/merchant/v1`)。
|
|
147
147
|
- 为 json 输出的 `profile` / `endpoint` 信封提供环境名 + host。
|
|
148
148
|
|
|
149
149
|
**环境治理(设置 host / 切换环境)归 `agenzo-admin-cli`**(`agenzo-admin-cli config set` / `set-host`)——与 `agenzo-token-cli` 一致。
|
package/dist/index.js
CHANGED
|
@@ -338,9 +338,9 @@ var ApiClient = class {
|
|
|
338
338
|
}
|
|
339
339
|
const code = responseBody.code;
|
|
340
340
|
const message = responseBody.message;
|
|
341
|
-
const data = responseBody.data;
|
|
342
341
|
if (response.ok && (!code || code === "0000")) {
|
|
343
|
-
const
|
|
342
|
+
const hasDataField = Object.prototype.hasOwnProperty.call(responseBody, "data");
|
|
343
|
+
const payload = hasDataField ? responseBody.data : responseBody;
|
|
344
344
|
return { success: true, data: payload, message };
|
|
345
345
|
}
|
|
346
346
|
const errorCode = code ? parseInt(code, 10) : 0;
|
|
@@ -410,11 +410,12 @@ var ApiClient = class {
|
|
|
410
410
|
return messages[status] ?? `Something went wrong (${status}). Please try again later.`;
|
|
411
411
|
}
|
|
412
412
|
};
|
|
413
|
+
var DEFAULT_API_PATH = "/api/admin/v1";
|
|
413
414
|
var DEFAULT_CONFIG = {
|
|
414
415
|
active_org: null,
|
|
415
416
|
active_developer_id: null,
|
|
416
417
|
api_host: "https://agent.everonet.com",
|
|
417
|
-
api_path:
|
|
418
|
+
api_path: DEFAULT_API_PATH
|
|
418
419
|
};
|
|
419
420
|
var BUILTIN_PROFILES = {
|
|
420
421
|
production: "https://agent.everonet.com",
|
|
@@ -436,6 +437,9 @@ function resolveApiHost(host) {
|
|
|
436
437
|
if (url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
|
|
437
438
|
return host;
|
|
438
439
|
}
|
|
440
|
+
if (url.protocol === "http:" && process.env.AGENZO_ALLOW_INSECURE_HOST === "1") {
|
|
441
|
+
return host;
|
|
442
|
+
}
|
|
439
443
|
throw new ValidationError(
|
|
440
444
|
`Insecure API host is not allowed: ${host}. Use HTTPS, except for localhost or 127.0.0.1.`
|
|
441
445
|
);
|
|
@@ -443,9 +447,20 @@ function resolveApiHost(host) {
|
|
|
443
447
|
var ConfigManager = class {
|
|
444
448
|
basePath;
|
|
445
449
|
configPath;
|
|
446
|
-
|
|
450
|
+
/**
|
|
451
|
+
* Product-line API prefix this CLI targets (e.g. /api/admin/v1,
|
|
452
|
+
* /api/token/v1). Injected per binary so the four CLIs share one api_host
|
|
453
|
+
* but route to different product lines. Overrides any persisted api_path.
|
|
454
|
+
*/
|
|
455
|
+
apiPath;
|
|
456
|
+
constructor(basePath, apiPath) {
|
|
447
457
|
this.basePath = basePath ?? join4(homedir3(), ".agenzo-admin-cli");
|
|
448
458
|
this.configPath = join4(this.basePath, "config.json");
|
|
459
|
+
this.apiPath = apiPath ?? DEFAULT_API_PATH;
|
|
460
|
+
}
|
|
461
|
+
/** The resolved product-line API prefix for this CLI (per-binary constant). */
|
|
462
|
+
getApiPath() {
|
|
463
|
+
return this.apiPath;
|
|
449
464
|
}
|
|
450
465
|
async ensureDirectories() {
|
|
451
466
|
await mkdir3(this.basePath, { recursive: true, mode: 448 });
|
|
@@ -506,7 +521,7 @@ var ConfigManager = class {
|
|
|
506
521
|
async getApiBaseUrl() {
|
|
507
522
|
const config = await this.load();
|
|
508
523
|
const host = resolveApiHost(config.api_host).replace(/\/+$/, "");
|
|
509
|
-
const path =
|
|
524
|
+
const path = this.apiPath.startsWith("/") ? this.apiPath : `/${this.apiPath}`;
|
|
510
525
|
return `${host}${path}`;
|
|
511
526
|
}
|
|
512
527
|
async setApiHost(host) {
|
|
@@ -1657,7 +1672,7 @@ function registerServiceGetCommand(parent) {
|
|
|
1657
1672
|
// src/index.ts
|
|
1658
1673
|
var programRef;
|
|
1659
1674
|
async function main() {
|
|
1660
|
-
const configManager = new ConfigManager();
|
|
1675
|
+
const configManager = new ConfigManager(void 0, "/api/merchant/v1");
|
|
1661
1676
|
await configManager.ensureDirectories();
|
|
1662
1677
|
const apiBaseUrl = await configManager.getApiBaseUrl();
|
|
1663
1678
|
const apiClient = new ApiClient({ baseUrl: apiBaseUrl });
|
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/ride-elife/watch.ts","../src/verb-schema.ts","../src/ride-elife/quote.ts","../src/ride-elife/book.ts","../src/idempotency.ts","../src/ride-elife/get.ts","../src/ride-elife/cancel.ts","../src/ride-elife/list-orders.ts","../src/services/registry.ts","../src/services/list.ts","../src/services/get.ts"],"sourcesContent":["import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n Formatter,\n CliError,\n UserCancelError,\n toErrorEnvelope,\n resolveFormat,\n type OutputFormat,\n exitCodeFor,\n getCurrentVersion,\n} from '@agenzo/cli-core';\n\n// ride-elife commands (injection-style register, D6)\nimport { registerQuoteCommand } from './ride-elife/quote.js';\nimport { registerBookCommand } from './ride-elife/book.js';\nimport { registerRideGetCommand } from './ride-elife/get.js';\nimport { registerCancelCommand } from './ride-elife/cancel.js';\nimport { registerListOrdersCommand } from './ride-elife/list-orders.js';\n\n// services commands (CLI-bundled registry, D4)\nimport { registerServicesListCommand } from './services/list.js';\nimport { registerServiceGetCommand } from './services/get.js';\n\n// Holds the parsed program so the top-level error handler can read the\n// resolved `--format` global flag. Assigned inside `main()` once the program\n// is constructed; may be undefined if an error is thrown before then.\nlet programRef: Command | undefined;\n\nasync function main() {\n // Instantiate shared infrastructure. merchant-cli authenticates per-command\n // via `--api-key` (X-Api-Key); there is no Bearer session / AuthService /\n // keystore. The no-arg ConfigManager reuses cli-core's default config (the\n // environment admin-cli governs) purely to supply the ApiClient baseUrl and\n // the json envelope's profile/endpoint — merchant-cli exposes no host\n // commands of its own.\n const configManager = new ConfigManager();\n await configManager.ensureDirectories();\n\n const apiBaseUrl = await configManager.getApiBaseUrl();\n const apiClient = new ApiClient({ baseUrl: apiBaseUrl });\n\n // Shared deps object for networked commands — API Key is supplied per-command\n // (or interactively), so commands only need the HTTP client.\n const deps = { apiClient };\n\n // Create program\n const program = new Command();\n programRef = program;\n program\n .name('agenzo-merchant-cli')\n .version(getCurrentVersion())\n .description(\n 'Agenzo merchant fulfillment plane: service discovery (services) and ride ordering (ride-elife)',\n )\n .option('--verbose', 'Show verbose logs')\n .option('--yes', 'Skip confirmation prompts (for automation/AI Agents)')\n // merchant-cli is an agent-first entrypoint, so it defaults to json (D2),\n // unlike the cli-core default (table). resolveFormat only acts as a\n // fallback when the flag is absent.\n .option(\n '--format <format>',\n 'Output format: json | table (default: json; or set AGENZO_FORMAT)',\n 'json',\n )\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\n\n // Mirror the resolved global --format into AGENZO_FORMAT before any action\n // runs, so code paths without direct format access can resolve the active\n // format and stay silent in json mode.\n program.hook('preAction', (thisCommand) => {\n const flag = thisCommand.opts().format as string | undefined;\n process.env.AGENZO_FORMAT = resolveFormat(flag);\n });\n\n // ride-elife command group (eLife ride ordering)\n const rideCmd = program.command('ride-elife').description('Ride ordering (eLife)');\n registerQuoteCommand(rideCmd, deps);\n registerBookCommand(rideCmd, deps);\n registerRideGetCommand(rideCmd, deps);\n registerCancelCommand(rideCmd, deps);\n registerListOrdersCommand(rideCmd, deps);\n\n // services command group (CLI-bundled capability discovery)\n const servicesCmd = program.command('services').description('Merchant service discovery');\n registerServicesListCommand(servicesCmd);\n registerServiceGetCommand(servicesCmd);\n\n // Parse and execute\n await program.parseAsync(process.argv);\n}\n\n/**\n * Resolve the active output format for error reporting. Prefers the parsed\n * global `--format` flag (available on `programRef` once the program is\n * constructed; defaults to `json` for merchant-cli); if an error was thrown\n * before parsing, falls back to `resolveFormat(undefined)` (which consults\n * `AGENZO_FORMAT`, else `table`).\n */\nfunction resolveActiveFormat(): OutputFormat {\n const flag = programRef?.opts().format as string | undefined;\n return resolveFormat(flag);\n}\n\n/**\n * Top-level failure path. Writes the error envelope to stderr in the resolved\n * format and exits with the mapped code (1–5). stdout is left untouched so a\n * partial machine payload is never emitted on failure.\n *\n * - `json`: a single `{ error: { code, code_num, message, request_id? } }` envelope (§8.2).\n * - `table`: `✗ [<code_num>] <message>`.\n */\nfunction reportError(error: unknown): never {\n const envelope = toErrorEnvelope(error);\n const format = resolveActiveFormat();\n\n if (format === 'json') {\n console.error(JSON.stringify(envelope));\n } else {\n console.error(\n Formatter.status('error', `[${envelope.error.code_num}] ${envelope.error.message}`),\n );\n // Unknown (non-CliError) failures keep the --verbose raw-dump affordance.\n if (!(error instanceof CliError) && process.argv.includes('--verbose')) {\n console.error(error);\n }\n }\n\n // exitCodeFor owns the error-class → exit-code matrix, including\n // UpgradeRequiredError → 2 and UserCancelError → 5.\n process.exit(exitCodeFor(error));\n}\n\n// Ctrl+C / SIGINT maps to a user-cancel (exit 5) via the same envelope path.\nprocess.on('SIGINT', () => {\n reportError(new UserCancelError());\n});\n\n// Global error handler. Normal completion exits 0 naturally (the mapper is\n// never consulted on success).\nmain().catch(reportError);\n","/**\n * CLI 对外统一错误码目录(cli-design §8 单一事实源)。\n *\n * 每个对外码同时有字符串码(首选路由键)和数字码(紧凑、便于日志聚合)。\n * 二者一一对应,由 {@link CODE_NUM} 绑定。字符串码按域前缀分组,数字码按\n * 同样的域分段(§8.3)。\n *\n * 注:`UPGRADE_REQUIRED`(版本过低)与 `CLIENT_ABORTED`(用户主动取消)是\n * CLI 本地检测的非业务码,不在 §8.4 业务字典内,分配在 CLIENT 号段尾部。\n */\nexport type ErrorCode =\n // AUTH_* (1000-1099)\n | 'AUTH_SESSION_EXPIRED'\n | 'AUTH_MAGIC_LINK_EXPIRED'\n | 'AUTH_INVITE_CODE_REQUIRED'\n | 'AUTH_INVITE_CODE_INVALID'\n // KEY_* (1100-1199)\n | 'KEY_INVALID'\n | 'KEY_SCOPE_DENIED'\n // RESOURCE_* (2000-2099)\n | 'RESOURCE_NOT_FOUND'\n | 'RESOURCE_CONFLICT'\n | 'RESOURCE_STATE_INVALID'\n // PARAM_* (2100-2199)\n | 'PARAM_INVALID'\n | 'PARAM_IDEMPOTENCY_KEY_REQUIRED'\n | 'PARAM_IDEMPOTENCY_KEY_CONFLICT'\n // BILLING_* (3000-3099)\n | 'BILLING_MODE_MISMATCH'\n // ACCOUNT_* (3100-3199)\n | 'ACCOUNT_NOT_FOUND'\n | 'ACCOUNT_SUSPENDED'\n | 'ACCOUNT_INSUFFICIENT_BALANCE'\n // PAYMENT_ORDER_* (3200-3299)\n | 'PAYMENT_ORDER_NOT_FOUND'\n | 'PAYMENT_ORDER_NOT_PAID'\n | 'PAYMENT_ORDER_MISMATCH'\n | 'PAYMENT_ORDER_ALREADY_CONSUMED'\n // TOKEN_* (4000-4099)\n | 'TOKEN_FEATURE_DISABLED'\n // SERVICE_* (4100-4199)\n | 'SERVICE_NOT_FOUND'\n // ride 业务码 (4200-4299)\n | 'VEHICLE_UNAVAILABLE'\n | 'QUOTE_EXPIRED'\n | 'BOOKING_FAILED'\n | 'CANCELLATION_NOT_ALLOWED'\n // RATE_* (5000-5099)\n | 'RATE_LIMITED'\n // UPSTREAM_* (5100-5199)\n | 'UPSTREAM_ERROR'\n // INTERNAL_* (5200-5299)\n | 'INTERNAL_ERROR'\n // NOT_IMPLEMENTED (5300)\n | 'NOT_IMPLEMENTED'\n // CLIENT_* (9000-9099) — CLI 本地产生\n | 'CLIENT_NOT_SIGNED_IN'\n | 'CLIENT_LOGIN_TIMEOUT'\n | 'CLIENT_ORG_NOT_LOCAL'\n | 'CLIENT_ORG_WRONG_ENV'\n | 'CLIENT_NO_PAYMENT_METHOD'\n | 'CLIENT_CARD_NOT_MATCHED'\n | 'CLIENT_ABORTED'\n // 非业务码(CLI 本地检测)\n | 'UPGRADE_REQUIRED';\n\n/**\n * 字符串码 → 数字码(§8.4)。每个对外码的数字码由本表唯一绑定,发布后只增不改。\n */\nexport const CODE_NUM: Record<ErrorCode, number> = {\n AUTH_SESSION_EXPIRED: 1001,\n AUTH_MAGIC_LINK_EXPIRED: 1002,\n AUTH_INVITE_CODE_REQUIRED: 1003,\n AUTH_INVITE_CODE_INVALID: 1004,\n KEY_INVALID: 1101,\n KEY_SCOPE_DENIED: 1102,\n RESOURCE_NOT_FOUND: 2001,\n RESOURCE_CONFLICT: 2002,\n RESOURCE_STATE_INVALID: 2003,\n PARAM_INVALID: 2101,\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 2102,\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 2103,\n BILLING_MODE_MISMATCH: 3001,\n ACCOUNT_NOT_FOUND: 3101,\n ACCOUNT_SUSPENDED: 3102,\n ACCOUNT_INSUFFICIENT_BALANCE: 3103,\n PAYMENT_ORDER_NOT_FOUND: 3201,\n PAYMENT_ORDER_NOT_PAID: 3202,\n PAYMENT_ORDER_MISMATCH: 3203,\n PAYMENT_ORDER_ALREADY_CONSUMED: 3204,\n TOKEN_FEATURE_DISABLED: 4001,\n SERVICE_NOT_FOUND: 4101,\n VEHICLE_UNAVAILABLE: 4201,\n QUOTE_EXPIRED: 4202,\n BOOKING_FAILED: 4203,\n CANCELLATION_NOT_ALLOWED: 4204,\n RATE_LIMITED: 5001,\n UPSTREAM_ERROR: 5101,\n INTERNAL_ERROR: 5201,\n NOT_IMPLEMENTED: 5300,\n CLIENT_NOT_SIGNED_IN: 9001,\n CLIENT_LOGIN_TIMEOUT: 9002,\n CLIENT_ORG_NOT_LOCAL: 9003,\n CLIENT_ORG_WRONG_ENV: 9004,\n CLIENT_NO_PAYMENT_METHOD: 9005,\n CLIENT_CARD_NOT_MATCHED: 9006,\n CLIENT_ABORTED: 9007,\n UPGRADE_REQUIRED: 9008,\n};\n\n/** Look up the numeric code for a string error code. */\nexport function codeNum(code: ErrorCode): number {\n return CODE_NUM[code];\n}\n","import { type ErrorCode, CODE_NUM, codeNum } from './error-catalog.js';\nimport type { ApiError, UpstreamError } from '../api-client/client.js';\n\n/** Base class for all CLI errors. Carries the CLI-facing error code (§8.4). */\nexport class CliError extends Error {\n constructor(\n public readonly code: ErrorCode,\n message: string,\n public readonly statusCode?: number,\n public readonly requestId?: string,\n public readonly upstream?: UpstreamError,\n ) {\n super(message);\n this.name = 'CliError';\n }\n\n /**\n * Map a backend ApiError to a CLI-facing code (§8.5 transitional mapping).\n * Backend numeric codes / HTTP status are translated to §8.4 string codes;\n * the raw backend message is NOT passed through (§8.1 principle 4) — a\n * stable, fixed message per code is used instead.\n *\n * The optional `opts.auth` selects the auth semantics for the 401 mapping:\n * - `'bearer'` (default, admin-cli Bearer Token): 401 → `AUTH_SESSION_EXPIRED`.\n * - `'api-key'` (token-cli `X-Api-Key`): 401 → `KEY_INVALID`.\n * 403 maps to `KEY_SCOPE_DENIED` under both auth modes. Omitting `opts`\n * preserves the original Bearer behavior exactly (§8.5 / requirement 6.4).\n *\n * Domain string-code routing (D3 / requirement 5.4): when the backend\n * supplies a string `error.code` in the v3 envelope that is a known §8 code\n * (present in {@link CODE_NUM}), it is used verbatim as the CLI-facing code\n * so ride/merchant-specific codes (`QUOTE_EXPIRED`, `VEHICLE_UNAVAILABLE`,\n * `BILLING_MODE_MISMATCH`, `PAYMENT_ORDER_*`, …) survive intact. Otherwise —\n * including when no string code is provided, as is the case for admin/token\n * today — mapping falls back to the HTTP-status table below, leaving the\n * existing Bearer/api-key behavior unchanged.\n */\n static fromApi(error: ApiError, opts?: { auth?: 'bearer' | 'api-key' }): CliError {\n // D3: prefer the backend's string code when it is a known §8 catalog code.\n if (error.code && isKnownErrorCode(error.code)) {\n return new CliError(\n error.code,\n STABLE_MESSAGE[error.code] ?? 'Request failed. Please check your input and retry.',\n error.statusCode,\n error.requestId,\n error.upstream,\n );\n }\n\n const status = error.statusCode;\n let code: ErrorCode;\n\n if (status === 401) code = opts?.auth === 'api-key' ? 'KEY_INVALID' : 'AUTH_SESSION_EXPIRED';\n else if (status === 403) code = 'KEY_SCOPE_DENIED';\n else if (status === 404) code = 'RESOURCE_NOT_FOUND';\n else if (status === 409) code = 'RESOURCE_CONFLICT';\n else if (status === 429) code = 'RATE_LIMITED';\n else if (status >= 500) code = 'INTERNAL_ERROR';\n else code = 'PARAM_INVALID'; // other 4xx (incl. 400/422)\n\n return new CliError(\n code,\n STABLE_MESSAGE[code] ?? 'Request failed. Please check your input and retry.',\n status,\n error.requestId,\n error.upstream,\n );\n }\n}\n\n/** Network / connectivity failure → UPSTREAM_ERROR. Never leak the internal URL/path. */\nexport class NetworkError extends CliError {\n constructor(_url: string, timeout?: number, _cause?: Error) {\n super(\n 'UPSTREAM_ERROR',\n timeout\n ? 'The request timed out. The service may be temporarily unavailable — please retry.'\n : 'Connection failed. The service may be temporarily unavailable — please retry.',\n );\n }\n}\n\n/** Auth / session failures. Code chosen by message intent (§8.4 AUTH_* / CLIENT_*). */\nexport class AuthError extends CliError {\n constructor(message: string, public readonly suggestion: string) {\n const m = message.toLowerCase();\n const code: ErrorCode = m.includes('not signed in')\n ? 'CLIENT_NOT_SIGNED_IN'\n : m.includes('time')\n ? 'CLIENT_LOGIN_TIMEOUT'\n : m.includes('magic link')\n ? 'AUTH_MAGIC_LINK_EXPIRED'\n : 'AUTH_SESSION_EXPIRED';\n super(code, message || 'Unknown error');\n }\n}\n\nexport class ConfigError extends CliError {\n constructor(message: string, public readonly filePath: string) {\n super('INTERNAL_ERROR', message || 'Unknown error');\n }\n}\n\nexport class ValidationError extends CliError {\n constructor(message: string) {\n super('PARAM_INVALID', message || 'Unknown error');\n }\n}\n\nexport class IdempotencyKeyRequiredError extends CliError {\n constructor(commandPath: string) {\n super(\n 'PARAM_IDEMPOTENCY_KEY_REQUIRED',\n `\\`${commandPath}\\` requires --idempotency-key <key>. Supply a unique key so the write can be safely retried.`,\n );\n }\n}\n\nexport class UpgradeRequiredError extends CliError {\n constructor(currentVersion: string, minVersion: string, upgradeCommand: string) {\n super(\n 'UPGRADE_REQUIRED',\n `agenzo-admin-cli ${currentVersion} is out of date — the server requires ${minVersion} or newer. To upgrade, run: ${upgradeCommand}`,\n );\n }\n}\n\nexport class UserCancelError extends CliError {\n constructor(message = 'Operation cancelled by user') {\n super('CLIENT_ABORTED', message || 'Unknown error');\n }\n}\n\n/** Type guard: is `value` a known §8 string error code (present in CODE_NUM)? */\nfunction isKnownErrorCode(value: string): value is ErrorCode {\n return Object.prototype.hasOwnProperty.call(CODE_NUM, value);\n}\n\n/**\n * Stable, CLI-owned message per code used when mapping opaque backend errors\n * (§8.1 principle 4: never surface raw backend detail).\n */\nconst STABLE_MESSAGE: Partial<Record<ErrorCode, string>> = {\n AUTH_SESSION_EXPIRED: 'Your session has expired. Please run `agenzo-admin-cli auth login` again.',\n AUTH_MAGIC_LINK_EXPIRED: 'Verification link is invalid or has expired. Please request a new one.',\n AUTH_INVITE_CODE_REQUIRED: 'An invitation code is required to register.',\n AUTH_INVITE_CODE_INVALID: 'The invitation code is invalid.',\n KEY_INVALID: 'The API key is invalid or has been revoked. Please check your --api-key and retry.',\n KEY_SCOPE_DENIED: 'This API key does not have the required scope for this command.',\n RESOURCE_NOT_FOUND: 'The resource was not found or does not belong to the current organization.',\n RESOURCE_CONFLICT: 'A resource with the same unique value already exists.',\n RESOURCE_STATE_INVALID: 'The resource is in a state that does not permit this operation.',\n RATE_LIMITED: 'Too many requests. Please back off and retry.',\n UPSTREAM_ERROR: 'A third-party service is temporarily unavailable. Please try again later.',\n INTERNAL_ERROR: 'Something went wrong on the server. Please retry and note the request_id.',\n PARAM_INVALID: 'One or more parameters are invalid. Please check your input and retry.',\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'A request with this idempotency key was already processed with different parameters.',\n TOKEN_FEATURE_DISABLED: 'This token feature is currently unavailable.',\n BILLING_MODE_MISMATCH: 'The billing mode does not match this operation. Please verify your account billing configuration.',\n ACCOUNT_NOT_FOUND: 'The settlement account was not found.',\n ACCOUNT_SUSPENDED: 'The settlement account is suspended. Please contact support.',\n ACCOUNT_INSUFFICIENT_BALANCE: 'The settlement account has insufficient balance for this operation.',\n PAYMENT_ORDER_NOT_FOUND: 'The payment order was not found.',\n PAYMENT_ORDER_NOT_PAID: 'The payment order has not been paid. Please complete payment and retry.',\n PAYMENT_ORDER_MISMATCH: 'The payment order does not match this order. Please check the --payment-order-id.',\n PAYMENT_ORDER_ALREADY_CONSUMED: 'The payment order has already been consumed by another booking.',\n SERVICE_NOT_FOUND: 'The requested service was not found.',\n VEHICLE_UNAVAILABLE: 'No vehicle is available for the requested trip. Please try a different time or class.',\n QUOTE_EXPIRED: 'The quote has expired. Please request a new quote and retry.',\n BOOKING_FAILED: 'The booking could not be completed. Please retry.',\n CANCELLATION_NOT_ALLOWED: 'This order cannot be cancelled in its current state.',\n NOT_IMPLEMENTED: 'This operation is not implemented yet.',\n};\n\n/** §8.2 error envelope: `{ error: { code, code_num, message, request_id?, upstream? } }`. */\nexport interface ErrorEnvelope {\n error: {\n code: ErrorCode;\n code_num: number;\n message: string;\n request_id?: string;\n upstream?: UpstreamError;\n };\n}\n\nexport function toErrorEnvelope(error: unknown): ErrorEnvelope {\n if (error instanceof CliError) {\n return {\n error: {\n code: error.code,\n code_num: codeNum(error.code),\n message: error.message || 'Unknown error',\n ...(error.requestId ? { request_id: error.requestId } : {}),\n ...(error.upstream ? { upstream: error.upstream } : {}),\n },\n };\n }\n\n const message =\n error instanceof Error\n ? error.message\n : typeof error === 'string'\n ? error\n : 'Unexpected error';\n return {\n error: {\n code: 'INTERNAL_ERROR',\n code_num: codeNum('INTERNAL_ERROR'),\n message: message || 'Unknown error',\n },\n };\n}\n","/**\n * CLI version + min-version comparator.\n *\n * The CLI's current version is read from `package.json` at runtime. This is\n * the single source of truth — bumping `package.json` automatically updates\n * what the CLI reports and what it compares against the server-advertised\n * minimum (`X-CLI-Min-Version` response header, driven by\n * `AGENT_PAY_CLI_MIN_VERSION` on the server).\n *\n * Only numeric major.minor.patch segments are compared; pre-release and build\n * metadata suffixes are stripped. This matches our versioning scheme and\n * avoids pulling in `semver` for a single `<` check.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/** Command the user should run to pick up the latest CLI. */\nexport const UPGRADE_COMMAND = 'npm install -g agenzo-admin-cli@latest';\n\n/**\n * Hard-coded fallback used only when `package.json` cannot be read at runtime\n * (unusual packaging/bundling edge cases). Keep this in sync with\n * `package.json`'s `version` on every release so the reported version and\n * the User-Agent stay accurate even in the degraded path.\n */\nexport const FALLBACK_VERSION = '0.1.1';\n\nlet cachedVersion: string | null = null;\n\nexport function getCurrentVersion(): string {\n if (cachedVersion !== null) return cachedVersion;\n // Walk up from the compiled file (dist/index.js) or source layout to find\n // package.json. Both `dist/..` and `src/utils/../..` resolve to the project\n // root, which is where package.json lives in a published npm install.\n const here = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n join(here, '..', 'package.json'), // dist/ → project root\n join(here, '..', '..', 'package.json'), // src/utils/ → project root\n ];\n for (const p of candidates) {\n try {\n const pkg = JSON.parse(readFileSync(p, 'utf-8')) as { version?: string };\n if (typeof pkg.version === 'string') {\n cachedVersion = pkg.version;\n return cachedVersion;\n }\n } catch {\n // try next candidate\n }\n }\n // Degrade gracefully instead of crashing the CLI: if we can't locate\n // package.json at runtime, report the hard-coded fallback. The User-Agent\n // and any min-version comparison will still behave sensibly. We write a\n // one-line warning to stderr so packaging regressions remain visible.\n cachedVersion = FALLBACK_VERSION;\n // eslint-disable-next-line no-console\n console.warn(\n `[agenzo-admin-cli] package.json not found; using fallback version ${FALLBACK_VERSION}`,\n );\n return cachedVersion;\n}\n\n/**\n * Returns negative / zero / positive like `Array.sort`, comparing `a` against `b`.\n * Non-numeric segments and suffixes are treated as zero.\n */\nexport function compareVersions(a: string, b: string): number {\n const parse = (v: string): [number, number, number] => {\n const clean = v.trim().replace(/^v/, '').split(/[-+]/)[0];\n const parts = clean.split('.');\n return [\n parseInt(parts[0] ?? '0', 10) || 0,\n parseInt(parts[1] ?? '0', 10) || 0,\n parseInt(parts[2] ?? '0', 10) || 0,\n ];\n };\n const [a1, a2, a3] = parse(a);\n const [b1, b2, b3] = parse(b);\n if (a1 !== b1) return a1 - b1;\n if (a2 !== b2) return a2 - b2;\n return a3 - b3;\n}\n\nexport function isBelow(current: string, minimum: string): boolean {\n return compareVersions(current, minimum) < 0;\n}\n","import { NetworkError, UpgradeRequiredError } from '../errors/errors.js';\nimport { getCurrentVersion, isBelow, UPGRADE_COMMAND } from '../version/version.js';\n\nexport interface ApiClientConfig {\n baseUrl: string;\n timeout?: number; // Default 30000ms\n}\n\nexport interface ApiResponse<T> {\n success: true;\n data: T;\n /** Server-provided message from the unified response envelope. */\n message?: string;\n}\n\n/** Upstream error details (diagnostic only, not stable). */\nexport interface UpstreamError {\n /** Upstream-specific error code (stringified). */\n code: string;\n /** Upstream-specific error message. */\n message: string;\n}\n\nexport interface ApiError {\n success: false;\n errorCode: number;\n errorMessage: string;\n statusCode: number;\n /**\n * Raw string code from the v3 response envelope (`{ code, message, data }`),\n * surfaced verbatim so {@link CliError.fromApi} can route domain-specific\n * §8 codes (e.g. `QUOTE_EXPIRED`, `VEHICLE_UNAVAILABLE`) by string code\n * before falling back to HTTP-status mapping. Absent when the backend does\n * not provide a string code (e.g. non-JSON error responses).\n */\n code?: string;\n /** Server-provided request correlation id, surfaced in the error envelope. */\n requestId?: string;\n /** Upstream error details for diagnostic transparency. */\n upstream?: UpstreamError;\n}\n\nexport type ApiResult<T> = ApiResponse<T> | ApiError;\n\nexport type AuthMode =\n | { type: 'bearer'; token: string }\n | { type: 'api-key'; key: string }\n | { type: 'none' };\n\nexport class ApiClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: ApiClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.timeout = config.timeout ?? 60000;\n }\n\n private buildHeaders(auth: AuthMode): Record<string, string> {\n const headers: Record<string, string> = {\n 'User-Agent': `agenzo-admin-cli/${getCurrentVersion()}`,\n };\n if (auth.type === 'bearer') {\n headers['Authorization'] = `Bearer ${auth.token}`;\n } else if (auth.type === 'api-key') {\n headers['X-Api-Key'] = auth.key;\n }\n return headers;\n }\n\n async get<T>(\n path: string,\n auth: AuthMode,\n params?: Record<string, string>,\n ): Promise<ApiResult<T>> {\n let url = `${this.baseUrl}${path}`;\n if (params && Object.keys(params).length > 0) {\n const searchParams = new URLSearchParams(params);\n url += `?${searchParams.toString()}`;\n }\n return this.request<T>(url, {\n method: 'GET',\n headers: this.buildHeaders(auth),\n });\n }\n\n async post<T>(\n path: string,\n auth: AuthMode,\n body?: Record<string, unknown>,\n extraHeaders?: Record<string, string>,\n ): Promise<ApiResult<T>> {\n const url = `${this.baseUrl}${path}`;\n const headers = this.buildHeaders(auth);\n headers['Content-Type'] = 'application/json';\n if (extraHeaders) {\n Object.assign(headers, extraHeaders);\n }\n return this.request<T>(url, {\n method: 'POST',\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n private async request<T>(url: string, init: RequestInit): Promise<ApiResult<T>> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n // Enforce server-advertised CLI version floor before doing any work\n // on the response. Throws UpgradeRequiredError which is rendered and\n // exits at the top level (src/index.ts).\n this.enforceMinVersion(response.headers.get('x-cli-min-version'));\n\n // Handle non-JSON responses (e.g. 500 Internal Server Error returns plain text)\n const contentType = response.headers.get('content-type') ?? '';\n let responseBody: Record<string, unknown>;\n if (contentType.includes('application/json')) {\n responseBody = await response.json() as Record<string, unknown>;\n } else {\n const text = await response.text();\n if (!response.ok) {\n const statusMsg = this.friendlyStatusMessage(response.status);\n return {\n success: false,\n errorCode: 0,\n errorMessage: statusMsg,\n statusCode: response.status,\n };\n }\n // Try parsing as JSON anyway (some servers don't set content-type)\n try {\n responseBody = JSON.parse(text) as Record<string, unknown>;\n } catch {\n return {\n success: false,\n errorCode: 0,\n errorMessage: `Unexpected response from server (${response.status})`,\n statusCode: response.status,\n };\n }\n }\n\n // Server uses unified format: { code: \"0000\", message: \"...\", data: {...} }\n const code = responseBody.code as string | undefined;\n const message = responseBody.message as string | undefined;\n const data = responseBody.data as Record<string, unknown> | undefined;\n\n // Success: HTTP 2xx AND code is \"0000\" (or no code field for raw responses)\n if (response.ok && (!code || code === '0000')) {\n // If server wraps data in a \"data\" field, unwrap it\n const payload = data ?? responseBody;\n return { success: true, data: payload as T, message };\n }\n\n // Error: either HTTP non-2xx or code !== \"0000\"\n const errorCode = code ? parseInt(code, 10) : 0;\n // Handle FastAPI 422 validation errors where detail is an array\n let errorMsg = message ?? response.statusText;\n if (!errorMsg || errorMsg === response.statusText) {\n const detail = responseBody.detail;\n if (Array.isArray(detail)) {\n errorMsg = detail.map((d: Record<string, unknown>) => {\n const loc = (d.loc as string[])?.slice(1).join('.') ?? '';\n return loc ? `${loc}: ${d.msg}` : String(d.msg);\n }).join('; ');\n } else if (typeof detail === 'string') {\n errorMsg = detail;\n }\n }\n\n // Prefer string error_code (CLI D3 routing) over numeric code string\n const errorCodeStr = responseBody.error_code as string | undefined;\n\n // Extract upstream error details from data.upstream\n const rawData = responseBody.data as Record<string, unknown> | undefined;\n const upstream = (rawData?.upstream && typeof rawData.upstream === 'object')\n ? rawData.upstream as UpstreamError\n : undefined;\n\n return {\n success: false,\n errorCode: isNaN(errorCode) ? 0 : errorCode,\n errorMessage: errorMsg,\n statusCode: response.status,\n ...(errorCodeStr ? { code: errorCodeStr } : (typeof code === 'string' && code ? { code } : {})),\n requestId: (responseBody.request_id ?? responseBody.requestId) as string | undefined,\n ...(upstream ? { upstream } : {}),\n };\n } catch (error) {\n // UpgradeRequiredError is a CliError and must propagate untouched to the\n // top-level handler; don't rewrap it as a NetworkError.\n if (error instanceof UpgradeRequiredError) {\n throw error;\n }\n if (error instanceof DOMException && error.name === 'AbortError') {\n throw new NetworkError(url, this.timeout);\n }\n throw new NetworkError(url, undefined, error instanceof Error ? error : undefined);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Validate that the running CLI meets the server-advertised minimum.\n * Missing or empty header → skip (backward compat with servers that don't\n * advertise yet, and clients hitting legacy proxies).\n */\n private enforceMinVersion(headerValue: string | null): void {\n const minVersion = headerValue?.trim();\n if (!minVersion) return;\n const current = getCurrentVersion();\n if (isBelow(current, minVersion)) {\n throw new UpgradeRequiredError(current, minVersion, UPGRADE_COMMAND);\n }\n }\n\n private friendlyStatusMessage(status: number): string {\n const messages: Record<number, string> = {\n 400: 'Invalid request. Please check your input.',\n 401: 'Authentication failed. Please check your API key or login again.',\n 403: 'Access denied. You do not have permission for this operation.',\n 404: 'Resource not found. Please check the ID.',\n 409: 'Conflict. This resource may already exist.',\n 422: 'Invalid input. Please check the request parameters.',\n 429: 'Too many requests. Please wait and try again.',\n 500: 'Something went wrong on the server. Please try again later.',\n 502: 'Service is temporarily unavailable. Please try again in a moment.',\n 503: 'Service is temporarily unavailable. Please try again in a moment.',\n 504: 'The request took too long. Please try again.',\n };\n return messages[status] ?? `Something went wrong (${status}). Please try again later.`;\n }\n}\n","import { readFile, writeFile, readdir, unlink, access, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { OrgCredential } from '../types/config.js';\n\nexport class CredentialStore {\n private readonly basePath: string;\n\n constructor(basePath?: string) {\n this.basePath = basePath ?? join(homedir(), '.agenzo-admin-cli', 'credentials');\n }\n\n private filePath(orgId: string): string {\n return join(this.basePath, `${orgId}.json`);\n }\n\n private async ensureDir(): Promise<void> {\n // Credentials hold long-lived Bearer tokens — dir must be owner-only (0700).\n // mkdir mode is subject to umask, so chmod afterwards to enforce it on\n // both freshly created and pre-existing directories.\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\n await chmod(this.basePath, 0o700);\n }\n\n async get(orgId: string): Promise<OrgCredential | null> {\n try {\n const content = await readFile(this.filePath(orgId), 'utf-8');\n return JSON.parse(content) as OrgCredential;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n }\n\n async save(credential: OrgCredential): Promise<void> {\n await this.ensureDir();\n const path = this.filePath(credential.org_id);\n // Owner read/write only (0600); chmod after write so pre-existing files\n // created before this safeguard also get tightened.\n await writeFile(path, JSON.stringify(credential, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n await chmod(path, 0o600);\n }\n\n async delete(orgId: string): Promise<void> {\n try {\n await unlink(this.filePath(orgId));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return;\n }\n throw error;\n }\n }\n\n async listAll(): Promise<OrgCredential[]> {\n try {\n const files = await readdir(this.basePath);\n const jsonFiles = files.filter((f) => f.endsWith('.json'));\n const credentials: OrgCredential[] = [];\n for (const file of jsonFiles) {\n try {\n const content = await readFile(join(this.basePath, file), 'utf-8');\n credentials.push(JSON.parse(content) as OrgCredential);\n } catch {\n // Skip corrupted files\n }\n }\n return credentials;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw error;\n }\n }\n\n async exists(orgId: string): Promise<boolean> {\n try {\n await access(this.filePath(orgId));\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { StoredApiKey } from '../types/config.js';\n\nexport class KeyStore {\n private readonly basePath: string;\n\n constructor(basePath?: string) {\n // API keys are shared across runtime-plane CLIs (token/merchant/payment).\n // Stored under the legacy path for backward compatibility; will migrate to\n // ~/.agenzo/keys/ in a future release.\n this.basePath = basePath ?? join(homedir(), '.agenzo-token-cli', 'api-keys');\n }\n\n private filePath(orgId: string): string {\n return join(this.basePath, `${orgId}.json`);\n }\n\n private async loadData(orgId: string): Promise<StoredApiKey[]> {\n try {\n const content = await readFile(this.filePath(orgId), 'utf-8');\n return JSON.parse(content) as StoredApiKey[];\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw error;\n }\n }\n\n private async saveData(orgId: string, data: StoredApiKey[]): Promise<void> {\n // Stored API keys are plaintext secrets — dir 0700, file 0600.\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\n await chmod(this.basePath, 0o700);\n const path = this.filePath(orgId);\n await writeFile(path, JSON.stringify(data, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n await chmod(path, 0o600);\n }\n\n async add(orgId: string, key: StoredApiKey): Promise<void> {\n const data = await this.loadData(orgId);\n data.push(key);\n await this.saveData(orgId, data);\n }\n\n async update(orgId: string, keyId: string, newKeyValue: string): Promise<void> {\n const data = await this.loadData(orgId);\n const key = data.find((k) => k.key_id === keyId);\n if (key) {\n key.key_value = newKeyValue;\n await this.saveData(orgId, data);\n }\n }\n\n async list(orgId: string): Promise<StoredApiKey[]> {\n return this.loadData(orgId);\n }\n\n async get(orgId: string, keyId: string): Promise<StoredApiKey | null> {\n const data = await this.loadData(orgId);\n return data.find((k) => k.key_id === keyId) ?? null;\n }\n}\n","import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { AppConfig } from '../types/config.js';\nimport { ConfigError, ValidationError } from '../errors/errors.js';\n\nconst DEFAULT_CONFIG: AppConfig = {\n active_org: null,\n active_developer_id: null,\n api_host: 'https://agent.everonet.com',\n api_path: '/api/v3/agent-pay',\n};\n\nexport const BUILTIN_PROFILES: Record<string, string> = {\n production: 'https://agent.everonet.com',\n testing: 'https://agent-test.everonet.com',\n};\n\n/**\n * Resolve a user-supplied host argument (a built-in profile name or an\n * explicit URL) to the concrete API host URL that gets persisted.\n * Pure (no I/O) so callers can compute the resolved value before/without a\n * config write — e.g. `config set-host` needs it to match stored credentials\n * by their resolved `api_host` rather than the raw profile name.\n * Throws `ValidationError` for unknown profiles / malformed URLs.\n */\nexport function resolveApiHost(host: string): string {\n if (BUILTIN_PROFILES[host]) {\n return BUILTIN_PROFILES[host];\n }\n\n let url: URL;\n try {\n url = new URL(host);\n } catch {\n throw new ValidationError(`Unknown profile or invalid URL: ${host}`);\n }\n\n if (url.protocol === 'https:') {\n return host;\n }\n\n if (\n url.protocol === 'http:'\n && (url.hostname === 'localhost' || url.hostname === '127.0.0.1')\n ) {\n return host;\n }\n\n throw new ValidationError(\n `Insecure API host is not allowed: ${host}. Use HTTPS, except for localhost or 127.0.0.1.`,\n );\n}\n\nexport class ConfigManager {\n private readonly basePath: string;\n private readonly configPath: string;\n\n constructor(basePath?: string) {\n this.basePath = basePath ?? join(homedir(), '.agenzo-admin-cli');\n this.configPath = join(this.basePath, 'config.json');\n }\n\n async ensureDirectories(): Promise<void> {\n // Base dir contains the credentials/ subtree → owner-only (0700).\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\n await chmod(this.basePath, 0o700);\n const credDir = join(this.basePath, 'credentials');\n await mkdir(credDir, { recursive: true, mode: 0o700 });\n await chmod(credDir, 0o700);\n }\n\n async load(): Promise<AppConfig> {\n try {\n const content = await readFile(this.configPath, 'utf-8');\n try {\n const raw = JSON.parse(content) as Record<string, unknown>;\n // Migrate old api_base_url format\n if (raw.api_base_url && !raw.api_host) {\n const url = String(raw.api_base_url);\n const pathIndex = url.indexOf('/api/');\n raw.api_host = pathIndex > 0 ? url.slice(0, pathIndex) : url;\n raw.api_path = pathIndex > 0 ? url.slice(pathIndex) : DEFAULT_CONFIG.api_path;\n delete raw.api_base_url;\n }\n return {\n active_org: (raw.active_org as string) ?? null,\n active_developer_id: (raw.active_developer_id as string) ?? null,\n api_host: (raw.api_host as string) ?? DEFAULT_CONFIG.api_host,\n api_path: (raw.api_path as string) ?? DEFAULT_CONFIG.api_path,\n };\n } catch {\n throw new ConfigError(\n `Invalid config file: ${this.configPath}`,\n this.configPath,\n );\n }\n } catch (error) {\n if (error instanceof ConfigError) throw error;\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return { ...DEFAULT_CONFIG };\n }\n throw error;\n }\n }\n\n async save(config: AppConfig): Promise<void> {\n await this.ensureDirectories();\n await writeFile(this.configPath, JSON.stringify(config, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n await chmod(this.configPath, 0o600);\n }\n\n async getActiveOrg(): Promise<string | null> {\n const config = await this.load();\n return config.active_org;\n }\n\n async setActiveOrg(orgId: string): Promise<void> {\n const config = await this.load();\n config.active_org = orgId;\n await this.save(config);\n }\n\n async getApiBaseUrl(): Promise<string> {\n const config = await this.load();\n const host = resolveApiHost(config.api_host).replace(/\\/+$/, '');\n const path = config.api_path.startsWith('/') ? config.api_path : `/${config.api_path}`;\n return `${host}${path}`;\n }\n\n async setApiHost(host: string): Promise<void> {\n const config = await this.load();\n config.api_host = resolveApiHost(host);\n await this.save(config);\n }\n\n async getApiHost(): Promise<string> {\n const config = await this.load();\n return resolveApiHost(config.api_host);\n }\n}\n","import { CliError } from '../errors/errors.js';\n\n/**\n * Exit-code mapper (cli-design §8.6 / cli-standard §5.4).\n *\n * Maps any thrown error reaching the top-level handler to one of the CLI's\n * non-zero exit codes. Normal completion implies `0` and never consults this.\n *\n * 1 — business / param: PARAM_* / RESOURCE_* / BILLING_* / ACCOUNT_* /\n * PAYMENT_ORDER_* / TOKEN_* / SERVICE_* / ride codes / CLIENT_* /\n * NOT_IMPLEMENTED, and unknown errors\n * 2 — upgrade required: UPGRADE_REQUIRED\n * 3 — auth-fail / invalid-key: AUTH_* / KEY_*\n * 4 — network / 5xx: UPSTREAM_ERROR / INTERNAL_ERROR / RATE_LIMITED\n * 5 — user-cancel: CLIENT_ABORTED\n */\nexport function exitCodeFor(error: unknown): 1 | 2 | 3 | 4 | 5 {\n if (!(error instanceof CliError)) {\n return 1;\n }\n\n const code = error.code;\n\n if (code === 'UPGRADE_REQUIRED') {\n return 2;\n }\n\n if (code === 'CLIENT_ABORTED') {\n return 5;\n }\n\n if (code.startsWith('AUTH_') || code.startsWith('KEY_')) {\n return 3;\n }\n\n if (\n code === 'UPSTREAM_ERROR' ||\n code === 'INTERNAL_ERROR' ||\n code === 'RATE_LIMITED'\n ) {\n return 4;\n }\n\n return 1;\n}\n","export type StatusPrefix = 'success' | 'error' | 'info' | 'warning' | 'loading';\n\nconst STATUS_ICONS: Record<StatusPrefix, string> = {\n success: '✓',\n error: '✗',\n info: 'ℹ',\n warning: '⚠',\n loading: '⠋',\n};\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nexport interface Spinner {\n /** Update the spinner message while it's running */\n update(message: string): void;\n /** Stop the spinner and show a final status line */\n stop(type?: StatusPrefix, finalMessage?: string): void;\n}\n\n/**\n * Creates an animated terminal spinner that cycles through braille frames.\n * Call `spinner.stop()` when the async work is done.\n */\nexport function createSpinner(message: string, intervalMs = 60): Spinner {\n let frameIdx = 0;\n let currentMessage = message;\n\n const render = () => {\n process.stdout.write(`\\r\\x1b[K${SPINNER_FRAMES[frameIdx]} ${currentMessage}`);\n frameIdx = (frameIdx + 1) % SPINNER_FRAMES.length;\n };\n\n render();\n const timer = setInterval(render, intervalMs);\n\n return {\n update(msg: string) {\n currentMessage = msg;\n },\n stop(type?: StatusPrefix, finalMessage?: string) {\n clearInterval(timer);\n process.stdout.write('\\r\\x1b[K');\n if (type && finalMessage) {\n console.log(Formatter.status(type, finalMessage));\n }\n },\n };\n}\n\nexport class Formatter {\n /** Get display width of a string (CJK characters count as 2) */\n private static displayWidth(str: string): number {\n let width = 0;\n for (const char of str) {\n const code = char.codePointAt(0)!;\n // CJK Unified Ideographs and common fullwidth ranges\n if (\n (code >= 0x4e00 && code <= 0x9fff) || // CJK Unified\n (code >= 0x3000 && code <= 0x303f) || // CJK Punctuation\n (code >= 0x3400 && code <= 0x4dbf) || // CJK Extension A\n (code >= 0xff00 && code <= 0xffef) || // Fullwidth Forms\n (code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility\n (code >= 0x20000 && code <= 0x2a6df) // CJK Extension B\n ) {\n width += 2;\n } else {\n width += 1;\n }\n }\n return width;\n }\n\n /** Pad string to target display width (right-pad with spaces) */\n private static padEndDisplay(str: string, targetWidth: number): string {\n const currentWidth = Formatter.displayWidth(str);\n const padding = Math.max(0, targetWidth - currentWidth);\n return str + ' '.repeat(padding);\n }\n\n /** Pad string to target display width (left-pad with spaces) */\n private static padStartDisplay(str: string, targetWidth: number): string {\n const currentWidth = Formatter.displayWidth(str);\n const padding = Math.max(0, targetWidth - currentWidth);\n return ' '.repeat(padding) + str;\n }\n\n /** Table output for list commands — columns aligned by max width */\n static table(headers: string[], rows: string[][]): string {\n const colWidths = headers.map((h, i) => {\n const cellWidths = rows.map((r) => Formatter.displayWidth(r[i] ?? ''));\n return Math.max(Formatter.displayWidth(h), ...cellWidths);\n });\n\n const sep = ' ';\n\n const headerLine = headers.map((h, i) => Formatter.padEndDisplay(h, colWidths[i])).join(sep);\n const divider = colWidths.map((w) => '-'.repeat(w)).join(sep);\n const dataLines = rows.map((row) =>\n row.map((cell, i) => Formatter.padEndDisplay(cell ?? '', colWidths[i])).join(sep),\n );\n\n return [headerLine, divider, ...dataLines].join('\\n');\n }\n\n /** Key-value output for detail commands — keys left-aligned */\n static keyValue(entries: [string, string][]): string {\n const maxKeyWidth = Math.max(...entries.map(([k]) => Formatter.displayWidth(k)));\n return entries\n .map(([key, value]) => `${Formatter.padEndDisplay(key, maxKeyWidth)} ${value}`)\n .join('\\n');\n }\n\n /** Status-prefixed message */\n static status(type: StatusPrefix, message: string): string {\n return `${STATUS_ICONS[type]} ${message}`;\n }\n\n /** Mask sensitive info, keeping only the prefix */\n static maskKey(key: string, prefixLength = 8): string {\n if (key.length <= prefixLength) {\n return key;\n }\n return key.slice(0, prefixLength) + '*'.repeat(key.length - prefixLength);\n }\n\n /**\n * Format ISO 8601 timestamp to local timezone display.\n * Automatically uses the user's system timezone.\n * e.g. \"2026-05-07T03:24:53+00:00\" → \"2026-05-07 11:24:53\" (in CST)\n * \"2026-05-07T03:24:53+00:00\" → \"2026-05-06 20:24:53\" (in PDT)\n * Returns the original string if parsing fails or input is empty.\n */\n static formatTime(iso: string | null | undefined): string {\n if (!iso) return '';\n const date = new Date(iso);\n if (isNaN(date.getTime())) return iso;\n const pad = (n: number) => String(n).padStart(2, '0');\n const y = date.getFullYear();\n const m = pad(date.getMonth() + 1);\n const d = pad(date.getDate());\n const h = pad(date.getHours());\n const min = pad(date.getMinutes());\n const s = pad(date.getSeconds());\n const offsetMin = -date.getTimezoneOffset();\n const sign = offsetMin >= 0 ? '+' : '-';\n const absOffset = Math.abs(offsetMin);\n const tzH = pad(Math.floor(absOffset / 60));\n const tzM = pad(absOffset % 60);\n return `${y}-${m}-${d} ${h}:${min}:${s} (UTC${sign}${tzH}:${tzM})`;\n }\n}\n","import type { CommandResult } from '../types/commands.js';\nimport { Formatter, type StatusPrefix } from './formatter.js';\n\n/**\n * Central output renderer.\n *\n * Single choke point that turns a {@link CommandResult} into stdout bytes,\n * switching between machine-readable JSON and a human-readable table view.\n * This is what lets command handlers stop calling `console.log` directly:\n * they build a `CommandResult` and hand it here.\n *\n * Contract (cli-standard §5.1/§5.2):\n * - stdout carries ONLY the business payload — a single JSON value\n * (`--format json`) or human-readable text (`--format table`).\n * - logs, spinners, prompts, hints and progress lines belong on stderr and\n * are NEVER written here.\n *\n * Recorded deviation from cli-standard §5.1: the default format is `table`\n * (not `json`), and the flag values are `json | table` (not `json | text`).\n */\n\n/** The two supported output formats. */\nexport type OutputFormat = 'json' | 'table';\n\n/** Options consumed by {@link render}. */\nexport interface RenderOptions {\n format: OutputFormat;\n}\n\n/** The default format used when nothing valid is supplied (deliberate deviation: `table`). */\nconst DEFAULT_FORMAT: OutputFormat = 'table';\n\n/** Narrow an arbitrary string to a known {@link OutputFormat}. */\nfunction isOutputFormat(value: string): value is OutputFormat {\n return value === 'json' || value === 'table';\n}\n\n/**\n * Resolve the active output format.\n *\n * Precedence: `--format` flag > `AGENZO_FORMAT` env var > default `table`.\n * Any invalid value falls back to the default. The result is always one of\n * `'json' | 'table'`.\n *\n * The `--format` flag is authoritative when provided: a provided-but-invalid\n * flag falls back to the default rather than deferring to the environment.\n */\nexport function resolveFormat(\n flag?: string,\n env: string | undefined = process.env.AGENZO_FORMAT,\n): OutputFormat {\n // 1. --format flag is authoritative when provided.\n if (flag !== undefined) {\n return isOutputFormat(flag) ? flag : DEFAULT_FORMAT;\n }\n // 2. AGENZO_FORMAT environment value, when set to a valid format.\n if (env !== undefined && isOutputFormat(env)) {\n return env;\n }\n // 3. Default.\n return DEFAULT_FORMAT;\n}\n\n/**\n * Emit a successful command result to stdout in the chosen format.\n *\n * - `json`: writes `JSON.stringify(result.data, null, 2)` (the machine payload\n * only — never the text-mode chrome).\n * - `table`: writes the lazy human presenter `result.text()`.\n *\n * Only the payload reaches stdout; status/progress lines must go to stderr by\n * the caller. A trailing newline is appended so the output pipes cleanly into\n * tools like `jq`.\n */\nexport function render<T>(result: CommandResult<T>, opts: RenderOptions): void {\n if (opts.format === 'json') {\n process.stdout.write(`${JSON.stringify(result.data, null, 2)}\\n`);\n return;\n }\n process.stdout.write(`${result.text()}\\n`);\n}\n\n/**\n * Emit a human-facing status line (✓ / ℹ / ⚠) to stderr — but ONLY in `table`\n * mode. In `json` mode the output is consumed by other agents/scripts, so any\n * decorative status text (even on stderr) is noise that can confuse parsing;\n * `json` mode therefore stays completely silent here. Errors are NOT routed\n * through this helper — they are owned by the top-level handler in index.ts.\n *\n * This is the single choke point for command success/progress notices, so the\n * `json`-silence rule is enforced in one place rather than scattered across\n * every handler.\n */\nexport function notify(\n format: OutputFormat,\n type: StatusPrefix,\n message: string,\n): void {\n if (format === 'json') {\n return;\n }\n console.error(Formatter.status(type, message));\n}\n","/**\n * Shared JSON envelope renderer (cli-design §7.7.2 BACK-011).\n *\n * In `--format json` mode, every command's payload is prefixed with two\n * client-assembled context fields:\n * - `profile`: the active environment name (production / testing / custom),\n * derived by reverse-looking-up the api_host in BUILTIN_PROFILES.\n * - `endpoint`: the api **host only** (e.g. https://agent.everonet.com) —\n * NEVER the internal API path (/api/v3/agent-pay), so internal\n * routing is not leaked to agent consumers.\n *\n * `result.data` is expected to be an object (single-resource payloads are flat\n * field maps; list payloads are `{ <namedKey>: [...], page: {...} }`). The two\n * context fields are spread in front of it.\n *\n * In `--format table` mode this is a passthrough to the standard `render`.\n *\n * This lives in `@agenzo/cli-core` (BACK-011) so every CLI shares one\n * implementation rather than copying it per app.\n */\nimport type { CommandResult } from '../types/commands.js';\nimport { type RenderOptions, render } from './output.js';\nimport { ConfigManager, BUILTIN_PROFILES } from '../config/config-manager.js';\n\nexport async function renderWithContext<T>(\n result: CommandResult<T>,\n opts: RenderOptions,\n configManager: ConfigManager,\n): Promise<void> {\n if (opts.format !== 'json') {\n render(result, opts);\n return;\n }\n\n const config = await configManager.load();\n const host = config.api_host.replace(/\\/+$/, '');\n const profile =\n Object.entries(BUILTIN_PROFILES).find(([, v]) => v === host)?.[0] ?? 'custom';\n\n const dataObj =\n result.data && typeof result.data === 'object'\n ? (result.data as Record<string, unknown>)\n : { value: result.data };\n\n const payload = {\n profile,\n endpoint: host,\n ...dataObj,\n };\n\n render({ ...result, data: payload } as CommandResult<typeof payload>, opts);\n}\n","import { input, password, select } from '@inquirer/prompts';\n\ninterface PromptConfig {\n message: string;\n type?: 'input' | 'password' | 'select';\n choices?: { name: string; value: string }[];\n validate?: (input: string) => boolean | string;\n}\n\nexport class PromptEngine {\n /** Return flagValue directly if provided, otherwise prompt interactively */\n static async resolveInput(\n flagValue: string | undefined,\n config: PromptConfig,\n ): Promise<string> {\n if (flagValue !== undefined) {\n return flagValue;\n }\n\n if (config.type === 'password') {\n return password({ message: config.message, mask: '*' });\n }\n\n if (config.type === 'select' && config.choices) {\n return select({\n message: config.message,\n choices: config.choices,\n });\n }\n\n return input({\n message: config.message,\n validate: config.validate,\n });\n }\n}\n","import type { ApiClient } from '@agenzo/cli-core';\nimport { CliError } from '@agenzo/cli-core';\nimport type { GetOrderResponse } from '../types/api.js';\n\n/**\n * NDJSON status-polling for `ride-elife get --watch` (§4.4.1.3 polling /\n * design Property 2). Merchant-domain logic — stays in the app per\n * requirement 4.4 (NOT pushed down to cli-core).\n *\n * The watch stream is a line stream: each poll result is written as ONE\n * independent, compact JSON line on stdout. It is deliberately NOT routed\n * through `renderWithContext`, so the profile/endpoint envelope is never\n * wrapped around the stream (an agent consumes it with a line reader).\n *\n * The polling engine is split from its I/O so it can be unit/PBT-tested with a\n * fake clock and shortened constants (task 6.5): `fetchStatus`, `writeLine`,\n * `sleep` and `now` are all injected.\n */\n\n/**\n * Terminal ride statuses (schema `polling.terminal_statuses`). Once the order\n * reaches one of these, `--watch` stops polling. CASE-SENSITIVE — must match\n * the server casing exactly.\n */\nexport const TERMINAL_STATUSES: ReadonlySet<string> = new Set([\n 'At destination',\n 'Cancelled',\n 'Rejected',\n 'Customer no show',\n 'Driver no show',\n]);\n\n/** Schema `polling.recommended_interval_seconds`. */\nexport const DEFAULT_WATCH_INTERVAL_SECONDS = 5;\n/** Safety cap so `--watch` can never poll forever. */\nexport const DEFAULT_WATCH_TIMEOUT_SECONDS = 600;\n\n/**\n * Pure terminal-state predicate (exported for direct unit/PBT testing). A\n * missing/undefined status is never terminal, so polling continues until a\n * known terminal status or the timeout.\n */\nexport function isTerminalStatus(status: string | undefined | null): boolean {\n return status !== undefined && status !== null && TERMINAL_STATUSES.has(status);\n}\n\n/** Read the case-sensitive `status` field off a poll result. */\nexport function statusOf(data: GetOrderResponse): string | undefined {\n const status = (data as { status?: unknown }).status;\n return typeof status === 'string' ? status : undefined;\n}\n\n/** The final NDJSON line emitted when polling gives up before a terminal status. */\nexport interface WatchTimeoutLine {\n watch_status: 'timeout';\n message: string;\n last_status: string | null;\n}\n\n/** I/O + clock seams the polling engine depends on (all injectable for tests). */\nexport interface WatchEngineDeps {\n /** Fetch one status snapshot (throws to abort the whole stream). */\n fetchStatus: () => Promise<GetOrderResponse>;\n /** Write one NDJSON record as a single compact line. */\n writeLine: (record: unknown) => void;\n /** Resolve after `ms` (real timer in prod; fake clock in tests). */\n sleep: (ms: number) => Promise<void>;\n /** Current epoch millis (real `Date.now` in prod; fake clock in tests). */\n now: () => number;\n}\n\n/** Interval / timeout budget for one watch run, in milliseconds. */\nexport interface WatchEngineOptions {\n intervalMs: number;\n timeoutMs: number;\n}\n\n/**\n * Poll `fetchStatus`, writing each result as an NDJSON line, until the order\n * reaches a terminal status or the timeout elapses. On timeout the FINAL line\n * is `{ watch_status: 'timeout', ... }` (requirement 3.2 / Property 2).\n *\n * Termination: every iteration either returns (terminal status) or, when the\n * next poll would land at/after the deadline, emits the timeout line and\n * returns. With a monotonically advancing clock (real time, or a fake clock\n * advanced by `sleep`) the deadline is always reached, so the loop is\n * guaranteed to terminate for any status sequence.\n */\nexport async function runWatch(\n deps: WatchEngineDeps,\n opts: WatchEngineOptions,\n): Promise<void> {\n const deadline = deps.now() + opts.timeoutMs;\n for (;;) {\n const data = await deps.fetchStatus();\n deps.writeLine(data);\n\n const status = statusOf(data);\n if (isTerminalStatus(status)) {\n return;\n }\n\n if (deps.now() + opts.intervalMs >= deadline) {\n const timeoutLine: WatchTimeoutLine = {\n watch_status: 'timeout',\n message: `Polling stopped after ${opts.timeoutMs / 1000}s without reaching a terminal status.`,\n last_status: status ?? null,\n };\n deps.writeLine(timeoutLine);\n return;\n }\n\n await deps.sleep(opts.intervalMs);\n }\n}\n\n/**\n * Parse a positive `--watch-*` seconds flag, falling back to a default when\n * absent or non-positive (mirrors the standalone reference behaviour). Returns\n * a value in SECONDS.\n */\nexport function resolveSeconds(value: string | undefined, fallback: number): number {\n if (value === undefined) return fallback;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : fallback;\n}\n\n/** Real-timer sleep used by the production watch path. */\nexport const realSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Compact single-line NDJSON writer used by the production watch path. */\nexport const ndjsonWriteLine = (record: unknown): void => {\n process.stdout.write(`${JSON.stringify(record)}\\n`);\n};\n\n/**\n * Production wiring for `ride-elife get --watch`: bind the polling engine to a\n * live `ApiClient` (status endpoint + api-key auth), the compact NDJSON stdout\n * writer, real timers and the system clock. A network/backend failure on any\n * poll surfaces as a `CliError` to the top-level handler, exactly like the\n * single-shot path.\n */\nexport async function watchRideStatus(\n apiClient: ApiClient,\n apiKey: string,\n orderId: string,\n opts: { intervalSeconds: number; timeoutSeconds: number },\n): Promise<void> {\n const path = `/ride/${encodeURIComponent(orderId)}/status`;\n await runWatch(\n {\n fetchStatus: async () => {\n const result = await apiClient.get<GetOrderResponse>(path, {\n type: 'api-key',\n key: apiKey,\n });\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n return result.data;\n },\n writeLine: ndjsonWriteLine,\n sleep: realSleep,\n now: () => Date.now(),\n },\n {\n intervalMs: opts.intervalSeconds * 1000,\n timeoutMs: opts.timeoutSeconds * 1000,\n },\n );\n}\n","/**\n * `--help --format json` verb-level schema (§4.4.1.3) — merchant domain only.\n *\n * Every ride-elife verb supports `--help --format json`, which prints a single\n * machine-readable JSON object describing the verb instead of commander's\n * default text help. This is the standard way an Agent discovers a verb's\n * flags, response shape, example invocation and (where relevant) error-recovery\n * and polling guidance locally, without a network round-trip.\n *\n * admin-cli / token-cli have no such mode, so this lives in the app (not in\n * cli-core) per requirement 4.4.\n *\n * Mechanism (commander v14): `attachSchemaHelp` overrides a command's\n * `helpInformation`. Commander resolves `--help` BEFORE later argv tokens are\n * applied to options, so the parsed `--format` value is not yet available when\n * help renders — we therefore read it straight from `process.argv`. Only an\n * explicit `--format json` switches to the JSON schema; bare `--help` and\n * `--help --format table` keep commander's default text help.\n */\nimport type { Command } from 'commander';\nimport { TERMINAL_STATUSES, DEFAULT_WATCH_INTERVAL_SECONDS } from './ride-elife/watch.js';\n\nconst CLI_NAME = 'agenzo-merchant-cli';\nconst NOUN = 'ride-elife';\n\n// ============================================================\n// Schema shape (§4.4.1.3 verb-level schema)\n// ============================================================\n\n/** One flag descriptor: type / required / optional default / description / constraints. */\nexport interface FlagSchema {\n type: string;\n /** `true` / `false`, or the literal `'conditional'` for mode-dependent flags. */\n required: boolean | 'conditional';\n default?: unknown;\n description: string;\n constraints?: string;\n}\n\n/** A complete, copy-pasteable example invocation plus what to read from the output. */\nexport interface ExampleSchema {\n command: string;\n output_summary: string;\n}\n\n/** Polling guidance — only status-query verbs (`get`) carry this block. */\nexport interface PollingSchema {\n recommended_interval_seconds: number;\n terminal_statuses: string[];\n in_progress_statuses: string[];\n field_availability?: Record<string, string>;\n}\n\n/**\n * The verb-level schema object emitted by `--help --format json`\n * (§4.4.1.3): `{ cli, noun, verb, description, flags, response, example,\n * [error_recovery], [polling] }`. `error_recovery` / `polling` are optional and\n * present only where the verb warrants them.\n */\nexport interface VerbSchema {\n cli: string;\n noun: string;\n verb: string;\n description: string;\n flags: Record<string, FlagSchema>;\n /** Key response fields + type descriptions (nested objects allowed). */\n response: Record<string, unknown>;\n example: ExampleSchema;\n error_recovery?: Record<string, string>;\n polling?: PollingSchema;\n}\n\n// ============================================================\n// Emit + attach mechanism\n// ============================================================\n\n/**\n * True only when `--format json` is explicitly present in `argv`. Commander\n * resolves `--help` before applying later option tokens, so the parsed format\n * is not yet available at help-render time; we read argv directly. Bare `--help`\n * and `--help --format table` deliberately return false (keep text help), even\n * though the program defaults `--format` to json — the default is never written\n * into argv.\n */\nexport function wantsJsonSchema(argv: string[] = process.argv): boolean {\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n if (a === '--format=json') return true;\n if (a === '--format' && argv[i + 1] === 'json') return true;\n }\n return false;\n}\n\n/** Print a verb schema as a single pretty-printed JSON object to stdout. */\nexport function emitSchema(schema: VerbSchema): void {\n console.log(JSON.stringify(schema, null, 2));\n}\n\n/**\n * Attach `--help --format json` schema output to a command. When help is\n * requested with an explicit `--format json`, the schema is printed to stdout\n * and an empty string is returned so commander prints nothing further and exits\n * cleanly. Otherwise the original (text) help is rendered unchanged.\n */\nexport function attachSchemaHelp(cmd: Command, schema: VerbSchema): Command {\n const baseHelp = cmd.helpInformation.bind(cmd);\n cmd.helpInformation = (context) => {\n if (!wantsJsonSchema()) return baseHelp(context);\n emitSchema(schema);\n return '';\n };\n return cmd;\n}\n\n// ============================================================\n// Ride-elife verb schemas\n// ============================================================\n//\n// Flags / response are kept aligned with each command's ACTUAL flags and the\n// cli-core response types (QuoteResponse / BookResponse / GetOrderResponse /\n// CancelResponse / ListOrdersResponse). Notably: quote's passenger fields are\n// optional here (the command only sends them when set); get's pickup/dropoff\n// are `from_location` / `to_location` (v3 snake_case, NOT elife from/to);\n// amounts are decimal currency units (NOT cents).\n\n/** `ride-elife quote` schema (§4.4.1.3 quote schema). */\nexport const quoteSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'quote',\n description: 'Request fare quotes for a ride between two points',\n flags: {\n 'pickup-lat': { type: 'float', required: true, description: 'Pickup latitude', constraints: '-90 to 90' },\n 'pickup-lng': { type: 'float', required: true, description: 'Pickup longitude', constraints: '-180 to 180' },\n 'pickup-name': { type: 'string', required: true, description: 'Pickup location name' },\n 'dropoff-lat': { type: 'float', required: true, description: 'Dropoff latitude', constraints: '-90 to 90' },\n 'dropoff-lng': { type: 'float', required: true, description: 'Dropoff longitude', constraints: '-180 to 180' },\n 'dropoff-name': { type: 'string', required: true, description: 'Dropoff location name' },\n 'pickup-time': {\n type: 'int|string',\n required: true,\n description: \"Epoch seconds or the literal 'now'\",\n },\n 'passenger-name': { type: 'string', required: false, description: 'Lead passenger full name' },\n 'passenger-phone': { type: 'string', required: false, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\n 'passenger-count': { type: 'int', required: false, description: 'Number of passengers' },\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\n 'passenger-email': { type: 'string', required: false, description: 'Passenger email address' },\n 'children-count': { type: 'int', required: false, description: 'Number of children' },\n },\n response: {\n vehicle_classes: {\n type: 'array',\n description: 'Available vehicle options with pricing',\n items: {\n vehicle_class: { type: 'string', description: 'Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\n 'price.amount': { type: 'float', description: 'Price in currency units (e.g. 42.50), NOT cents' },\n 'price.currency': { type: 'string', description: 'ISO 4217 (e.g. USD)' },\n 'price.quote_id': { type: 'string', description: 'Use this in `ride-elife book --quote-id`' },\n passenger_capacity: { type: 'int', description: 'Max passengers' },\n luggage_capacity: { type: 'int', description: 'Max luggage items' },\n },\n },\n meet_and_greet: { type: 'object|null', description: 'Meet & greet availability and price' },\n is_airport_transfer: { type: 'bool', description: 'Whether this is an airport transfer' },\n airport_direction: { type: 'string|null', description: 'pickup / dropoff / null' },\n },\n example: {\n command:\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',\n output_summary:\n 'Returns vehicle_classes[] with a quote_id per option. Use quote_id and vehicle_class for booking.',\n },\n error_recovery: {\n VEHICLE_UNAVAILABLE: 'No vehicles for this route/time. Try a different pickup-time or location. Do NOT blindly retry.',\n PARAM_INVALID: 'Fix the offending flag (coordinates must be numbers; required pickup/dropoff/pickup-time present), then retry.',\n },\n};\n\n/** `ride-elife book` schema (§4.4.1.3 book schema). Write op (W/Y). */\nexport const bookSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'book',\n description: 'Book a ride using a quote_id returned by a previous quote call',\n flags: {\n 'quote-id': { type: 'string', required: true, description: 'Quote id from quote response (vehicle_classes[].price.quote_id)' },\n 'vehicle-class': { type: 'string', required: true, description: 'Vehicle class: Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\n 'price-amount': { type: 'float', required: true, description: 'Fare in decimal currency units (NOT cents), from the quote' },\n 'price-currency': { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code' },\n 'payment-order-id': {\n type: 'string',\n required: 'conditional',\n description: 'Required when billing_mode=pay_per_call (a PAID payment order). Forbidden when billing_mode=monthly_settlement',\n },\n 'passenger-name': { type: 'string', required: true, description: 'Passenger full name' },\n 'passenger-phone': { type: 'string', required: true, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\n 'passenger-email': { type: 'string', required: true, description: 'Passenger email (required by eLife for booking)' },\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\n 'special-requests': { type: 'string', required: false, description: 'Free-text special requests or notes' },\n 'pickup-lat': { type: 'float', required: false, description: 'Pickup latitude (must match the quote)', constraints: '-90 to 90' },\n 'pickup-lng': { type: 'float', required: false, description: 'Pickup longitude (must match the quote)', constraints: '-180 to 180' },\n 'pickup-name': { type: 'string', required: false, description: 'Pickup location name (must match the quote)' },\n 'dropoff-lat': { type: 'float', required: false, description: 'Dropoff latitude (must match the quote)', constraints: '-90 to 90' },\n 'dropoff-lng': { type: 'float', required: false, description: 'Dropoff longitude (must match the quote)', constraints: '-180 to 180' },\n 'dropoff-name': { type: 'string', required: false, description: 'Dropoff location name (must match the quote)' },\n 'pickup-time': { type: 'int|string', required: false, description: \"Epoch seconds or 'now' (must match the quote)\" },\n 'meet-and-greet': { type: 'bool', required: false, default: false, description: 'Enable meet & greet service' },\n 'meet-and-greet-price': { type: 'float', required: false, description: 'Meet & greet surcharge from the quote (meet_and_greet.price.amount)' },\n 'welcome-sign': { type: 'string', required: false, description: 'Welcome sign text (meet & greet)' },\n 'child-seat-count': { type: 'int', required: false, description: 'Number of child seats needed', constraints: '0 to 5' },\n 'infant-seat-count': { type: 'int', required: false, description: 'Number of infant seats needed', constraints: '0 to 5' },\n 'toddler-seat-count': { type: 'int', required: false, description: 'Number of toddler seats needed', constraints: '0 to 5' },\n 'arrival-flight-no': { type: 'string', required: false, description: 'Arrival flight number (airport pickup)' },\n 'arrival-airline': { type: 'string', required: false, description: 'Arrival airline name' },\n 'departure-flight-no': { type: 'string', required: false, description: 'Departure flight number (airport dropoff)' },\n 'departure-airline': { type: 'string', required: false, description: 'Departure airline name' },\n 'idempotency-key': {\n type: 'string',\n required: true,\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\n },\n },\n response: {\n ride_id: { type: 'string|int', description: 'Ride identifier — use for `ride-elife get` / `ride-elife cancel`' },\n order_id: { type: 'string|int', description: 'Internal order id for reconciliation' },\n status: { type: 'string', description: 'Ride status (case-sensitive server casing)' },\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride; false = realtime' },\n order_type: { type: 'string', description: \"'realtime' or 'airport'\" },\n price: { type: 'object', description: '{ amount, currency, quote_id }' },\n payment_status: { type: 'string', description: 'PAID (pay_per_call) or ON_ACCOUNT (monthly_settlement)' },\n billing_entry_id: { type: 'string|absent', description: 'Only in monthly_settlement mode' },\n payment_order_id: { type: 'string|absent', description: 'Only in pay_per_call mode (echoes the request)' },\n },\n example: {\n command:\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',\n output_summary: 'Returns ride_id. Use ride_id in `ride-elife get` to poll status.',\n },\n error_recovery: {\n QUOTE_EXPIRED: \"Re-invoke 'quote' for a fresh quote_id, then retry 'book' with the SAME --idempotency-key.\",\n BILLING_MODE_MISMATCH: 'Check Developer.billing_mode. pay_per_call requires --payment-order-id; monthly_settlement forbids it.',\n PAYMENT_ORDER_NOT_PAID: 'Wait for the payment order status=PAID, then retry with the SAME --idempotency-key.',\n PAYMENT_ORDER_ALREADY_CONSUMED: 'Create a new payment order, then retry with the new payment-order-id and a NEW --idempotency-key.',\n ACCOUNT_INSUFFICIENT_BALANCE: 'Top up the settlement account (offline) or pick a cheaper vehicle_class, then retry.',\n BOOKING_FAILED: 'elife rejected after settlement. The message contains a ref: for manual reconciliation. Do NOT auto-retry.',\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\n },\n};\n\n/** `ride-elife get` schema (§4.4.1.3 get schema). Read-only, supports `--watch`. */\nexport const rideGetSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'get',\n description: 'Retrieve a ride order status by id; with --watch, poll until a terminal status',\n flags: {\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' },\n watch: { type: 'bool', required: false, default: false, description: 'Poll until a terminal status, emitting one NDJSON line per update' },\n 'watch-interval': { type: 'int', required: false, default: DEFAULT_WATCH_INTERVAL_SECONDS, description: 'Seconds between polls when --watch is set' },\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll before giving up' },\n },\n response: {\n ride_id: { type: 'string|int', description: 'Ride identifier' },\n status: { type: 'string', description: 'Pending / Accepted / On my way / Waiting / On board / At destination / Rejected / Cancelled / Customer no show / Driver no show' },\n source: { type: 'string', description: \"'local_cache' when served from the local fallback; 'mock' in sandbox\" },\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride' },\n from_location: { type: 'object', description: 'Pickup { lat, lng, name, address } (v3 snake_case, NOT elife from/to)' },\n to_location: { type: 'object', description: 'Dropoff { lat, lng, name, address }' },\n pickup_time: { type: 'int|string', description: 'Pickup time' },\n vehicle_class: { type: 'string|null', description: 'Vehicle class' },\n price: { type: 'object', description: '{ amount, currency, quote_id }' },\n final_amount: { type: 'float|null', description: 'Final settled fare (realtime, after final-fare settlement)' },\n final_settlement_status: { type: 'string', description: 'pending / settled / no_adjustment / settlement_pending / not_applicable' },\n driver: { type: 'object|null', description: '{ name, phone_number } — available after a driver is assigned' },\n vehicle: { type: 'object|null', description: '{ make, model, color, license_plate, image_url } — available after a driver is assigned' },\n created_at: { type: 'string', description: 'Order creation time' },\n },\n example: {\n command: 'agenzo-merchant-cli ride-elife get --order-id EL-20260527-1023456',\n output_summary:\n 'Returns current status and driver/vehicle info. Terminal statuses: At destination, Cancelled, Rejected, Customer no show, Driver no show.',\n },\n polling: {\n recommended_interval_seconds: DEFAULT_WATCH_INTERVAL_SECONDS,\n terminal_statuses: [...TERMINAL_STATUSES],\n in_progress_statuses: ['Pending', 'Accepted', 'On my way', 'Waiting', 'On board'],\n field_availability: {\n driver: \"Populated from status 'Accepted' onwards (after a driver is dispatched). Null in 'Pending'.\",\n vehicle: \"Populated from status 'Accepted' onwards. Null in 'Pending'.\",\n },\n },\n error_recovery: {\n VEHICLE_UNAVAILABLE: 'Order not found. Verify --order-id is the ride_id from book. Do NOT retry.',\n BOOKING_FAILED: 'Transient elife error. Retry once after 5s.',\n },\n};\n\n/** `ride-elife cancel` schema (§4.4.1.3 cancel schema). Write op (W/Y). */\nexport const cancelSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'cancel',\n description: 'Cancel a ride order by id (a cancellation fee may apply depending on ride status)',\n flags: {\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' },\n 'idempotency-key': {\n type: 'string',\n required: true,\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\n },\n },\n response: {\n ride_id: { type: 'string|int', description: 'Cancelled ride id' },\n ride_stat: { type: 'string', description: \"Status after cancellation (typically 'Cancelled')\" },\n cancellation: {\n type: 'object|null',\n description: 'Cancellation details',\n properties: {\n cancellation_fee: { type: 'float', description: 'Fee charged for cancellation' },\n reversal_amount: { type: 'float', description: 'Amount reversed/refunded' },\n currency: { type: 'string', description: 'ISO 4217 currency code' },\n },\n },\n refund_amount: { type: 'float', description: 'Amount credited back to the settlement balance (paid − cancellation_fee)' },\n },\n example: {\n command: 'agenzo-merchant-cli ride-elife cancel --order-id EL-20260527-1023456 --idempotency-key cancel-456',\n output_summary: 'Returns cancellation fee and refund amount.',\n },\n error_recovery: {\n CANCELLATION_NOT_ALLOWED: 'The ride is in a non-cancellable state. Do NOT retry; query status with `ride-elife get`.',\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\n },\n};\n\n/** `ride-elife list-orders` schema (§4.4.1.3 list-orders schema). Read-only. */\nexport const listOrdersSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'list-orders',\n description: 'List previously placed ride orders with optional filters and pagination',\n flags: {\n status: { type: 'string', required: false, description: 'Filter by ride status (case-sensitive server casing)' },\n 'order-type': { type: 'string', required: false, description: 'Filter by order type (e.g. realtime / airport)' },\n page: { type: 'int', required: false, default: 1, description: 'Page number', constraints: '>= 1' },\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page', constraints: '>= 1' },\n },\n response: {\n orders: {\n type: 'array',\n description: 'List of ride orders (slim list-item shape)',\n items: {\n order_id: { type: 'string', description: 'Internal order id' },\n ride_id: { type: 'string', description: 'Ride id (same as ride_id from book)' },\n status: { type: 'string', description: 'Current ride status' },\n vehicle_class: { type: 'string', description: 'Vehicle class' },\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport, false = realtime' },\n scheduled_at: { type: 'string', description: 'ISO 8601 datetime; empty for realtime orders' },\n price_amount: { type: 'float|null', description: 'Price in decimal currency units (NOT cents)' },\n final_amount: { type: 'float|null', description: 'Final settled amount' },\n price_currency: { type: 'string', description: 'ISO 4217 currency code' },\n payment_status: { type: 'string', description: 'Payment status' },\n final_settlement_status: { type: 'string', description: 'pending / settled / no_adjustment / settlement_pending / not_applicable' },\n cancellation_fee: { type: 'float|null', description: 'Cancellation fee for cancelled orders; null otherwise' },\n provider: { type: 'string', description: 'Service provider (elife)' },\n created_at: { type: 'string|null', description: 'Order creation time (ISO 8601)' },\n updated_at: { type: 'string|null', description: 'Last update time (ISO 8601)' },\n },\n },\n total: { type: 'int', description: 'Total matching orders' },\n page: { type: 'int', description: 'Current page' },\n page_size: { type: 'int', description: 'Items per page' },\n },\n example: {\n command: 'agenzo-merchant-cli ride-elife list-orders --status Pending --page 1 --page-size 10',\n output_summary: 'Returns a paginated list of ride orders with status and amount info.',\n },\n error_recovery: {\n INTERNAL_ERROR: 'Transient backend error. Retry once after a short delay.',\n PARAM_INVALID: 'Ensure --page / --page-size are positive integers, then retry.',\n },\n};\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { QuoteResponse, VehicleClass } from '../types/api.js';\nimport { attachSchemaHelp, quoteSchema } from '../verb-schema.js';\n\n// ============================================================\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\n// ============================================================\n\n/**\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\n * (requirement 2.1 / design §4.4.1.3) — a catalog code (exit 1), never\n * `PARAM_REQUIRED` (not in the cli-core error catalog).\n */\nfunction need(value: string | undefined, flag: string): string {\n if (value === undefined) {\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\n }\n return value;\n}\n\n/**\n * Number-ify a coordinate / numeric flag. Non-finite input maps to\n * `PARAM_INVALID`. Coordinates are sent as numbers, never strings (§4.4.1.3).\n */\nfunction num(value: string | undefined, flag: string): number {\n const n = Number(need(value, flag));\n if (!Number.isFinite(n)) {\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\n }\n return n;\n}\n\n// ============================================================\n// Output helper (table summary)\n// ============================================================\n\n/**\n * Render the quote as a table for `--format table`. Each vehicle class is one\n * row; amounts are decimal currency units (NOT cents) — printed verbatim.\n */\nfunction formatQuote(data: QuoteResponse): string {\n const classes: VehicleClass[] = data.vehicle_classes ?? [];\n if (classes.length === 0) {\n return Formatter.status('info', 'No vehicle classes available for this route');\n }\n\n const headers = ['Vehicle Class', 'Price', 'Currency', 'Quote ID', 'Pax', 'Luggage'];\n const rows = classes.map((vc) => [\n String(vc.vehicle_class ?? '-'),\n String(vc.price?.amount ?? '-'),\n String(vc.price?.currency ?? '-'),\n String(vc.price?.quote_id ?? '-'),\n String(vc.passenger_capacity ?? '-'),\n String(vc.luggage_capacity ?? '-'),\n ]);\n\n const lines: [string, string][] = [\n ['Airport transfer', String(data.is_airport_transfer ?? false)],\n ];\n if (data.airport_direction) {\n lines.push(['Airport direction', String(data.airport_direction)]);\n }\n if (data.meet_and_greet) {\n const mg = data.meet_and_greet;\n const mgPrice = mg.price ? ` (${mg.price.amount} ${mg.price.currency})` : '';\n lines.push(['Meet & greet', `${mg.available ? 'available' : 'unavailable'}${mgPrice}`]);\n }\n\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(lines)}`;\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife quote` — request fare quotes between two points (§4.4.1.3).\n *\n * Read-only (no idempotency key). Builds the `/ride/quote` body from flags\n * (coordinates number-ified, missing required → `PARAM_INVALID`), POSTs with\n * the `X-Api-Key` auth, and renders `QuoteResponse` via `renderWithContext`\n * (json carries the profile/endpoint envelope). The progress line is emitted\n * through `notify` so it goes to stderr and stays silent in json mode.\n */\nexport function registerQuoteCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('quote')\n .description('Request fare quotes for a ride between two points')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--pickup-lat <lat>', 'Pickup latitude')\n .option('--pickup-lng <lng>', 'Pickup longitude')\n .option('--pickup-name <name>', 'Pickup location name')\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\n .option('--dropoff-name <name>', 'Dropoff location name')\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\n .option('--passenger-name <name>', 'Lead passenger full name')\n .option('--passenger-phone <phone>', 'Passenger phone (E.164)')\n .option('--passenger-count <n>', 'Passenger count')\n .option('--luggage-count <n>', 'Luggage count')\n .option('--passenger-email <email>', 'Passenger email')\n .option('--children-count <n>', 'Children count');\n\n attachSchemaHelp(cmd, quoteSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // Build request body. Coordinates are number-ified; pickup_time accepts the\n // literal \"now\" or epoch seconds. Missing required fields throw\n // PARAM_INVALID before any request is sent.\n const body: Record<string, unknown> = {\n pickup: {\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\n },\n dropoff: {\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\n },\n pickup_time:\n opts.pickupTime === 'now'\n ? 'now'\n : num(opts.pickupTime as string | undefined, 'pickup-time'),\n };\n\n // Optional passenger / luggage / children fields — included only when set.\n if (opts.passengerName) body.passenger_name = opts.passengerName as string;\n if (opts.passengerPhone) body.passenger_phone = opts.passengerPhone as string;\n if (opts.passengerCount !== undefined) {\n body.passenger_count = num(opts.passengerCount as string, 'passenger-count');\n }\n if (opts.luggageCount !== undefined) {\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\n }\n if (opts.childrenCount !== undefined) {\n body.children_count = num(opts.childrenCount as string, 'children-count');\n }\n if (opts.passengerEmail !== undefined) {\n body.passenger_email = opts.passengerEmail as string;\n }\n\n // Progress line: stderr in table mode, silent in json mode.\n notify(format, 'loading', 'Fetching quotes...');\n\n const result = await deps.apiClient.post<QuoteResponse>(\n '/ride/quote',\n { type: 'api-key', key: apiKey },\n body,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<QuoteResponse> = {\n data,\n text: () => formatQuote(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport { confirm } from '@inquirer/prompts';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { BookResponse } from '../types/api.js';\nimport { attachSchemaHelp, bookSchema } from '../verb-schema.js';\nimport { resolveIdempotencyKey } from '../idempotency.js';\n\n// ============================================================\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\n// ============================================================\n\n/**\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\n * (requirement 2.2 / design §4.4.1.3) — a catalog code (exit 1), mirroring the\n * sibling `quote` command's convention.\n */\nfunction need(value: string | undefined, flag: string): string {\n if (value === undefined) {\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\n }\n return value;\n}\n\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\nfunction num(value: string | undefined, flag: string): number {\n const n = Number(need(value, flag));\n if (!Number.isFinite(n)) {\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\n }\n return n;\n}\n\n/**\n * Number-ify a seat count and enforce the 0–5 range (design §4.4.1.3 book\n * schema). Out-of-range values map to `PARAM_INVALID`.\n */\nfunction seatCount(value: string, flag: string): number {\n const n = num(value, flag);\n if (!Number.isInteger(n) || n < 0 || n > 5) {\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer between 0 and 5.`);\n }\n return n;\n}\n\n// ============================================================\n// Output helper (table summary)\n// ============================================================\n\n/**\n * Render a booked ride as a key/value block for `--format table`. Amounts are\n * decimal currency units (NOT cents) — printed verbatim.\n */\nfunction formatBook(data: BookResponse): string {\n const lines: [string, string][] = [\n ['Ride ID', String(data.ride_id ?? '-')],\n ['Order ID', String(data.order_id ?? '-')],\n ['Status', String(data.status ?? '-')],\n ['Scheduled', String(data.is_scheduled ?? false)],\n ['Order type', String(data.order_type ?? '-')],\n ];\n if (data.price) {\n lines.push(['Price', `${data.price.amount} ${data.price.currency}`]);\n if (data.price.quote_id) lines.push(['Quote ID', String(data.price.quote_id)]);\n }\n lines.push(['Payment status', String(data.payment_status ?? '-')]);\n // Mode-dependent: monthly_settlement returns billing_entry_id, pay_per_call\n // echoes back payment_order_id.\n if (data.billing_entry_id) lines.push(['Billing entry', String(data.billing_entry_id)]);\n if (data.payment_order_id) lines.push(['Payment order', String(data.payment_order_id)]);\n\n return Formatter.keyValue(lines);\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife book` — book a ride against a previously returned quote\n * (§4.4.1.3 book schema + §4.4.2.1). Write op (W/Y).\n *\n * Funding is decided server-side by the developer's `billing_mode`:\n * - monthly_settlement: no payment handle; fare is deducted from the\n * settlement account (payment_status=ON_ACCOUNT).\n * - pay_per_call: pass `--payment-order-id` (a PAID order from payment-cli).\n * The CLI MUST NOT accept `--payment-method-id` or card info — the merchant\n * domain never holds a payment credential, so the request body carries at most\n * an optional `payment_order_id` (design Property 5).\n *\n * `POST /ride/book` with `X-Api-Key` auth + the `Idempotency-Key` header (key\n * forwarded verbatim, never in the body). `--yes` skips the confirm; a missing\n * `--idempotency-key` under `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED`\n * before any request is sent. Renders `BookResponse` via `renderWithContext`\n * (json carries the profile/endpoint envelope); the progress line goes to\n * stderr via `notify` and stays silent in json mode.\n */\nexport function registerBookCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('book')\n .description('Book a ride using a quote_id returned by quote')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--quote-id <id>', 'Quote id from `ride-elife quote`')\n .option('--vehicle-class <class>', 'Chosen vehicle class')\n .option('--price-amount <amount>', 'Fare in decimal currency units (not cents)')\n .option('--price-currency <currency>', 'Currency code (default USD)')\n .option('--payment-order-id <id>', 'Paid payment order id (pay_per_call mode only)')\n .option('--passenger-name <name>', 'Passenger full name')\n .option('--passenger-phone <phone>', 'Passenger phone')\n .option('--passenger-email <email>', 'Passenger email')\n .option('--luggage-count <n>', 'Luggage count')\n .option('--special-requests <text>', 'Free-text special requests')\n .option('--pickup-lat <lat>', 'Pickup latitude')\n .option('--pickup-lng <lng>', 'Pickup longitude')\n .option('--pickup-name <name>', 'Pickup location name')\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\n .option('--dropoff-name <name>', 'Dropoff location name')\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\n .option('--meet-and-greet', 'Enable meet & greet service')\n .option('--meet-and-greet-price <amount>', 'Meet & greet surcharge')\n .option('--welcome-sign <text>', 'Welcome sign text')\n .option('--child-seat-count <n>', 'Number of child seats needed (0-5)')\n .option('--infant-seat-count <n>', 'Number of infant seats needed (0-5)')\n .option('--toddler-seat-count <n>', 'Number of toddler seats needed (0-5)')\n .option('--arrival-flight-no <no>', 'Arrival flight number')\n .option('--arrival-airline <airline>', 'Arrival airline')\n .option('--departure-flight-no <no>', 'Departure flight number')\n .option('--departure-airline <airline>', 'Departure airline')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n attachSchemaHelp(cmd, bookSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n const isYes = Boolean(opts.yes);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // Build request body. Required fields throw PARAM_INVALID before any\n // request is sent (mirrors the sibling `quote` command). The body carries\n // NO payment_method_id / card info — at most an optional payment_order_id\n // (design Property 5); funding is decided server-side by billing_mode.\n const quoteId = need(opts.quoteId as string | undefined, 'quote-id');\n const body: Record<string, unknown> = {\n quote_id: quoteId,\n vehicle_class: need(opts.vehicleClass as string | undefined, 'vehicle-class'),\n price_amount: num(opts.priceAmount as string | undefined, 'price-amount'),\n price_currency: (opts.priceCurrency as string | undefined) ?? 'USD',\n passenger_name: need(opts.passengerName as string | undefined, 'passenger-name'),\n passenger_phone: need(opts.passengerPhone as string | undefined, 'passenger-phone'),\n };\n\n // pay_per_call: optional paid payment order id (the only payment handle the\n // merchant CLI ever forwards). monthly_settlement omits it entirely.\n if (opts.paymentOrderId) body.payment_order_id = opts.paymentOrderId as string;\n if (opts.passengerEmail) body.passenger_email = opts.passengerEmail as string;\n if (opts.luggageCount !== undefined) {\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\n }\n if (opts.specialRequests) body.special_requests = opts.specialRequests as string;\n\n // Pickup / dropoff / pickup_time are included only when supplied (they must\n // match the originating quote). Coordinates are number-ified.\n if (opts.pickupLat || opts.pickupLng || opts.pickupName) {\n body.pickup = {\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\n };\n }\n if (opts.dropoffLat || opts.dropoffLng || opts.dropoffName) {\n body.dropoff = {\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\n };\n }\n if (opts.pickupTime) {\n body.pickup_time =\n opts.pickupTime === 'now' ? 'now' : num(opts.pickupTime as string, 'pickup-time');\n }\n\n if (opts.meetAndGreet) body.meet_and_greet = true;\n if (opts.meetAndGreetPrice !== undefined) {\n body.meet_and_greet_price = num(opts.meetAndGreetPrice as string, 'meet-and-greet-price');\n }\n if (opts.welcomeSign) body.welcome_sign = opts.welcomeSign as string;\n if (opts.childSeatCount !== undefined) {\n body.child_seat_count = seatCount(opts.childSeatCount as string, 'child-seat-count');\n }\n if (opts.infantSeatCount !== undefined) {\n body.infant_seat_count = seatCount(opts.infantSeatCount as string, 'infant-seat-count');\n }\n if (opts.toddlerSeatCount !== undefined) {\n body.toddler_seat_count = seatCount(opts.toddlerSeatCount as string, 'toddler-seat-count');\n }\n if (opts.arrivalFlightNo || opts.arrivalAirline) {\n body.arrival_flight = {\n flight_no: opts.arrivalFlightNo as string | undefined,\n airline: opts.arrivalAirline as string | undefined,\n };\n }\n if (opts.departureFlightNo || opts.departureAirline) {\n body.departure_flight = {\n flight_no: opts.departureFlightNo as string | undefined,\n airline: opts.departureAirline as string | undefined,\n };\n }\n\n // Confirm before the write unless --yes. The warning/prompt go to stderr;\n // declining maps to CLIENT_ABORTED (exit 5) via the top-level envelope.\n if (!isYes) {\n const confirmed = await confirm({\n message: `Book ride with quote ${quoteId}?`,\n default: true,\n });\n if (!confirmed) {\n throw new CliError('CLIENT_ABORTED', 'Booking cancelled by user.');\n }\n }\n\n // Idempotency key (requirement 5.3): resolved before the request. Under\n // --yes a missing key is a hard error and no request is sent. The key is\n // sent as a header, never in the body.\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\n yes: isYes,\n commandPath: 'ride-elife book',\n });\n\n // Progress line: stderr in table mode, silent in json mode.\n notify(format, 'loading', 'Booking ride...');\n\n const result = await deps.apiClient.post<BookResponse>(\n '/ride/book',\n { type: 'api-key', key: apiKey },\n body,\n { 'Idempotency-Key': idempotencyKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<BookResponse> = {\n data,\n text: () => formatBook(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","/**\n * Idempotency key resolution for write commands (`ride-elife book` / `cancel`)\n * — requirement 5.3 / §6.1, design Property 3.\n *\n * The error type is reused from `@agenzo/cli-core` (`IdempotencyKeyRequiredError`\n * → `PARAM_IDEMPOTENCY_KEY_REQUIRED`) so the merchant CLI does not re-define it.\n * The resolve/normalize logic stays in the app because it is merchant-domain\n * policy (per requirement 4.4): the §6.1 key format `[A-Za-z0-9_-]{1,128}`, the\n * `--yes`-missing hard error vs. interactive prompt branch, and the rule that\n * the key is forwarded verbatim as the `Idempotency-Key` HTTP header and is\n * never placed in the request body.\n *\n * The CLI NEVER auto-generates a key: under `--yes` a missing key is a hard\n * error thrown before any request is sent; otherwise the caller is prompted.\n */\nimport {\n CliError,\n IdempotencyKeyRequiredError,\n PromptEngine,\n} from '@agenzo/cli-core';\n\n/**\n * §6.1 idempotency key format: 1–128 characters drawn from `[A-Za-z0-9_-]`.\n */\nexport const IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;\n\n/** Human-readable rule reused in validation messages and prompt feedback. */\nexport const IDEMPOTENCY_KEY_RULE = 'Use 1-128 characters from [A-Za-z0-9_-].';\n\n/**\n * Validate + normalize a caller-supplied idempotency key. A malformed key maps\n * to `PARAM_INVALID` (catalog code, exit 1) — never silently corrected and\n * never auto-generated.\n */\nexport function normalizeIdempotencyKey(key: string): string {\n const trimmed = key.trim();\n if (!IDEMPOTENCY_KEY_PATTERN.test(trimmed)) {\n throw new CliError(\n 'PARAM_INVALID',\n `Invalid idempotency key: \"${key}\". ${IDEMPOTENCY_KEY_RULE}`,\n );\n }\n return trimmed;\n}\n\n/**\n * Resolve the idempotency key for a write operation (requirement 5.3). The CLI\n * never generates one:\n * - supplied via `--idempotency-key` → validated + normalized;\n * - absent under `--yes` → hard error (`PARAM_IDEMPOTENCY_KEY_REQUIRED`,\n * reused from cli-core) thrown before any request is sent;\n * - absent otherwise → collected interactively, then validated.\n *\n * The returned key is forwarded verbatim as the `Idempotency-Key` header by the\n * caller — it never enters the request body.\n */\nexport async function resolveIdempotencyKey(\n flagValue: string | undefined,\n opts: { yes: boolean; commandPath: string },\n): Promise<string> {\n if (flagValue !== undefined) {\n return normalizeIdempotencyKey(flagValue);\n }\n if (opts.yes) {\n throw new IdempotencyKeyRequiredError(opts.commandPath);\n }\n const entered = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => IDEMPOTENCY_KEY_PATTERN.test(v.trim()) || IDEMPOTENCY_KEY_RULE,\n });\n return normalizeIdempotencyKey(entered);\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { GetOrderResponse } from '../types/api.js';\nimport {\n DEFAULT_WATCH_INTERVAL_SECONDS,\n DEFAULT_WATCH_TIMEOUT_SECONDS,\n resolveSeconds,\n watchRideStatus,\n} from './watch.js';\nimport { attachSchemaHelp, rideGetSchema } from '../verb-schema.js';\n\n// ============================================================\n// Input helpers (ride-domain — stays in app per req 4.4)\n// ============================================================\n\n/**\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\n * (requirement 3.1 / §4.4.1.3) — a catalog code (exit 1), mirroring the\n * sibling quote/book commands' convention.\n */\nfunction need(value: string | undefined, flag: string): string {\n if (value === undefined) {\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\n }\n return value;\n}\n\n// ============================================================\n// Output helper (table summary, non-watch path only)\n// ============================================================\n\n/**\n * Render a single ride order as a key/value block for `--format table`.\n * Pickup/dropoff are `from_location`/`to_location` (v3 snake_case, NOT the\n * elife `from`/`to` aliases). Amounts are decimal currency units (NOT cents).\n */\nfunction formatGetOrder(data: GetOrderResponse): string {\n const lines: [string, string][] = [\n ['Ride ID', String(data.ride_id ?? '-')],\n ['Status', String(data.status ?? '-')],\n ];\n if (data.source) lines.push(['Source', String(data.source)]);\n if (data.is_scheduled !== undefined) lines.push(['Scheduled', String(data.is_scheduled)]);\n if (data.from_location) {\n lines.push(['From', String(data.from_location.name ?? '-')]);\n }\n if (data.to_location) {\n lines.push(['To', String(data.to_location.name ?? '-')]);\n }\n if (data.pickup_time !== undefined) lines.push(['Pickup time', String(data.pickup_time)]);\n if (data.vehicle_class) lines.push(['Vehicle class', String(data.vehicle_class)]);\n if (data.price) {\n lines.push(['Price', `${data.price.amount} ${data.price.currency}`]);\n }\n if (data.final_amount !== undefined && data.final_amount !== null) {\n lines.push(['Final amount', String(data.final_amount)]);\n }\n if (data.final_settlement_status) {\n lines.push(['Settlement', String(data.final_settlement_status)]);\n }\n if (data.driver) {\n const driver = data.driver;\n const phone = driver.phone_number ? ` (${driver.phone_number})` : '';\n lines.push(['Driver', `${driver.name ?? '-'}${phone}`]);\n }\n if (data.vehicle) {\n const v = data.vehicle;\n const desc = [v.color, v.make, v.model].filter(Boolean).join(' ') || '-';\n const plate = v.license_plate ? ` [${v.license_plate}]` : '';\n lines.push(['Vehicle', `${desc}${plate}`]);\n }\n if (data.created_at) lines.push(['Created at', String(data.created_at)]);\n\n return Formatter.keyValue(lines);\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife get` — fetch a ride order status by id (§4.4.1.3 get schema).\n * Read-only (no idempotency key).\n *\n * Two modes:\n * - Non-`--watch`: a single `GET /ride/<id>/status` → `CommandResult` +\n * `renderWithContext` (json carries the profile/endpoint envelope).\n * - `--watch`: hands off to `watch.ts`, which polls until a terminal status\n * or timeout, writing each result as ONE NDJSON line on stdout. The watch\n * stream is NOT wrapped in the profile/endpoint envelope (it is a line\n * stream); on timeout the final line is `{ watch_status:'timeout', ... }`\n * (design Property 2).\n *\n * Named `registerRideGetCommand` to avoid clashing with the `services get`\n * registration.\n */\nexport function registerRideGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('get')\n .description('Retrieve a ride order status by id (repeatable for polling)')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--order-id <id>', 'Ride order id (the ride_id returned by `ride-elife book`)')\n .option('--watch', 'Poll until a terminal status, emitting one NDJSON line per update')\n .option(\n '--watch-interval <seconds>',\n `Seconds between polls when --watch is set (default ${DEFAULT_WATCH_INTERVAL_SECONDS})`,\n )\n .option(\n '--watch-timeout <seconds>',\n `Max seconds to poll before giving up (default ${DEFAULT_WATCH_TIMEOUT_SECONDS})`,\n );\n\n attachSchemaHelp(cmd, rideGetSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n const orderId = need(opts.orderId as string | undefined, 'order-id');\n\n // --watch: NDJSON line stream (no profile/endpoint envelope). The stream\n // itself is the progress, so no spinner/notify is emitted.\n if (opts.watch) {\n await watchRideStatus(deps.apiClient, apiKey, orderId, {\n intervalSeconds: resolveSeconds(\n opts.watchInterval as string | undefined,\n DEFAULT_WATCH_INTERVAL_SECONDS,\n ),\n timeoutSeconds: resolveSeconds(\n opts.watchTimeout as string | undefined,\n DEFAULT_WATCH_TIMEOUT_SECONDS,\n ),\n });\n return;\n }\n\n // Single-shot: progress line on stderr (silent in json mode).\n notify(format, 'loading', 'Fetching ride status...');\n\n const result = await deps.apiClient.get<GetOrderResponse>(\n `/ride/${encodeURIComponent(orderId)}/status`,\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<GetOrderResponse> = {\n data,\n text: () => formatGetOrder(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport { confirm } from '@inquirer/prompts';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { CancelResponse } from '../types/api.js';\nimport { attachSchemaHelp, cancelSchema } from '../verb-schema.js';\nimport { resolveIdempotencyKey } from '../idempotency.js';\n\n// ============================================================\n// Input helpers (ride-domain — stays in app per req 4.4)\n// ============================================================\n\n/**\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\n * (requirement 3.3 / §4.4.1.3 cancel schema) — a catalog code (exit 1),\n * mirroring the sibling quote/book/get commands' convention.\n */\nfunction need(value: string | undefined, flag: string): string {\n if (value === undefined) {\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\n }\n return value;\n}\n\n// ============================================================\n// Output helper (table summary)\n// ============================================================\n\n/**\n * Render a cancelled ride as a key/value block for `--format table`. Amounts\n * are decimal currency units (NOT cents) — printed verbatim. `cancellation`\n * may be null when the backend reports no fee/reversal breakdown.\n */\nfunction formatCancel(data: CancelResponse): string {\n const lines: [string, string][] = [\n ['Ride ID', String(data.ride_id ?? '-')],\n ['Status', String(data.ride_stat ?? '-')],\n ];\n if (data.cancellation) {\n const c = data.cancellation;\n lines.push(['Cancellation fee', `${c.cancellation_fee} ${c.currency}`]);\n lines.push(['Reversal amount', `${c.reversal_amount} ${c.currency}`]);\n }\n if (data.refund_amount !== undefined && data.refund_amount !== null) {\n lines.push(['Refund amount', String(data.refund_amount)]);\n }\n\n return Formatter.keyValue(lines);\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife cancel` — cancel a ride order by id (§4.4.1.3 cancel schema).\n * Write op (W/Y).\n *\n * `POST /ride/<order-id>/cancel` with NO request body, `X-Api-Key` auth, and\n * the `Idempotency-Key` header (key forwarded verbatim, never in the body).\n * Cancelling may incur a fee, so the non-`--yes` path MUST confirm before the\n * write; `--yes` skips the confirmation. A missing `--idempotency-key` under\n * `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED` before any request is sent;\n * non-`--yes` prompts for it. Declining the confirmation maps to\n * `CLIENT_ABORTED` (exit 5) via the top-level envelope. Renders\n * `CancelResponse` via `renderWithContext` (json carries the profile/endpoint\n * envelope); the progress line goes to stderr via `notify` and stays silent in\n * json mode.\n */\nexport function registerCancelCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('cancel')\n .description('Cancel a ride order by id (may incur a cancellation fee)')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--order-id <id>', 'Ride order id to cancel (the ride_id returned by book)')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n attachSchemaHelp(cmd, cancelSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n const isYes = Boolean(opts.yes);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // Required input throws PARAM_INVALID before any request is sent (mirrors\n // the sibling get/book commands).\n const orderId = need(opts.orderId as string | undefined, 'order-id');\n\n // Confirm before the write unless --yes. Cancelling may incur a fee, so the\n // prompt warns explicitly (requirement 3.3). The warning/prompt go to\n // stderr; declining maps to CLIENT_ABORTED (exit 5) via the top-level\n // envelope.\n if (!isYes) {\n const confirmed = await confirm({\n message: `Cancel ride ${orderId}? This may incur a fee.`,\n default: false,\n });\n if (!confirmed) {\n throw new CliError('CLIENT_ABORTED', 'Cancellation aborted by user.');\n }\n }\n\n // Idempotency key (requirement 5.3): resolved before the request. Under\n // --yes a missing key is a hard error and no request is sent. The key is\n // sent as a header, never in the body.\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\n yes: isYes,\n commandPath: 'ride-elife cancel',\n });\n\n // Progress line: stderr in table mode, silent in json mode.\n notify(format, 'loading', 'Cancelling ride...');\n\n // POST /ride/<id>/cancel carries NO body — only the Idempotency-Key header.\n const result = await deps.apiClient.post<CancelResponse>(\n `/ride/${encodeURIComponent(orderId)}/cancel`,\n { type: 'api-key', key: apiKey },\n undefined,\n { 'Idempotency-Key': idempotencyKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<CancelResponse> = {\n data,\n text: () => formatCancel(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { ListOrdersResponse, RideOrderListItem } from '../types/api.js';\nimport { attachSchemaHelp, listOrdersSchema } from '../verb-schema.js';\n\n// ============================================================\n// Input helpers (ride-domain — stays in app per req 4.4)\n// ============================================================\n\nconst DEFAULT_PAGE = '1';\nconst DEFAULT_PAGE_SIZE = '20';\n\n/**\n * Number-ify a pagination flag. Non-finite / non-integer / non-positive input\n * maps to `PARAM_INVALID` (catalog code, exit 1) — mirroring the sibling\n * quote/get/cancel commands' convention. Returns the canonical string form to\n * be passed through as a query parameter.\n */\nfunction positiveInt(value: string, flag: string): string {\n const n = Number(value);\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\n }\n return String(n);\n}\n\n// ============================================================\n// Output helper (table summary)\n// ============================================================\n\n/**\n * Render the order list as a table for `--format table`. Each order is one\n * row; amounts are decimal currency units (NOT cents) — printed verbatim.\n */\nfunction formatOrders(data: ListOrdersResponse): string {\n const orders: RideOrderListItem[] = data.orders ?? [];\n if (orders.length === 0) {\n return Formatter.status('info', 'No ride orders found');\n }\n\n const headers = ['Order ID', 'Ride ID', 'Status', 'Vehicle Class', 'Price', 'Currency', 'Payment'];\n const rows = orders.map((o) => [\n String(o.order_id ?? '-'),\n String(o.ride_id ?? '-'),\n String(o.status ?? '-'),\n String(o.vehicle_class ?? '-'),\n String(o.price_amount ?? '-'),\n String(o.price_currency ?? '-'),\n String(o.payment_status ?? '-'),\n ]);\n\n const summary: [string, string][] = [\n ['Total', String(data.total ?? '-')],\n ['Page', String(data.page ?? '-')],\n ['Page size', String(data.page_size ?? '-')],\n ];\n\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(summary)}`;\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife list-orders` — list previously placed ride orders (§4.4.1.3\n * list-orders schema). Read-only (no idempotency key).\n *\n * Passes `--page`(default 1) / `--page-size`(default 20) / `--status` /\n * `--order-type` through as query parameters to `GET /ride/orders` with the\n * `X-Api-Key` auth, and renders `ListOrdersResponse` via `renderWithContext`\n * (json carries the profile/endpoint envelope). `page`/`page-size` are\n * validated as positive integers (invalid → `PARAM_INVALID`); `status` /\n * `order-type` are forwarded verbatim only when set. The progress line is\n * emitted through `notify` so it goes to stderr and stays silent in json mode.\n */\nexport function registerListOrdersCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('list-orders')\n .description('List previously placed ride orders')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--page <page>', 'Page number', DEFAULT_PAGE)\n .option('--page-size <size>', 'Page size', DEFAULT_PAGE_SIZE)\n .option('--status <status>', 'Filter by order status')\n .option('--order-type <type>', 'Filter by order type');\n\n attachSchemaHelp(cmd, listOrdersSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // Build query params. page/page-size are validated as positive integers\n // (invalid → PARAM_INVALID before any request); status/order-type are\n // forwarded verbatim only when set. Sent as a query string, never a body.\n const params: Record<string, string> = {\n page: positiveInt((opts.page as string | undefined) ?? DEFAULT_PAGE, 'page'),\n page_size: positiveInt((opts.pageSize as string | undefined) ?? DEFAULT_PAGE_SIZE, 'page-size'),\n };\n if (opts.status !== undefined) params.status = opts.status as string;\n if (opts.orderType !== undefined) params.order_type = opts.orderType as string;\n\n // Progress line: stderr in table mode, silent in json mode.\n notify(format, 'loading', 'Fetching orders...');\n\n const result = await deps.apiClient.get<ListOrdersResponse>(\n '/ride/orders',\n { type: 'api-key', key: apiKey },\n params,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<ListOrdersResponse> = {\n data,\n text: () => formatOrders(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","/**\n * Built-in static capability registry (D4, merchant-domain only).\n *\n * NOTE: this is a CLI-bundled, single-merchant catalog — NOT a live backend\n * discovery feed. It does not reflect which services are enabled for the\n * current API key, nor the developer's billing mode (that is a per-developer\n * property decided by the backend, surfaced via the `book` response /\n * error codes, not advertised here). The §4.4.1 backend `/services` discovery\n * endpoint (BACK-063) + top-level `billing` block + `page` cursor are pending\n * impl; until they land, `services list/get` read this table.\n *\n * Each entry describes a CLI-exposed service: which `cli_noun` group hosts it,\n * the verbs it offers (with one-line descriptions), the recommended call\n * `workflow`, and discovery hints. `services list` renders a summary of these\n * entries and `services get <service-id>` returns one in full.\n *\n * `ServiceCapability` / the registry are merchant-domain specific (only\n * merchant-cli uses them) and stay in the app — they are NOT lifted to\n * `@agenzo/cli-core`.\n */\n\n/** Discovery hints for a capability (§4.4.1 schema; `schema_url` reserved for backend feed). */\nexport interface ServiceDiscovery {\n /** Command an agent can run to discover the verbs in detail. */\n help_command: string;\n /** Reserved for the backend discovery feed's per-verb JSON schema URL (pending impl). */\n schema_url?: string;\n}\n\nexport interface ServiceCapability {\n service_id: string;\n name: string;\n description: string;\n /** Service category (e.g. `ride`); part of the §4.4.1 schema form. */\n category: string;\n version: string;\n /** Upstream capability provider. */\n provider: string;\n /** Top-level CLI noun (command group) that hosts this service's verbs (`<category>-<provider>`). */\n cli_noun: string;\n /** Verb names exposed under `cli_noun`. */\n verbs: string[];\n /** One-line description per verb, keyed by verb name. */\n verb_descriptions: Record<string, string>;\n /** Ordered call sequence; `[cancel]` is optional. */\n workflow: string[];\n /** ISO date the capability became available. */\n since: string;\n discovery: ServiceDiscovery;\n}\n\n/** Static registry. This iteration ships a single `ride-elife` capability. */\nexport const SERVICE_REGISTRY: ServiceCapability[] = [\n {\n service_id: 'ride-elife',\n name: 'Ride hailing (eLife)',\n description: 'On-demand ride ordering: quote a fare, book it, poll status, and cancel.',\n category: 'ride',\n version: '1.0.0',\n provider: 'elife',\n cli_noun: 'ride-elife',\n verbs: ['quote', 'book', 'get', 'cancel', 'list-orders'],\n verb_descriptions: {\n quote: 'Request fare quotes for a ride between two points.',\n book: 'Book a ride using a quote_id returned by quote.',\n get: 'Retrieve a ride order by id (poll for status changes with --watch).',\n cancel: 'Cancel a ride order by id (may incur a fee).',\n 'list-orders': 'List previously placed ride orders.',\n },\n workflow: ['quote', 'book', 'get (poll for status)', 'cancel (optional)'],\n since: '2026-06-01',\n discovery: { help_command: 'agenzo-merchant-cli ride-elife --help' },\n },\n];\n\n/** Look up a capability by its service_id. Returns undefined when not found. */\nexport function findService(serviceId: string): ServiceCapability | undefined {\n return SERVICE_REGISTRY.find((s) => s.service_id === serviceId);\n}\n","import { Command } from 'commander';\nimport { ConfigManager, Formatter, resolveFormat, renderWithContext } from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport { SERVICE_REGISTRY, type ServiceCapability } from './registry.js';\n\n/**\n * Summary view of a registry entry for `services list` (§4.4.1.1): the\n * discovery-relevant subset — service_id/name/category/provider/cli_noun/\n * version/verbs/since/discovery — without the heavier verb_descriptions /\n * workflow detail (those are returned in full by `services get`).\n */\ninterface ServiceListItem {\n service_id: string;\n name: string;\n category: string;\n provider: string;\n cli_noun: string;\n version: string;\n verbs: string[];\n since: string;\n discovery: ServiceCapability['discovery'];\n}\n\nfunction toListItem(s: ServiceCapability): ServiceListItem {\n return {\n service_id: s.service_id,\n name: s.name,\n category: s.category,\n provider: s.provider,\n cli_noun: s.cli_noun,\n version: s.version,\n verbs: s.verbs,\n since: s.since,\n discovery: s.discovery,\n };\n}\n\n/**\n * `services list` — list available merchant capabilities (§4.4.1.1).\n *\n * Read-only, no `--idempotency-key`. Data source is the CLI-bundled registry\n * (D4), not a live backend feed. Output is wrapped by `renderWithContext` so\n * json carries the profile/endpoint envelope; the table form renders a\n * one-line-per-service summary on stdout.\n */\nexport function registerServicesListCommand(parent: Command): void {\n const cmd = parent\n .command('list')\n .description('List available merchant services from the registry');\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const services = SERVICE_REGISTRY.map(toListItem);\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<{ services: ServiceListItem[] }> = {\n data: { services },\n text: () => {\n if (services.length === 0) {\n return Formatter.status('info', 'No services found');\n }\n const headers = ['Service ID', 'Name', 'Category', 'Provider', 'Version', 'Verbs'];\n const rows = services.map((s) => [\n s.service_id,\n s.name,\n s.category,\n s.provider,\n s.version,\n s.verbs.join(', '),\n ]);\n return Formatter.table(headers, rows);\n },\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport {\n ConfigManager,\n Formatter,\n CliError,\n resolveFormat,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport { findService, type ServiceCapability } from './registry.js';\n\n/**\n * Render the full capability as a key/value block for table output.\n */\nfunction formatServiceGet(s: ServiceCapability): string {\n const lines: [string, string][] = [\n ['Service ID', s.service_id],\n ['Name', s.name],\n ['Description', s.description],\n ['Category', s.category],\n ['Version', s.version],\n ['Provider', s.provider],\n ['CLI Noun', s.cli_noun],\n ['Verbs', s.verbs.join(', ')],\n ['Workflow', s.workflow.join(' → ')],\n ['Since', s.since],\n ['Help', s.discovery.help_command],\n ];\n const verbDetail = s.verbs\n .map((v) => ` ${v}: ${s.verb_descriptions[v] ?? ''}`)\n .join('\\n');\n return `${Formatter.keyValue(lines)}\\nVerb descriptions:\\n${verbDetail}`;\n}\n\n/**\n * `services get <service-id>` — return a single capability's full metadata\n * (§4.4.1.2), including verb_descriptions / workflow / discovery.\n *\n * Read-only, reads the CLI-bundled registry (D4). A hit is rendered via\n * `renderWithContext` (json carries the profile/endpoint envelope); a miss\n * throws cli-core's `CliError` with code `SERVICE_NOT_FOUND` (exit 1).\n */\nexport function registerServiceGetCommand(parent: Command): void {\n const cmd = parent\n .command('get <service-id>')\n .description('Retrieve a single merchant service by id');\n\n cmd.action(async (serviceId: string) => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const service = findService(serviceId);\n if (!service) {\n throw new CliError(\n 'SERVICE_NOT_FOUND',\n `Service '${serviceId}' was not found in the registry. Run \"services list\" to see available services.`,\n );\n }\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<ServiceCapability> = {\n data: service,\n text: () => formatServiceGet(service),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n"],"mappings":"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","names":["readFile","writeFile","mkdir","chmod","join","homedir","join","homedir","mkdir","chmod","readFile","writeFile","need","num","need","confirm","need","confirm"]}
|
|
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/ride-elife/watch.ts","../src/verb-schema.ts","../src/ride-elife/quote.ts","../src/ride-elife/book.ts","../src/idempotency.ts","../src/ride-elife/get.ts","../src/ride-elife/cancel.ts","../src/ride-elife/list-orders.ts","../src/services/registry.ts","../src/services/list.ts","../src/services/get.ts"],"sourcesContent":["import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n Formatter,\n CliError,\n UserCancelError,\n toErrorEnvelope,\n resolveFormat,\n type OutputFormat,\n exitCodeFor,\n getCurrentVersion,\n} from '@agenzo/cli-core';\n\n// ride-elife commands (injection-style register, D6)\nimport { registerQuoteCommand } from './ride-elife/quote.js';\nimport { registerBookCommand } from './ride-elife/book.js';\nimport { registerRideGetCommand } from './ride-elife/get.js';\nimport { registerCancelCommand } from './ride-elife/cancel.js';\nimport { registerListOrdersCommand } from './ride-elife/list-orders.js';\n\n// services commands (CLI-bundled registry, D4)\nimport { registerServicesListCommand } from './services/list.js';\nimport { registerServiceGetCommand } from './services/get.js';\n\n// Holds the parsed program so the top-level error handler can read the\n// resolved `--format` global flag. Assigned inside `main()` once the program\n// is constructed; may be undefined if an error is thrown before then.\nlet programRef: Command | undefined;\n\nasync function main() {\n // Instantiate shared infrastructure. merchant-cli authenticates per-command\n // via `--api-key` (X-Api-Key); there is no Bearer session / AuthService /\n // keystore. The no-arg ConfigManager reuses cli-core's default config (the\n // environment admin-cli governs) purely to supply the ApiClient baseUrl and\n // the json envelope's profile/endpoint — merchant-cli exposes no host\n // commands of its own.\n const configManager = new ConfigManager(undefined, '/api/merchant/v1');\n await configManager.ensureDirectories();\n\n const apiBaseUrl = await configManager.getApiBaseUrl();\n const apiClient = new ApiClient({ baseUrl: apiBaseUrl });\n\n // Shared deps object for networked commands — API Key is supplied per-command\n // (or interactively), so commands only need the HTTP client.\n const deps = { apiClient };\n\n // Create program\n const program = new Command();\n programRef = program;\n program\n .name('agenzo-merchant-cli')\n .version(getCurrentVersion())\n .description(\n 'Agenzo merchant fulfillment plane: service discovery (services) and ride ordering (ride-elife)',\n )\n .option('--verbose', 'Show verbose logs')\n .option('--yes', 'Skip confirmation prompts (for automation/AI Agents)')\n // merchant-cli is an agent-first entrypoint, so it defaults to json (D2),\n // unlike the cli-core default (table). resolveFormat only acts as a\n // fallback when the flag is absent.\n .option(\n '--format <format>',\n 'Output format: json | table (default: json; or set AGENZO_FORMAT)',\n 'json',\n )\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)');\n\n // Mirror the resolved global --format into AGENZO_FORMAT before any action\n // runs, so code paths without direct format access can resolve the active\n // format and stay silent in json mode.\n program.hook('preAction', (thisCommand) => {\n const flag = thisCommand.opts().format as string | undefined;\n process.env.AGENZO_FORMAT = resolveFormat(flag);\n });\n\n // ride-elife command group (eLife ride ordering)\n const rideCmd = program.command('ride-elife').description('Ride ordering (eLife)');\n registerQuoteCommand(rideCmd, deps);\n registerBookCommand(rideCmd, deps);\n registerRideGetCommand(rideCmd, deps);\n registerCancelCommand(rideCmd, deps);\n registerListOrdersCommand(rideCmd, deps);\n\n // services command group (CLI-bundled capability discovery)\n const servicesCmd = program.command('services').description('Merchant service discovery');\n registerServicesListCommand(servicesCmd);\n registerServiceGetCommand(servicesCmd);\n\n // Parse and execute\n await program.parseAsync(process.argv);\n}\n\n/**\n * Resolve the active output format for error reporting. Prefers the parsed\n * global `--format` flag (available on `programRef` once the program is\n * constructed; defaults to `json` for merchant-cli); if an error was thrown\n * before parsing, falls back to `resolveFormat(undefined)` (which consults\n * `AGENZO_FORMAT`, else `table`).\n */\nfunction resolveActiveFormat(): OutputFormat {\n const flag = programRef?.opts().format as string | undefined;\n return resolveFormat(flag);\n}\n\n/**\n * Top-level failure path. Writes the error envelope to stderr in the resolved\n * format and exits with the mapped code (1–5). stdout is left untouched so a\n * partial machine payload is never emitted on failure.\n *\n * - `json`: a single `{ error: { code, code_num, message, request_id? } }` envelope (§8.2).\n * - `table`: `✗ [<code_num>] <message>`.\n */\nfunction reportError(error: unknown): never {\n const envelope = toErrorEnvelope(error);\n const format = resolveActiveFormat();\n\n if (format === 'json') {\n console.error(JSON.stringify(envelope));\n } else {\n console.error(\n Formatter.status('error', `[${envelope.error.code_num}] ${envelope.error.message}`),\n );\n // Unknown (non-CliError) failures keep the --verbose raw-dump affordance.\n if (!(error instanceof CliError) && process.argv.includes('--verbose')) {\n console.error(error);\n }\n }\n\n // exitCodeFor owns the error-class → exit-code matrix, including\n // UpgradeRequiredError → 2 and UserCancelError → 5.\n process.exit(exitCodeFor(error));\n}\n\n// Ctrl+C / SIGINT maps to a user-cancel (exit 5) via the same envelope path.\nprocess.on('SIGINT', () => {\n reportError(new UserCancelError());\n});\n\n// Global error handler. Normal completion exits 0 naturally (the mapper is\n// never consulted on success).\nmain().catch(reportError);\n","/**\n * CLI 对外统一错误码目录(cli-design §8 单一事实源)。\n *\n * 每个对外码同时有字符串码(首选路由键)和数字码(紧凑、便于日志聚合)。\n * 二者一一对应,由 {@link CODE_NUM} 绑定。字符串码按域前缀分组,数字码按\n * 同样的域分段(§8.3)。\n *\n * 注:`UPGRADE_REQUIRED`(版本过低)与 `CLIENT_ABORTED`(用户主动取消)是\n * CLI 本地检测的非业务码,不在 §8.4 业务字典内,分配在 CLIENT 号段尾部。\n */\nexport type ErrorCode =\n // AUTH_* (1000-1099)\n | 'AUTH_SESSION_EXPIRED'\n | 'AUTH_MAGIC_LINK_EXPIRED'\n | 'AUTH_INVITE_CODE_REQUIRED'\n | 'AUTH_INVITE_CODE_INVALID'\n // KEY_* (1100-1199)\n | 'KEY_INVALID'\n | 'KEY_SCOPE_DENIED'\n // RESOURCE_* (2000-2099)\n | 'RESOURCE_NOT_FOUND'\n | 'RESOURCE_CONFLICT'\n | 'RESOURCE_STATE_INVALID'\n // PARAM_* (2100-2199)\n | 'PARAM_INVALID'\n | 'PARAM_IDEMPOTENCY_KEY_REQUIRED'\n | 'PARAM_IDEMPOTENCY_KEY_CONFLICT'\n // BILLING_* (3000-3099)\n | 'BILLING_MODE_MISMATCH'\n // ACCOUNT_* (3100-3199)\n | 'ACCOUNT_NOT_FOUND'\n | 'ACCOUNT_SUSPENDED'\n | 'ACCOUNT_INSUFFICIENT_BALANCE'\n // PAYMENT_ORDER_* (3200-3299)\n | 'PAYMENT_ORDER_NOT_FOUND'\n | 'PAYMENT_ORDER_NOT_PAID'\n | 'PAYMENT_ORDER_MISMATCH'\n | 'PAYMENT_ORDER_ALREADY_CONSUMED'\n // TOKEN_* (4000-4099)\n | 'TOKEN_FEATURE_DISABLED'\n // SERVICE_* (4100-4199)\n | 'SERVICE_NOT_FOUND'\n // ride 业务码 (4200-4299)\n | 'VEHICLE_UNAVAILABLE'\n | 'QUOTE_EXPIRED'\n | 'BOOKING_FAILED'\n | 'CANCELLATION_NOT_ALLOWED'\n // RATE_* (5000-5099)\n | 'RATE_LIMITED'\n // UPSTREAM_* (5100-5199)\n | 'UPSTREAM_ERROR'\n // INTERNAL_* (5200-5299)\n | 'INTERNAL_ERROR'\n // NOT_IMPLEMENTED (5300)\n | 'NOT_IMPLEMENTED'\n // CLIENT_* (9000-9099) — CLI 本地产生\n | 'CLIENT_NOT_SIGNED_IN'\n | 'CLIENT_LOGIN_TIMEOUT'\n | 'CLIENT_ORG_NOT_LOCAL'\n | 'CLIENT_ORG_WRONG_ENV'\n | 'CLIENT_NO_PAYMENT_METHOD'\n | 'CLIENT_CARD_NOT_MATCHED'\n | 'CLIENT_ABORTED'\n // 非业务码(CLI 本地检测)\n | 'UPGRADE_REQUIRED';\n\n/**\n * 字符串码 → 数字码(§8.4)。每个对外码的数字码由本表唯一绑定,发布后只增不改。\n */\nexport const CODE_NUM: Record<ErrorCode, number> = {\n AUTH_SESSION_EXPIRED: 1001,\n AUTH_MAGIC_LINK_EXPIRED: 1002,\n AUTH_INVITE_CODE_REQUIRED: 1003,\n AUTH_INVITE_CODE_INVALID: 1004,\n KEY_INVALID: 1101,\n KEY_SCOPE_DENIED: 1102,\n RESOURCE_NOT_FOUND: 2001,\n RESOURCE_CONFLICT: 2002,\n RESOURCE_STATE_INVALID: 2003,\n PARAM_INVALID: 2101,\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 2102,\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 2103,\n BILLING_MODE_MISMATCH: 3001,\n ACCOUNT_NOT_FOUND: 3101,\n ACCOUNT_SUSPENDED: 3102,\n ACCOUNT_INSUFFICIENT_BALANCE: 3103,\n PAYMENT_ORDER_NOT_FOUND: 3201,\n PAYMENT_ORDER_NOT_PAID: 3202,\n PAYMENT_ORDER_MISMATCH: 3203,\n PAYMENT_ORDER_ALREADY_CONSUMED: 3204,\n TOKEN_FEATURE_DISABLED: 4001,\n SERVICE_NOT_FOUND: 4101,\n VEHICLE_UNAVAILABLE: 4201,\n QUOTE_EXPIRED: 4202,\n BOOKING_FAILED: 4203,\n CANCELLATION_NOT_ALLOWED: 4204,\n RATE_LIMITED: 5001,\n UPSTREAM_ERROR: 5101,\n INTERNAL_ERROR: 5201,\n NOT_IMPLEMENTED: 5300,\n CLIENT_NOT_SIGNED_IN: 9001,\n CLIENT_LOGIN_TIMEOUT: 9002,\n CLIENT_ORG_NOT_LOCAL: 9003,\n CLIENT_ORG_WRONG_ENV: 9004,\n CLIENT_NO_PAYMENT_METHOD: 9005,\n CLIENT_CARD_NOT_MATCHED: 9006,\n CLIENT_ABORTED: 9007,\n UPGRADE_REQUIRED: 9008,\n};\n\n/** Look up the numeric code for a string error code. */\nexport function codeNum(code: ErrorCode): number {\n return CODE_NUM[code];\n}\n","import { type ErrorCode, CODE_NUM, codeNum } from './error-catalog.js';\nimport type { ApiError, UpstreamError } from '../api-client/client.js';\n\n/** Base class for all CLI errors. Carries the CLI-facing error code (§8.4). */\nexport class CliError extends Error {\n constructor(\n public readonly code: ErrorCode,\n message: string,\n public readonly statusCode?: number,\n public readonly requestId?: string,\n public readonly upstream?: UpstreamError,\n ) {\n super(message);\n this.name = 'CliError';\n }\n\n /**\n * Map a backend ApiError to a CLI-facing code (§8.5 transitional mapping).\n * Backend numeric codes / HTTP status are translated to §8.4 string codes;\n * the raw backend message is NOT passed through (§8.1 principle 4) — a\n * stable, fixed message per code is used instead.\n *\n * The optional `opts.auth` selects the auth semantics for the 401 mapping:\n * - `'bearer'` (default, admin-cli Bearer Token): 401 → `AUTH_SESSION_EXPIRED`.\n * - `'api-key'` (token-cli `X-Api-Key`): 401 → `KEY_INVALID`.\n * 403 maps to `KEY_SCOPE_DENIED` under both auth modes. Omitting `opts`\n * preserves the original Bearer behavior exactly (§8.5 / requirement 6.4).\n *\n * Domain string-code routing (D3 / requirement 5.4): when the backend\n * supplies a string `error.code` in the v3 envelope that is a known §8 code\n * (present in {@link CODE_NUM}), it is used verbatim as the CLI-facing code\n * so ride/merchant-specific codes (`QUOTE_EXPIRED`, `VEHICLE_UNAVAILABLE`,\n * `BILLING_MODE_MISMATCH`, `PAYMENT_ORDER_*`, …) survive intact. Otherwise —\n * including when no string code is provided, as is the case for admin/token\n * today — mapping falls back to the HTTP-status table below, leaving the\n * existing Bearer/api-key behavior unchanged.\n */\n static fromApi(error: ApiError, opts?: { auth?: 'bearer' | 'api-key' }): CliError {\n // D3: prefer the backend's string code when it is a known §8 catalog code.\n if (error.code && isKnownErrorCode(error.code)) {\n return new CliError(\n error.code,\n STABLE_MESSAGE[error.code] ?? 'Request failed. Please check your input and retry.',\n error.statusCode,\n error.requestId,\n error.upstream,\n );\n }\n\n const status = error.statusCode;\n let code: ErrorCode;\n\n if (status === 401) code = opts?.auth === 'api-key' ? 'KEY_INVALID' : 'AUTH_SESSION_EXPIRED';\n else if (status === 403) code = 'KEY_SCOPE_DENIED';\n else if (status === 404) code = 'RESOURCE_NOT_FOUND';\n else if (status === 409) code = 'RESOURCE_CONFLICT';\n else if (status === 429) code = 'RATE_LIMITED';\n else if (status >= 500) code = 'INTERNAL_ERROR';\n else code = 'PARAM_INVALID'; // other 4xx (incl. 400/422)\n\n return new CliError(\n code,\n STABLE_MESSAGE[code] ?? 'Request failed. Please check your input and retry.',\n status,\n error.requestId,\n error.upstream,\n );\n }\n}\n\n/** Network / connectivity failure → UPSTREAM_ERROR. Never leak the internal URL/path. */\nexport class NetworkError extends CliError {\n constructor(_url: string, timeout?: number, _cause?: Error) {\n super(\n 'UPSTREAM_ERROR',\n timeout\n ? 'The request timed out. The service may be temporarily unavailable — please retry.'\n : 'Connection failed. The service may be temporarily unavailable — please retry.',\n );\n }\n}\n\n/** Auth / session failures. Code chosen by message intent (§8.4 AUTH_* / CLIENT_*). */\nexport class AuthError extends CliError {\n constructor(message: string, public readonly suggestion: string) {\n const m = message.toLowerCase();\n const code: ErrorCode = m.includes('not signed in')\n ? 'CLIENT_NOT_SIGNED_IN'\n : m.includes('time')\n ? 'CLIENT_LOGIN_TIMEOUT'\n : m.includes('magic link')\n ? 'AUTH_MAGIC_LINK_EXPIRED'\n : 'AUTH_SESSION_EXPIRED';\n super(code, message || 'Unknown error');\n }\n}\n\nexport class ConfigError extends CliError {\n constructor(message: string, public readonly filePath: string) {\n super('INTERNAL_ERROR', message || 'Unknown error');\n }\n}\n\nexport class ValidationError extends CliError {\n constructor(message: string) {\n super('PARAM_INVALID', message || 'Unknown error');\n }\n}\n\nexport class IdempotencyKeyRequiredError extends CliError {\n constructor(commandPath: string) {\n super(\n 'PARAM_IDEMPOTENCY_KEY_REQUIRED',\n `\\`${commandPath}\\` requires --idempotency-key <key>. Supply a unique key so the write can be safely retried.`,\n );\n }\n}\n\nexport class UpgradeRequiredError extends CliError {\n constructor(currentVersion: string, minVersion: string, upgradeCommand: string) {\n super(\n 'UPGRADE_REQUIRED',\n `agenzo-admin-cli ${currentVersion} is out of date — the server requires ${minVersion} or newer. To upgrade, run: ${upgradeCommand}`,\n );\n }\n}\n\nexport class UserCancelError extends CliError {\n constructor(message = 'Operation cancelled by user') {\n super('CLIENT_ABORTED', message || 'Unknown error');\n }\n}\n\n/** Type guard: is `value` a known §8 string error code (present in CODE_NUM)? */\nfunction isKnownErrorCode(value: string): value is ErrorCode {\n return Object.prototype.hasOwnProperty.call(CODE_NUM, value);\n}\n\n/**\n * Stable, CLI-owned message per code used when mapping opaque backend errors\n * (§8.1 principle 4: never surface raw backend detail).\n */\nconst STABLE_MESSAGE: Partial<Record<ErrorCode, string>> = {\n AUTH_SESSION_EXPIRED: 'Your session has expired. Please run `agenzo-admin-cli auth login` again.',\n AUTH_MAGIC_LINK_EXPIRED: 'Verification link is invalid or has expired. Please request a new one.',\n AUTH_INVITE_CODE_REQUIRED: 'An invitation code is required to register.',\n AUTH_INVITE_CODE_INVALID: 'The invitation code is invalid.',\n KEY_INVALID: 'The API key is invalid or has been revoked. Please check your --api-key and retry.',\n KEY_SCOPE_DENIED: 'This API key does not have the required scope for this command.',\n RESOURCE_NOT_FOUND: 'The resource was not found or does not belong to the current organization.',\n RESOURCE_CONFLICT: 'A resource with the same unique value already exists.',\n RESOURCE_STATE_INVALID: 'The resource is in a state that does not permit this operation.',\n RATE_LIMITED: 'Too many requests. Please back off and retry.',\n UPSTREAM_ERROR: 'A third-party service is temporarily unavailable. Please try again later.',\n INTERNAL_ERROR: 'Something went wrong on the server. Please retry and note the request_id.',\n PARAM_INVALID: 'One or more parameters are invalid. Please check your input and retry.',\n PARAM_IDEMPOTENCY_KEY_CONFLICT: 'A request with this idempotency key was already processed with different parameters.',\n TOKEN_FEATURE_DISABLED: 'This token feature is currently unavailable.',\n BILLING_MODE_MISMATCH: 'The billing mode does not match this operation. Please verify your account billing configuration.',\n ACCOUNT_NOT_FOUND: 'The settlement account was not found.',\n ACCOUNT_SUSPENDED: 'The settlement account is suspended. Please contact support.',\n ACCOUNT_INSUFFICIENT_BALANCE: 'The settlement account has insufficient balance for this operation.',\n PAYMENT_ORDER_NOT_FOUND: 'The payment order was not found.',\n PAYMENT_ORDER_NOT_PAID: 'The payment order has not been paid. Please complete payment and retry.',\n PAYMENT_ORDER_MISMATCH: 'The payment order does not match this order. Please check the --payment-order-id.',\n PAYMENT_ORDER_ALREADY_CONSUMED: 'The payment order has already been consumed by another booking.',\n SERVICE_NOT_FOUND: 'The requested service was not found.',\n VEHICLE_UNAVAILABLE: 'No vehicle is available for the requested trip. Please try a different time or class.',\n QUOTE_EXPIRED: 'The quote has expired. Please request a new quote and retry.',\n BOOKING_FAILED: 'The booking could not be completed. Please retry.',\n CANCELLATION_NOT_ALLOWED: 'This order cannot be cancelled in its current state.',\n NOT_IMPLEMENTED: 'This operation is not implemented yet.',\n};\n\n/** §8.2 error envelope: `{ error: { code, code_num, message, request_id?, upstream? } }`. */\nexport interface ErrorEnvelope {\n error: {\n code: ErrorCode;\n code_num: number;\n message: string;\n request_id?: string;\n upstream?: UpstreamError;\n };\n}\n\nexport function toErrorEnvelope(error: unknown): ErrorEnvelope {\n if (error instanceof CliError) {\n return {\n error: {\n code: error.code,\n code_num: codeNum(error.code),\n message: error.message || 'Unknown error',\n ...(error.requestId ? { request_id: error.requestId } : {}),\n ...(error.upstream ? { upstream: error.upstream } : {}),\n },\n };\n }\n\n const message =\n error instanceof Error\n ? error.message\n : typeof error === 'string'\n ? error\n : 'Unexpected error';\n return {\n error: {\n code: 'INTERNAL_ERROR',\n code_num: codeNum('INTERNAL_ERROR'),\n message: message || 'Unknown error',\n },\n };\n}\n","/**\n * CLI version + min-version comparator.\n *\n * The CLI's current version is read from `package.json` at runtime. This is\n * the single source of truth — bumping `package.json` automatically updates\n * what the CLI reports and what it compares against the server-advertised\n * minimum (`X-CLI-Min-Version` response header, driven by\n * `AGENT_PAY_CLI_MIN_VERSION` on the server).\n *\n * Only numeric major.minor.patch segments are compared; pre-release and build\n * metadata suffixes are stripped. This matches our versioning scheme and\n * avoids pulling in `semver` for a single `<` check.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/** Command the user should run to pick up the latest CLI. */\nexport const UPGRADE_COMMAND = 'npm install -g agenzo-admin-cli@latest';\n\n/**\n * Hard-coded fallback used only when `package.json` cannot be read at runtime\n * (unusual packaging/bundling edge cases). Keep this in sync with\n * `package.json`'s `version` on every release so the reported version and\n * the User-Agent stay accurate even in the degraded path.\n */\nexport const FALLBACK_VERSION = '0.1.1';\n\nlet cachedVersion: string | null = null;\n\nexport function getCurrentVersion(): string {\n if (cachedVersion !== null) return cachedVersion;\n // Walk up from the compiled file (dist/index.js) or source layout to find\n // package.json. Both `dist/..` and `src/utils/../..` resolve to the project\n // root, which is where package.json lives in a published npm install.\n const here = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n join(here, '..', 'package.json'), // dist/ → project root\n join(here, '..', '..', 'package.json'), // src/utils/ → project root\n ];\n for (const p of candidates) {\n try {\n const pkg = JSON.parse(readFileSync(p, 'utf-8')) as { version?: string };\n if (typeof pkg.version === 'string') {\n cachedVersion = pkg.version;\n return cachedVersion;\n }\n } catch {\n // try next candidate\n }\n }\n // Degrade gracefully instead of crashing the CLI: if we can't locate\n // package.json at runtime, report the hard-coded fallback. The User-Agent\n // and any min-version comparison will still behave sensibly. We write a\n // one-line warning to stderr so packaging regressions remain visible.\n cachedVersion = FALLBACK_VERSION;\n // eslint-disable-next-line no-console\n console.warn(\n `[agenzo-admin-cli] package.json not found; using fallback version ${FALLBACK_VERSION}`,\n );\n return cachedVersion;\n}\n\n/**\n * Returns negative / zero / positive like `Array.sort`, comparing `a` against `b`.\n * Non-numeric segments and suffixes are treated as zero.\n */\nexport function compareVersions(a: string, b: string): number {\n const parse = (v: string): [number, number, number] => {\n const clean = v.trim().replace(/^v/, '').split(/[-+]/)[0];\n const parts = clean.split('.');\n return [\n parseInt(parts[0] ?? '0', 10) || 0,\n parseInt(parts[1] ?? '0', 10) || 0,\n parseInt(parts[2] ?? '0', 10) || 0,\n ];\n };\n const [a1, a2, a3] = parse(a);\n const [b1, b2, b3] = parse(b);\n if (a1 !== b1) return a1 - b1;\n if (a2 !== b2) return a2 - b2;\n return a3 - b3;\n}\n\nexport function isBelow(current: string, minimum: string): boolean {\n return compareVersions(current, minimum) < 0;\n}\n","import { NetworkError, UpgradeRequiredError } from '../errors/errors.js';\nimport { getCurrentVersion, isBelow, UPGRADE_COMMAND } from '../version/version.js';\n\nexport interface ApiClientConfig {\n baseUrl: string;\n timeout?: number; // Default 30000ms\n}\n\nexport interface ApiResponse<T> {\n success: true;\n data: T;\n /** Server-provided message from the unified response envelope. */\n message?: string;\n}\n\n/** Upstream error details (diagnostic only, not stable). */\nexport interface UpstreamError {\n /** Upstream-specific error code (stringified). */\n code: string;\n /** Upstream-specific error message. */\n message: string;\n}\n\nexport interface ApiError {\n success: false;\n errorCode: number;\n errorMessage: string;\n statusCode: number;\n /**\n * Raw string code from the v3 response envelope (`{ code, message, data }`),\n * surfaced verbatim so {@link CliError.fromApi} can route domain-specific\n * §8 codes (e.g. `QUOTE_EXPIRED`, `VEHICLE_UNAVAILABLE`) by string code\n * before falling back to HTTP-status mapping. Absent when the backend does\n * not provide a string code (e.g. non-JSON error responses).\n */\n code?: string;\n /** Server-provided request correlation id, surfaced in the error envelope. */\n requestId?: string;\n /** Upstream error details for diagnostic transparency. */\n upstream?: UpstreamError;\n}\n\nexport type ApiResult<T> = ApiResponse<T> | ApiError;\n\nexport type AuthMode =\n | { type: 'bearer'; token: string }\n | { type: 'api-key'; key: string }\n | { type: 'none' };\n\nexport class ApiClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: ApiClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.timeout = config.timeout ?? 60000;\n }\n\n private buildHeaders(auth: AuthMode): Record<string, string> {\n const headers: Record<string, string> = {\n 'User-Agent': `agenzo-admin-cli/${getCurrentVersion()}`,\n };\n if (auth.type === 'bearer') {\n headers['Authorization'] = `Bearer ${auth.token}`;\n } else if (auth.type === 'api-key') {\n headers['X-Api-Key'] = auth.key;\n }\n return headers;\n }\n\n async get<T>(\n path: string,\n auth: AuthMode,\n params?: Record<string, string>,\n ): Promise<ApiResult<T>> {\n let url = `${this.baseUrl}${path}`;\n if (params && Object.keys(params).length > 0) {\n const searchParams = new URLSearchParams(params);\n url += `?${searchParams.toString()}`;\n }\n return this.request<T>(url, {\n method: 'GET',\n headers: this.buildHeaders(auth),\n });\n }\n\n async post<T>(\n path: string,\n auth: AuthMode,\n body?: Record<string, unknown>,\n extraHeaders?: Record<string, string>,\n ): Promise<ApiResult<T>> {\n const url = `${this.baseUrl}${path}`;\n const headers = this.buildHeaders(auth);\n headers['Content-Type'] = 'application/json';\n if (extraHeaders) {\n Object.assign(headers, extraHeaders);\n }\n return this.request<T>(url, {\n method: 'POST',\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n private async request<T>(url: string, init: RequestInit): Promise<ApiResult<T>> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n // Enforce server-advertised CLI version floor before doing any work\n // on the response. Throws UpgradeRequiredError which is rendered and\n // exits at the top level (src/index.ts).\n this.enforceMinVersion(response.headers.get('x-cli-min-version'));\n\n // Handle non-JSON responses (e.g. 500 Internal Server Error returns plain text)\n const contentType = response.headers.get('content-type') ?? '';\n let responseBody: Record<string, unknown>;\n if (contentType.includes('application/json')) {\n responseBody = await response.json() as Record<string, unknown>;\n } else {\n const text = await response.text();\n if (!response.ok) {\n const statusMsg = this.friendlyStatusMessage(response.status);\n return {\n success: false,\n errorCode: 0,\n errorMessage: statusMsg,\n statusCode: response.status,\n };\n }\n // Try parsing as JSON anyway (some servers don't set content-type)\n try {\n responseBody = JSON.parse(text) as Record<string, unknown>;\n } catch {\n return {\n success: false,\n errorCode: 0,\n errorMessage: `Unexpected response from server (${response.status})`,\n statusCode: response.status,\n };\n }\n }\n\n // Server uses unified format: { code: \"0000\", message: \"...\", data: {...} }\n const code = responseBody.code as string | undefined;\n const message = responseBody.message as string | undefined;\n\n // Success: HTTP 2xx AND code is \"0000\" (or no code field for raw responses)\n if (response.ok && (!code || code === '0000')) {\n // If the server wraps the payload in a \"data\" field, unwrap it —\n // including when `data` is explicitly null (a valid empty payload,\n // e.g. GET /accounts for a developer without a settlement account).\n // We must distinguish \"no data field\" (raw response → use the whole\n // body) from \"data field present but null\" (→ return null), since\n // `data ?? responseBody` would wrongly fall back to the envelope and\n // surface { code, message, data: null } as the payload.\n const hasDataField = Object.prototype.hasOwnProperty.call(responseBody, 'data');\n const payload = hasDataField ? responseBody.data : responseBody;\n return { success: true, data: payload as T, message };\n }\n\n // Error: either HTTP non-2xx or code !== \"0000\"\n const errorCode = code ? parseInt(code, 10) : 0;\n // Handle FastAPI 422 validation errors where detail is an array\n let errorMsg = message ?? response.statusText;\n if (!errorMsg || errorMsg === response.statusText) {\n const detail = responseBody.detail;\n if (Array.isArray(detail)) {\n errorMsg = detail.map((d: Record<string, unknown>) => {\n const loc = (d.loc as string[])?.slice(1).join('.') ?? '';\n return loc ? `${loc}: ${d.msg}` : String(d.msg);\n }).join('; ');\n } else if (typeof detail === 'string') {\n errorMsg = detail;\n }\n }\n\n // Prefer string error_code (CLI D3 routing) over numeric code string\n const errorCodeStr = responseBody.error_code as string | undefined;\n\n // Extract upstream error details from data.upstream\n const rawData = responseBody.data as Record<string, unknown> | undefined;\n const upstream = (rawData?.upstream && typeof rawData.upstream === 'object')\n ? rawData.upstream as UpstreamError\n : undefined;\n\n return {\n success: false,\n errorCode: isNaN(errorCode) ? 0 : errorCode,\n errorMessage: errorMsg,\n statusCode: response.status,\n ...(errorCodeStr ? { code: errorCodeStr } : (typeof code === 'string' && code ? { code } : {})),\n requestId: (responseBody.request_id ?? responseBody.requestId) as string | undefined,\n ...(upstream ? { upstream } : {}),\n };\n } catch (error) {\n // UpgradeRequiredError is a CliError and must propagate untouched to the\n // top-level handler; don't rewrap it as a NetworkError.\n if (error instanceof UpgradeRequiredError) {\n throw error;\n }\n if (error instanceof DOMException && error.name === 'AbortError') {\n throw new NetworkError(url, this.timeout);\n }\n throw new NetworkError(url, undefined, error instanceof Error ? error : undefined);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Validate that the running CLI meets the server-advertised minimum.\n * Missing or empty header → skip (backward compat with servers that don't\n * advertise yet, and clients hitting legacy proxies).\n */\n private enforceMinVersion(headerValue: string | null): void {\n const minVersion = headerValue?.trim();\n if (!minVersion) return;\n const current = getCurrentVersion();\n if (isBelow(current, minVersion)) {\n throw new UpgradeRequiredError(current, minVersion, UPGRADE_COMMAND);\n }\n }\n\n private friendlyStatusMessage(status: number): string {\n const messages: Record<number, string> = {\n 400: 'Invalid request. Please check your input.',\n 401: 'Authentication failed. Please check your API key or login again.',\n 403: 'Access denied. You do not have permission for this operation.',\n 404: 'Resource not found. Please check the ID.',\n 409: 'Conflict. This resource may already exist.',\n 422: 'Invalid input. Please check the request parameters.',\n 429: 'Too many requests. Please wait and try again.',\n 500: 'Something went wrong on the server. Please try again later.',\n 502: 'Service is temporarily unavailable. Please try again in a moment.',\n 503: 'Service is temporarily unavailable. Please try again in a moment.',\n 504: 'The request took too long. Please try again.',\n };\n return messages[status] ?? `Something went wrong (${status}). Please try again later.`;\n }\n}\n","import { readFile, writeFile, readdir, unlink, access, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { OrgCredential } from '../types/config.js';\n\nexport class CredentialStore {\n private readonly basePath: string;\n\n constructor(basePath?: string) {\n this.basePath = basePath ?? join(homedir(), '.agenzo-admin-cli', 'credentials');\n }\n\n private filePath(orgId: string): string {\n return join(this.basePath, `${orgId}.json`);\n }\n\n private async ensureDir(): Promise<void> {\n // Credentials hold long-lived Bearer tokens — dir must be owner-only (0700).\n // mkdir mode is subject to umask, so chmod afterwards to enforce it on\n // both freshly created and pre-existing directories.\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\n await chmod(this.basePath, 0o700);\n }\n\n async get(orgId: string): Promise<OrgCredential | null> {\n try {\n const content = await readFile(this.filePath(orgId), 'utf-8');\n return JSON.parse(content) as OrgCredential;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n }\n\n async save(credential: OrgCredential): Promise<void> {\n await this.ensureDir();\n const path = this.filePath(credential.org_id);\n // Owner read/write only (0600); chmod after write so pre-existing files\n // created before this safeguard also get tightened.\n await writeFile(path, JSON.stringify(credential, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n await chmod(path, 0o600);\n }\n\n async delete(orgId: string): Promise<void> {\n try {\n await unlink(this.filePath(orgId));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return;\n }\n throw error;\n }\n }\n\n async listAll(): Promise<OrgCredential[]> {\n try {\n const files = await readdir(this.basePath);\n const jsonFiles = files.filter((f) => f.endsWith('.json'));\n const credentials: OrgCredential[] = [];\n for (const file of jsonFiles) {\n try {\n const content = await readFile(join(this.basePath, file), 'utf-8');\n credentials.push(JSON.parse(content) as OrgCredential);\n } catch {\n // Skip corrupted files\n }\n }\n return credentials;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw error;\n }\n }\n\n async exists(orgId: string): Promise<boolean> {\n try {\n await access(this.filePath(orgId));\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { StoredApiKey } from '../types/config.js';\n\nexport class KeyStore {\n private readonly basePath: string;\n\n constructor(basePath?: string) {\n // API keys are shared across runtime-plane CLIs (token/merchant/payment).\n // Stored under the legacy path for backward compatibility; will migrate to\n // ~/.agenzo/keys/ in a future release.\n this.basePath = basePath ?? join(homedir(), '.agenzo-token-cli', 'api-keys');\n }\n\n private filePath(orgId: string): string {\n return join(this.basePath, `${orgId}.json`);\n }\n\n private async loadData(orgId: string): Promise<StoredApiKey[]> {\n try {\n const content = await readFile(this.filePath(orgId), 'utf-8');\n return JSON.parse(content) as StoredApiKey[];\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw error;\n }\n }\n\n private async saveData(orgId: string, data: StoredApiKey[]): Promise<void> {\n // Stored API keys are plaintext secrets — dir 0700, file 0600.\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\n await chmod(this.basePath, 0o700);\n const path = this.filePath(orgId);\n await writeFile(path, JSON.stringify(data, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n await chmod(path, 0o600);\n }\n\n async add(orgId: string, key: StoredApiKey): Promise<void> {\n const data = await this.loadData(orgId);\n data.push(key);\n await this.saveData(orgId, data);\n }\n\n async update(orgId: string, keyId: string, newKeyValue: string): Promise<void> {\n const data = await this.loadData(orgId);\n const key = data.find((k) => k.key_id === keyId);\n if (key) {\n key.key_value = newKeyValue;\n await this.saveData(orgId, data);\n }\n }\n\n async list(orgId: string): Promise<StoredApiKey[]> {\n return this.loadData(orgId);\n }\n\n async get(orgId: string, keyId: string): Promise<StoredApiKey | null> {\n const data = await this.loadData(orgId);\n return data.find((k) => k.key_id === keyId) ?? null;\n }\n}\n","import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { AppConfig } from '../types/config.js';\nimport { ConfigError, ValidationError } from '../errors/errors.js';\n\n// §6 target routing: each product line is served under its own prefix\n// (/api/{line}/v1). The prefix is a per-binary constant injected into\n// ConfigManager (see constructor `apiPath`), NOT a single shared value — the\n// four CLIs hit different product lines under one shared api_host.\n// This default is the admin control-plane prefix; other CLIs override it.\nconst DEFAULT_API_PATH = '/api/admin/v1';\n\nconst DEFAULT_CONFIG: AppConfig = {\n active_org: null,\n active_developer_id: null,\n api_host: 'https://agent.everonet.com',\n api_path: DEFAULT_API_PATH,\n};\n\nexport const BUILTIN_PROFILES: Record<string, string> = {\n production: 'https://agent.everonet.com',\n testing: 'https://agent-test.everonet.com',\n};\n\n/**\n * Resolve a user-supplied host argument (a built-in profile name or an\n * explicit URL) to the concrete API host URL that gets persisted.\n * Pure (no I/O) so callers can compute the resolved value before/without a\n * config write — e.g. `config set-host` needs it to match stored credentials\n * by their resolved `api_host` rather than the raw profile name.\n * Throws `ValidationError` for unknown profiles / malformed URLs.\n */\nexport function resolveApiHost(host: string): string {\n if (BUILTIN_PROFILES[host]) {\n return BUILTIN_PROFILES[host];\n }\n\n let url: URL;\n try {\n url = new URL(host);\n } catch {\n throw new ValidationError(`Unknown profile or invalid URL: ${host}`);\n }\n\n if (url.protocol === 'https:') {\n return host;\n }\n\n if (\n url.protocol === 'http:'\n && (url.hostname === 'localhost' || url.hostname === '127.0.0.1')\n ) {\n return host;\n }\n\n // Docker 容器内部通信允许 HTTP(环境变量控制)\n if (url.protocol === 'http:' && process.env.AGENZO_ALLOW_INSECURE_HOST === '1') {\n return host;\n }\n\n throw new ValidationError(\n `Insecure API host is not allowed: ${host}. Use HTTPS, except for localhost or 127.0.0.1.`,\n );\n}\n\nexport class ConfigManager {\n private readonly basePath: string;\n private readonly configPath: string;\n /**\n * Product-line API prefix this CLI targets (e.g. /api/admin/v1,\n * /api/token/v1). Injected per binary so the four CLIs share one api_host\n * but route to different product lines. Overrides any persisted api_path.\n */\n private readonly apiPath: string;\n\n constructor(basePath?: string, apiPath?: string) {\n this.basePath = basePath ?? join(homedir(), '.agenzo-admin-cli');\n this.configPath = join(this.basePath, 'config.json');\n this.apiPath = apiPath ?? DEFAULT_API_PATH;\n }\n\n /** The resolved product-line API prefix for this CLI (per-binary constant). */\n getApiPath(): string {\n return this.apiPath;\n }\n\n async ensureDirectories(): Promise<void> {\n // Base dir contains the credentials/ subtree → owner-only (0700).\n await mkdir(this.basePath, { recursive: true, mode: 0o700 });\n await chmod(this.basePath, 0o700);\n const credDir = join(this.basePath, 'credentials');\n await mkdir(credDir, { recursive: true, mode: 0o700 });\n await chmod(credDir, 0o700);\n }\n\n async load(): Promise<AppConfig> {\n try {\n const content = await readFile(this.configPath, 'utf-8');\n try {\n const raw = JSON.parse(content) as Record<string, unknown>;\n // Migrate old api_base_url format\n if (raw.api_base_url && !raw.api_host) {\n const url = String(raw.api_base_url);\n const pathIndex = url.indexOf('/api/');\n raw.api_host = pathIndex > 0 ? url.slice(0, pathIndex) : url;\n raw.api_path = pathIndex > 0 ? url.slice(pathIndex) : DEFAULT_CONFIG.api_path;\n delete raw.api_base_url;\n }\n return {\n active_org: (raw.active_org as string) ?? null,\n active_developer_id: (raw.active_developer_id as string) ?? null,\n api_host: (raw.api_host as string) ?? DEFAULT_CONFIG.api_host,\n api_path: (raw.api_path as string) ?? DEFAULT_CONFIG.api_path,\n };\n } catch {\n throw new ConfigError(\n `Invalid config file: ${this.configPath}`,\n this.configPath,\n );\n }\n } catch (error) {\n if (error instanceof ConfigError) throw error;\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return { ...DEFAULT_CONFIG };\n }\n throw error;\n }\n }\n\n async save(config: AppConfig): Promise<void> {\n await this.ensureDirectories();\n await writeFile(this.configPath, JSON.stringify(config, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n await chmod(this.configPath, 0o600);\n }\n\n async getActiveOrg(): Promise<string | null> {\n const config = await this.load();\n return config.active_org;\n }\n\n async setActiveOrg(orgId: string): Promise<void> {\n const config = await this.load();\n config.active_org = orgId;\n await this.save(config);\n }\n\n async getApiBaseUrl(): Promise<string> {\n const config = await this.load();\n const host = resolveApiHost(config.api_host).replace(/\\/+$/, '');\n // Use the per-binary product-line prefix, not the persisted api_path —\n // the latter is shared across all CLIs and would route every binary to the\n // same product line. The injected prefix overrides any stale stored value.\n const path = this.apiPath.startsWith('/') ? this.apiPath : `/${this.apiPath}`;\n return `${host}${path}`;\n }\n\n async setApiHost(host: string): Promise<void> {\n const config = await this.load();\n config.api_host = resolveApiHost(host);\n await this.save(config);\n }\n\n async getApiHost(): Promise<string> {\n const config = await this.load();\n return resolveApiHost(config.api_host);\n }\n}\n","import { CliError } from '../errors/errors.js';\n\n/**\n * Exit-code mapper (cli-design §8.6 / cli-standard §5.4).\n *\n * Maps any thrown error reaching the top-level handler to one of the CLI's\n * non-zero exit codes. Normal completion implies `0` and never consults this.\n *\n * 1 — business / param: PARAM_* / RESOURCE_* / BILLING_* / ACCOUNT_* /\n * PAYMENT_ORDER_* / TOKEN_* / SERVICE_* / ride codes / CLIENT_* /\n * NOT_IMPLEMENTED, and unknown errors\n * 2 — upgrade required: UPGRADE_REQUIRED\n * 3 — auth-fail / invalid-key: AUTH_* / KEY_*\n * 4 — network / 5xx: UPSTREAM_ERROR / INTERNAL_ERROR / RATE_LIMITED\n * 5 — user-cancel: CLIENT_ABORTED\n */\nexport function exitCodeFor(error: unknown): 1 | 2 | 3 | 4 | 5 {\n if (!(error instanceof CliError)) {\n return 1;\n }\n\n const code = error.code;\n\n if (code === 'UPGRADE_REQUIRED') {\n return 2;\n }\n\n if (code === 'CLIENT_ABORTED') {\n return 5;\n }\n\n if (code.startsWith('AUTH_') || code.startsWith('KEY_')) {\n return 3;\n }\n\n if (\n code === 'UPSTREAM_ERROR' ||\n code === 'INTERNAL_ERROR' ||\n code === 'RATE_LIMITED'\n ) {\n return 4;\n }\n\n return 1;\n}\n","export type StatusPrefix = 'success' | 'error' | 'info' | 'warning' | 'loading';\n\nconst STATUS_ICONS: Record<StatusPrefix, string> = {\n success: '✓',\n error: '✗',\n info: 'ℹ',\n warning: '⚠',\n loading: '⠋',\n};\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nexport interface Spinner {\n /** Update the spinner message while it's running */\n update(message: string): void;\n /** Stop the spinner and show a final status line */\n stop(type?: StatusPrefix, finalMessage?: string): void;\n}\n\n/**\n * Creates an animated terminal spinner that cycles through braille frames.\n * Call `spinner.stop()` when the async work is done.\n */\nexport function createSpinner(message: string, intervalMs = 60): Spinner {\n let frameIdx = 0;\n let currentMessage = message;\n\n const render = () => {\n process.stdout.write(`\\r\\x1b[K${SPINNER_FRAMES[frameIdx]} ${currentMessage}`);\n frameIdx = (frameIdx + 1) % SPINNER_FRAMES.length;\n };\n\n render();\n const timer = setInterval(render, intervalMs);\n\n return {\n update(msg: string) {\n currentMessage = msg;\n },\n stop(type?: StatusPrefix, finalMessage?: string) {\n clearInterval(timer);\n process.stdout.write('\\r\\x1b[K');\n if (type && finalMessage) {\n console.log(Formatter.status(type, finalMessage));\n }\n },\n };\n}\n\nexport class Formatter {\n /** Get display width of a string (CJK characters count as 2) */\n private static displayWidth(str: string): number {\n let width = 0;\n for (const char of str) {\n const code = char.codePointAt(0)!;\n // CJK Unified Ideographs and common fullwidth ranges\n if (\n (code >= 0x4e00 && code <= 0x9fff) || // CJK Unified\n (code >= 0x3000 && code <= 0x303f) || // CJK Punctuation\n (code >= 0x3400 && code <= 0x4dbf) || // CJK Extension A\n (code >= 0xff00 && code <= 0xffef) || // Fullwidth Forms\n (code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility\n (code >= 0x20000 && code <= 0x2a6df) // CJK Extension B\n ) {\n width += 2;\n } else {\n width += 1;\n }\n }\n return width;\n }\n\n /** Pad string to target display width (right-pad with spaces) */\n private static padEndDisplay(str: string, targetWidth: number): string {\n const currentWidth = Formatter.displayWidth(str);\n const padding = Math.max(0, targetWidth - currentWidth);\n return str + ' '.repeat(padding);\n }\n\n /** Pad string to target display width (left-pad with spaces) */\n private static padStartDisplay(str: string, targetWidth: number): string {\n const currentWidth = Formatter.displayWidth(str);\n const padding = Math.max(0, targetWidth - currentWidth);\n return ' '.repeat(padding) + str;\n }\n\n /** Table output for list commands — columns aligned by max width */\n static table(headers: string[], rows: string[][]): string {\n const colWidths = headers.map((h, i) => {\n const cellWidths = rows.map((r) => Formatter.displayWidth(r[i] ?? ''));\n return Math.max(Formatter.displayWidth(h), ...cellWidths);\n });\n\n const sep = ' ';\n\n const headerLine = headers.map((h, i) => Formatter.padEndDisplay(h, colWidths[i])).join(sep);\n const divider = colWidths.map((w) => '-'.repeat(w)).join(sep);\n const dataLines = rows.map((row) =>\n row.map((cell, i) => Formatter.padEndDisplay(cell ?? '', colWidths[i])).join(sep),\n );\n\n return [headerLine, divider, ...dataLines].join('\\n');\n }\n\n /** Key-value output for detail commands — keys left-aligned */\n static keyValue(entries: [string, string][]): string {\n const maxKeyWidth = Math.max(...entries.map(([k]) => Formatter.displayWidth(k)));\n return entries\n .map(([key, value]) => `${Formatter.padEndDisplay(key, maxKeyWidth)} ${value}`)\n .join('\\n');\n }\n\n /** Status-prefixed message */\n static status(type: StatusPrefix, message: string): string {\n return `${STATUS_ICONS[type]} ${message}`;\n }\n\n /** Mask sensitive info, keeping only the prefix */\n static maskKey(key: string, prefixLength = 8): string {\n if (key.length <= prefixLength) {\n return key;\n }\n return key.slice(0, prefixLength) + '*'.repeat(key.length - prefixLength);\n }\n\n /**\n * Format ISO 8601 timestamp to local timezone display.\n * Automatically uses the user's system timezone.\n * e.g. \"2026-05-07T03:24:53+00:00\" → \"2026-05-07 11:24:53\" (in CST)\n * \"2026-05-07T03:24:53+00:00\" → \"2026-05-06 20:24:53\" (in PDT)\n * Returns the original string if parsing fails or input is empty.\n */\n static formatTime(iso: string | null | undefined): string {\n if (!iso) return '';\n const date = new Date(iso);\n if (isNaN(date.getTime())) return iso;\n const pad = (n: number) => String(n).padStart(2, '0');\n const y = date.getFullYear();\n const m = pad(date.getMonth() + 1);\n const d = pad(date.getDate());\n const h = pad(date.getHours());\n const min = pad(date.getMinutes());\n const s = pad(date.getSeconds());\n const offsetMin = -date.getTimezoneOffset();\n const sign = offsetMin >= 0 ? '+' : '-';\n const absOffset = Math.abs(offsetMin);\n const tzH = pad(Math.floor(absOffset / 60));\n const tzM = pad(absOffset % 60);\n return `${y}-${m}-${d} ${h}:${min}:${s} (UTC${sign}${tzH}:${tzM})`;\n }\n}\n","import type { CommandResult } from '../types/commands.js';\nimport { Formatter, type StatusPrefix } from './formatter.js';\n\n/**\n * Central output renderer.\n *\n * Single choke point that turns a {@link CommandResult} into stdout bytes,\n * switching between machine-readable JSON and a human-readable table view.\n * This is what lets command handlers stop calling `console.log` directly:\n * they build a `CommandResult` and hand it here.\n *\n * Contract (cli-standard §5.1/§5.2):\n * - stdout carries ONLY the business payload — a single JSON value\n * (`--format json`) or human-readable text (`--format table`).\n * - logs, spinners, prompts, hints and progress lines belong on stderr and\n * are NEVER written here.\n *\n * Recorded deviation from cli-standard §5.1: the default format is `table`\n * (not `json`), and the flag values are `json | table` (not `json | text`).\n */\n\n/** The two supported output formats. */\nexport type OutputFormat = 'json' | 'table';\n\n/** Options consumed by {@link render}. */\nexport interface RenderOptions {\n format: OutputFormat;\n}\n\n/** The default format used when nothing valid is supplied (deliberate deviation: `table`). */\nconst DEFAULT_FORMAT: OutputFormat = 'table';\n\n/** Narrow an arbitrary string to a known {@link OutputFormat}. */\nfunction isOutputFormat(value: string): value is OutputFormat {\n return value === 'json' || value === 'table';\n}\n\n/**\n * Resolve the active output format.\n *\n * Precedence: `--format` flag > `AGENZO_FORMAT` env var > default `table`.\n * Any invalid value falls back to the default. The result is always one of\n * `'json' | 'table'`.\n *\n * The `--format` flag is authoritative when provided: a provided-but-invalid\n * flag falls back to the default rather than deferring to the environment.\n */\nexport function resolveFormat(\n flag?: string,\n env: string | undefined = process.env.AGENZO_FORMAT,\n): OutputFormat {\n // 1. --format flag is authoritative when provided.\n if (flag !== undefined) {\n return isOutputFormat(flag) ? flag : DEFAULT_FORMAT;\n }\n // 2. AGENZO_FORMAT environment value, when set to a valid format.\n if (env !== undefined && isOutputFormat(env)) {\n return env;\n }\n // 3. Default.\n return DEFAULT_FORMAT;\n}\n\n/**\n * Emit a successful command result to stdout in the chosen format.\n *\n * - `json`: writes `JSON.stringify(result.data, null, 2)` (the machine payload\n * only — never the text-mode chrome).\n * - `table`: writes the lazy human presenter `result.text()`.\n *\n * Only the payload reaches stdout; status/progress lines must go to stderr by\n * the caller. A trailing newline is appended so the output pipes cleanly into\n * tools like `jq`.\n */\nexport function render<T>(result: CommandResult<T>, opts: RenderOptions): void {\n if (opts.format === 'json') {\n process.stdout.write(`${JSON.stringify(result.data, null, 2)}\\n`);\n return;\n }\n process.stdout.write(`${result.text()}\\n`);\n}\n\n/**\n * Emit a human-facing status line (✓ / ℹ / ⚠) to stderr — but ONLY in `table`\n * mode. In `json` mode the output is consumed by other agents/scripts, so any\n * decorative status text (even on stderr) is noise that can confuse parsing;\n * `json` mode therefore stays completely silent here. Errors are NOT routed\n * through this helper — they are owned by the top-level handler in index.ts.\n *\n * This is the single choke point for command success/progress notices, so the\n * `json`-silence rule is enforced in one place rather than scattered across\n * every handler.\n */\nexport function notify(\n format: OutputFormat,\n type: StatusPrefix,\n message: string,\n): void {\n if (format === 'json') {\n return;\n }\n console.error(Formatter.status(type, message));\n}\n","/**\n * Shared JSON envelope renderer (cli-design §7.7.2 BACK-011).\n *\n * In `--format json` mode, every command's payload is prefixed with two\n * client-assembled context fields:\n * - `profile`: the active environment name (production / testing / custom),\n * derived by reverse-looking-up the api_host in BUILTIN_PROFILES.\n * - `endpoint`: the api **host only** (e.g. https://agent.everonet.com) —\n * NEVER the internal API path (/api/admin/v1), so internal\n * routing is not leaked to agent consumers.\n *\n * `result.data` is expected to be an object (single-resource payloads are flat\n * field maps; list payloads are `{ <namedKey>: [...], page: {...} }`). The two\n * context fields are spread in front of it.\n *\n * In `--format table` mode this is a passthrough to the standard `render`.\n *\n * This lives in `@agenzo/cli-core` (BACK-011) so every CLI shares one\n * implementation rather than copying it per app.\n */\nimport type { CommandResult } from '../types/commands.js';\nimport { type RenderOptions, render } from './output.js';\nimport { ConfigManager, BUILTIN_PROFILES } from '../config/config-manager.js';\n\nexport async function renderWithContext<T>(\n result: CommandResult<T>,\n opts: RenderOptions,\n configManager: ConfigManager,\n): Promise<void> {\n if (opts.format !== 'json') {\n render(result, opts);\n return;\n }\n\n const config = await configManager.load();\n const host = config.api_host.replace(/\\/+$/, '');\n const profile =\n Object.entries(BUILTIN_PROFILES).find(([, v]) => v === host)?.[0] ?? 'custom';\n\n const dataObj =\n result.data && typeof result.data === 'object'\n ? (result.data as Record<string, unknown>)\n : { value: result.data };\n\n const payload = {\n profile,\n endpoint: host,\n ...dataObj,\n };\n\n render({ ...result, data: payload } as CommandResult<typeof payload>, opts);\n}\n","import { input, password, select } from '@inquirer/prompts';\n\ninterface PromptConfig {\n message: string;\n type?: 'input' | 'password' | 'select';\n choices?: { name: string; value: string }[];\n validate?: (input: string) => boolean | string;\n}\n\nexport class PromptEngine {\n /** Return flagValue directly if provided, otherwise prompt interactively */\n static async resolveInput(\n flagValue: string | undefined,\n config: PromptConfig,\n ): Promise<string> {\n if (flagValue !== undefined) {\n return flagValue;\n }\n\n if (config.type === 'password') {\n return password({ message: config.message, mask: '*' });\n }\n\n if (config.type === 'select' && config.choices) {\n return select({\n message: config.message,\n choices: config.choices,\n });\n }\n\n return input({\n message: config.message,\n validate: config.validate,\n });\n }\n}\n","import type { ApiClient } from '@agenzo/cli-core';\nimport { CliError } from '@agenzo/cli-core';\nimport type { GetOrderResponse } from '../types/api.js';\n\n/**\n * NDJSON status-polling for `ride-elife get --watch` (§4.4.1.3 polling /\n * design Property 2). Merchant-domain logic — stays in the app per\n * requirement 4.4 (NOT pushed down to cli-core).\n *\n * The watch stream is a line stream: each poll result is written as ONE\n * independent, compact JSON line on stdout. It is deliberately NOT routed\n * through `renderWithContext`, so the profile/endpoint envelope is never\n * wrapped around the stream (an agent consumes it with a line reader).\n *\n * The polling engine is split from its I/O so it can be unit/PBT-tested with a\n * fake clock and shortened constants (task 6.5): `fetchStatus`, `writeLine`,\n * `sleep` and `now` are all injected.\n */\n\n/**\n * Terminal ride statuses (schema `polling.terminal_statuses`). Once the order\n * reaches one of these, `--watch` stops polling. CASE-SENSITIVE — must match\n * the server casing exactly.\n */\nexport const TERMINAL_STATUSES: ReadonlySet<string> = new Set([\n 'At destination',\n 'Cancelled',\n 'Rejected',\n 'Customer no show',\n 'Driver no show',\n]);\n\n/** Schema `polling.recommended_interval_seconds`. */\nexport const DEFAULT_WATCH_INTERVAL_SECONDS = 5;\n/** Safety cap so `--watch` can never poll forever. */\nexport const DEFAULT_WATCH_TIMEOUT_SECONDS = 600;\n\n/**\n * Pure terminal-state predicate (exported for direct unit/PBT testing). A\n * missing/undefined status is never terminal, so polling continues until a\n * known terminal status or the timeout.\n */\nexport function isTerminalStatus(status: string | undefined | null): boolean {\n return status !== undefined && status !== null && TERMINAL_STATUSES.has(status);\n}\n\n/** Read the case-sensitive `status` field off a poll result. */\nexport function statusOf(data: GetOrderResponse): string | undefined {\n const status = (data as { status?: unknown }).status;\n return typeof status === 'string' ? status : undefined;\n}\n\n/** The final NDJSON line emitted when polling gives up before a terminal status. */\nexport interface WatchTimeoutLine {\n watch_status: 'timeout';\n message: string;\n last_status: string | null;\n}\n\n/** I/O + clock seams the polling engine depends on (all injectable for tests). */\nexport interface WatchEngineDeps {\n /** Fetch one status snapshot (throws to abort the whole stream). */\n fetchStatus: () => Promise<GetOrderResponse>;\n /** Write one NDJSON record as a single compact line. */\n writeLine: (record: unknown) => void;\n /** Resolve after `ms` (real timer in prod; fake clock in tests). */\n sleep: (ms: number) => Promise<void>;\n /** Current epoch millis (real `Date.now` in prod; fake clock in tests). */\n now: () => number;\n}\n\n/** Interval / timeout budget for one watch run, in milliseconds. */\nexport interface WatchEngineOptions {\n intervalMs: number;\n timeoutMs: number;\n}\n\n/**\n * Poll `fetchStatus`, writing each result as an NDJSON line, until the order\n * reaches a terminal status or the timeout elapses. On timeout the FINAL line\n * is `{ watch_status: 'timeout', ... }` (requirement 3.2 / Property 2).\n *\n * Termination: every iteration either returns (terminal status) or, when the\n * next poll would land at/after the deadline, emits the timeout line and\n * returns. With a monotonically advancing clock (real time, or a fake clock\n * advanced by `sleep`) the deadline is always reached, so the loop is\n * guaranteed to terminate for any status sequence.\n */\nexport async function runWatch(\n deps: WatchEngineDeps,\n opts: WatchEngineOptions,\n): Promise<void> {\n const deadline = deps.now() + opts.timeoutMs;\n for (;;) {\n const data = await deps.fetchStatus();\n deps.writeLine(data);\n\n const status = statusOf(data);\n if (isTerminalStatus(status)) {\n return;\n }\n\n if (deps.now() + opts.intervalMs >= deadline) {\n const timeoutLine: WatchTimeoutLine = {\n watch_status: 'timeout',\n message: `Polling stopped after ${opts.timeoutMs / 1000}s without reaching a terminal status.`,\n last_status: status ?? null,\n };\n deps.writeLine(timeoutLine);\n return;\n }\n\n await deps.sleep(opts.intervalMs);\n }\n}\n\n/**\n * Parse a positive `--watch-*` seconds flag, falling back to a default when\n * absent or non-positive (mirrors the standalone reference behaviour). Returns\n * a value in SECONDS.\n */\nexport function resolveSeconds(value: string | undefined, fallback: number): number {\n if (value === undefined) return fallback;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : fallback;\n}\n\n/** Real-timer sleep used by the production watch path. */\nexport const realSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Compact single-line NDJSON writer used by the production watch path. */\nexport const ndjsonWriteLine = (record: unknown): void => {\n process.stdout.write(`${JSON.stringify(record)}\\n`);\n};\n\n/**\n * Production wiring for `ride-elife get --watch`: bind the polling engine to a\n * live `ApiClient` (status endpoint + api-key auth), the compact NDJSON stdout\n * writer, real timers and the system clock. A network/backend failure on any\n * poll surfaces as a `CliError` to the top-level handler, exactly like the\n * single-shot path.\n */\nexport async function watchRideStatus(\n apiClient: ApiClient,\n apiKey: string,\n orderId: string,\n opts: { intervalSeconds: number; timeoutSeconds: number },\n): Promise<void> {\n const path = `/ride/${encodeURIComponent(orderId)}/status`;\n await runWatch(\n {\n fetchStatus: async () => {\n const result = await apiClient.get<GetOrderResponse>(path, {\n type: 'api-key',\n key: apiKey,\n });\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n return result.data;\n },\n writeLine: ndjsonWriteLine,\n sleep: realSleep,\n now: () => Date.now(),\n },\n {\n intervalMs: opts.intervalSeconds * 1000,\n timeoutMs: opts.timeoutSeconds * 1000,\n },\n );\n}\n","/**\n * `--help --format json` verb-level schema (§4.4.1.3) — merchant domain only.\n *\n * Every ride-elife verb supports `--help --format json`, which prints a single\n * machine-readable JSON object describing the verb instead of commander's\n * default text help. This is the standard way an Agent discovers a verb's\n * flags, response shape, example invocation and (where relevant) error-recovery\n * and polling guidance locally, without a network round-trip.\n *\n * admin-cli / token-cli have no such mode, so this lives in the app (not in\n * cli-core) per requirement 4.4.\n *\n * Mechanism (commander v14): `attachSchemaHelp` overrides a command's\n * `helpInformation`. Commander resolves `--help` BEFORE later argv tokens are\n * applied to options, so the parsed `--format` value is not yet available when\n * help renders — we therefore read it straight from `process.argv`. Only an\n * explicit `--format json` switches to the JSON schema; bare `--help` and\n * `--help --format table` keep commander's default text help.\n */\nimport type { Command } from 'commander';\nimport { TERMINAL_STATUSES, DEFAULT_WATCH_INTERVAL_SECONDS } from './ride-elife/watch.js';\n\nconst CLI_NAME = 'agenzo-merchant-cli';\nconst NOUN = 'ride-elife';\n\n// ============================================================\n// Schema shape (§4.4.1.3 verb-level schema)\n// ============================================================\n\n/** One flag descriptor: type / required / optional default / description / constraints. */\nexport interface FlagSchema {\n type: string;\n /** `true` / `false`, or the literal `'conditional'` for mode-dependent flags. */\n required: boolean | 'conditional';\n default?: unknown;\n description: string;\n constraints?: string;\n}\n\n/** A complete, copy-pasteable example invocation plus what to read from the output. */\nexport interface ExampleSchema {\n command: string;\n output_summary: string;\n}\n\n/** Polling guidance — only status-query verbs (`get`) carry this block. */\nexport interface PollingSchema {\n recommended_interval_seconds: number;\n terminal_statuses: string[];\n in_progress_statuses: string[];\n field_availability?: Record<string, string>;\n}\n\n/**\n * The verb-level schema object emitted by `--help --format json`\n * (§4.4.1.3): `{ cli, noun, verb, description, flags, response, example,\n * [error_recovery], [polling] }`. `error_recovery` / `polling` are optional and\n * present only where the verb warrants them.\n */\nexport interface VerbSchema {\n cli: string;\n noun: string;\n verb: string;\n description: string;\n flags: Record<string, FlagSchema>;\n /** Key response fields + type descriptions (nested objects allowed). */\n response: Record<string, unknown>;\n example: ExampleSchema;\n error_recovery?: Record<string, string>;\n polling?: PollingSchema;\n}\n\n// ============================================================\n// Emit + attach mechanism\n// ============================================================\n\n/**\n * True only when `--format json` is explicitly present in `argv`. Commander\n * resolves `--help` before applying later option tokens, so the parsed format\n * is not yet available at help-render time; we read argv directly. Bare `--help`\n * and `--help --format table` deliberately return false (keep text help), even\n * though the program defaults `--format` to json — the default is never written\n * into argv.\n */\nexport function wantsJsonSchema(argv: string[] = process.argv): boolean {\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n if (a === '--format=json') return true;\n if (a === '--format' && argv[i + 1] === 'json') return true;\n }\n return false;\n}\n\n/** Print a verb schema as a single pretty-printed JSON object to stdout. */\nexport function emitSchema(schema: VerbSchema): void {\n console.log(JSON.stringify(schema, null, 2));\n}\n\n/**\n * Attach `--help --format json` schema output to a command. When help is\n * requested with an explicit `--format json`, the schema is printed to stdout\n * and an empty string is returned so commander prints nothing further and exits\n * cleanly. Otherwise the original (text) help is rendered unchanged.\n */\nexport function attachSchemaHelp(cmd: Command, schema: VerbSchema): Command {\n const baseHelp = cmd.helpInformation.bind(cmd);\n cmd.helpInformation = (context) => {\n if (!wantsJsonSchema()) return baseHelp(context);\n emitSchema(schema);\n return '';\n };\n return cmd;\n}\n\n// ============================================================\n// Ride-elife verb schemas\n// ============================================================\n//\n// Flags / response are kept aligned with each command's ACTUAL flags and the\n// cli-core response types (QuoteResponse / BookResponse / GetOrderResponse /\n// CancelResponse / ListOrdersResponse). Notably: quote's passenger fields are\n// optional here (the command only sends them when set); get's pickup/dropoff\n// are `from_location` / `to_location` (v3 snake_case, NOT elife from/to);\n// amounts are decimal currency units (NOT cents).\n\n/** `ride-elife quote` schema (§4.4.1.3 quote schema). */\nexport const quoteSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'quote',\n description: 'Request fare quotes for a ride between two points',\n flags: {\n 'pickup-lat': { type: 'float', required: true, description: 'Pickup latitude', constraints: '-90 to 90' },\n 'pickup-lng': { type: 'float', required: true, description: 'Pickup longitude', constraints: '-180 to 180' },\n 'pickup-name': { type: 'string', required: true, description: 'Pickup location name' },\n 'dropoff-lat': { type: 'float', required: true, description: 'Dropoff latitude', constraints: '-90 to 90' },\n 'dropoff-lng': { type: 'float', required: true, description: 'Dropoff longitude', constraints: '-180 to 180' },\n 'dropoff-name': { type: 'string', required: true, description: 'Dropoff location name' },\n 'pickup-time': {\n type: 'int|string',\n required: true,\n description: \"Epoch seconds or the literal 'now'\",\n },\n 'passenger-name': { type: 'string', required: false, description: 'Lead passenger full name' },\n 'passenger-phone': { type: 'string', required: false, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\n 'passenger-count': { type: 'int', required: false, description: 'Number of passengers' },\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\n 'passenger-email': { type: 'string', required: false, description: 'Passenger email address' },\n 'children-count': { type: 'int', required: false, description: 'Number of children' },\n },\n response: {\n vehicle_classes: {\n type: 'array',\n description: 'Available vehicle options with pricing',\n items: {\n vehicle_class: { type: 'string', description: 'Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\n 'price.amount': { type: 'float', description: 'Price in currency units (e.g. 42.50), NOT cents' },\n 'price.currency': { type: 'string', description: 'ISO 4217 (e.g. USD)' },\n 'price.quote_id': { type: 'string', description: 'Use this in `ride-elife book --quote-id`' },\n passenger_capacity: { type: 'int', description: 'Max passengers' },\n luggage_capacity: { type: 'int', description: 'Max luggage items' },\n },\n },\n meet_and_greet: { type: 'object|null', description: 'Meet & greet availability and price' },\n is_airport_transfer: { type: 'bool', description: 'Whether this is an airport transfer' },\n airport_direction: { type: 'string|null', description: 'pickup / dropoff / null' },\n },\n example: {\n command:\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',\n output_summary:\n 'Returns vehicle_classes[] with a quote_id per option. Use quote_id and vehicle_class for booking.',\n },\n error_recovery: {\n VEHICLE_UNAVAILABLE: 'No vehicles for this route/time. Try a different pickup-time or location. Do NOT blindly retry.',\n PARAM_INVALID: 'Fix the offending flag (coordinates must be numbers; required pickup/dropoff/pickup-time present), then retry.',\n },\n};\n\n/** `ride-elife book` schema (§4.4.1.3 book schema). Write op (W/Y). */\nexport const bookSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'book',\n description: 'Book a ride using a quote_id returned by a previous quote call',\n flags: {\n 'quote-id': { type: 'string', required: true, description: 'Quote id from quote response (vehicle_classes[].price.quote_id)' },\n 'vehicle-class': { type: 'string', required: true, description: 'Vehicle class: Sedan / SUV / MPV-5 / MPV-7 / Van / Luxury / Train' },\n 'price-amount': { type: 'float', required: true, description: 'Fare in decimal currency units (NOT cents), from the quote' },\n 'price-currency': { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code' },\n 'payment-order-id': {\n type: 'string',\n required: 'conditional',\n description: 'Required when billing_mode=pay_per_call (a PAID payment order). Forbidden when billing_mode=monthly_settlement',\n },\n 'passenger-name': { type: 'string', required: true, description: 'Passenger full name' },\n 'passenger-phone': { type: 'string', required: true, description: 'Passenger phone in E.164 format (e.g. +14155551234)' },\n 'passenger-email': { type: 'string', required: true, description: 'Passenger email (required by eLife for booking)' },\n 'luggage-count': { type: 'int', required: false, description: 'Number of luggage items' },\n 'special-requests': { type: 'string', required: false, description: 'Free-text special requests or notes' },\n 'pickup-lat': { type: 'float', required: false, description: 'Pickup latitude (must match the quote)', constraints: '-90 to 90' },\n 'pickup-lng': { type: 'float', required: false, description: 'Pickup longitude (must match the quote)', constraints: '-180 to 180' },\n 'pickup-name': { type: 'string', required: false, description: 'Pickup location name (must match the quote)' },\n 'dropoff-lat': { type: 'float', required: false, description: 'Dropoff latitude (must match the quote)', constraints: '-90 to 90' },\n 'dropoff-lng': { type: 'float', required: false, description: 'Dropoff longitude (must match the quote)', constraints: '-180 to 180' },\n 'dropoff-name': { type: 'string', required: false, description: 'Dropoff location name (must match the quote)' },\n 'pickup-time': { type: 'int|string', required: false, description: \"Epoch seconds or 'now' (must match the quote)\" },\n 'meet-and-greet': { type: 'bool', required: false, default: false, description: 'Enable meet & greet service' },\n 'meet-and-greet-price': { type: 'float', required: false, description: 'Meet & greet surcharge from the quote (meet_and_greet.price.amount)' },\n 'welcome-sign': { type: 'string', required: false, description: 'Welcome sign text (meet & greet)' },\n 'child-seat-count': { type: 'int', required: false, description: 'Number of child seats needed', constraints: '0 to 5' },\n 'infant-seat-count': { type: 'int', required: false, description: 'Number of infant seats needed', constraints: '0 to 5' },\n 'toddler-seat-count': { type: 'int', required: false, description: 'Number of toddler seats needed', constraints: '0 to 5' },\n 'arrival-flight-no': { type: 'string', required: false, description: 'Arrival flight number (airport pickup)' },\n 'arrival-airline': { type: 'string', required: false, description: 'Arrival airline name' },\n 'departure-flight-no': { type: 'string', required: false, description: 'Departure flight number (airport dropoff)' },\n 'departure-airline': { type: 'string', required: false, description: 'Departure airline name' },\n 'idempotency-key': {\n type: 'string',\n required: true,\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\n },\n },\n response: {\n ride_id: { type: 'string|int', description: 'Ride identifier — use for `ride-elife get` / `ride-elife cancel`' },\n order_id: { type: 'string|int', description: 'Internal order id for reconciliation' },\n status: { type: 'string', description: 'Ride status (case-sensitive server casing)' },\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride; false = realtime' },\n order_type: { type: 'string', description: \"'realtime' or 'airport'\" },\n price: { type: 'object', description: '{ amount, currency, quote_id }' },\n payment_status: { type: 'string', description: 'PAID (pay_per_call) or ON_ACCOUNT (monthly_settlement)' },\n billing_entry_id: { type: 'string|absent', description: 'Only in monthly_settlement mode' },\n payment_order_id: { type: 'string|absent', description: 'Only in pay_per_call mode (echoes the request)' },\n },\n example: {\n command:\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',\n output_summary: 'Returns ride_id. Use ride_id in `ride-elife get` to poll status.',\n },\n error_recovery: {\n QUOTE_EXPIRED: \"Re-invoke 'quote' for a fresh quote_id, then retry 'book' with the SAME --idempotency-key.\",\n BILLING_MODE_MISMATCH: 'Check Developer.billing_mode. pay_per_call requires --payment-order-id; monthly_settlement forbids it.',\n PAYMENT_ORDER_NOT_PAID: 'Wait for the payment order status=PAID, then retry with the SAME --idempotency-key.',\n PAYMENT_ORDER_ALREADY_CONSUMED: 'Create a new payment order, then retry with the new payment-order-id and a NEW --idempotency-key.',\n ACCOUNT_INSUFFICIENT_BALANCE: 'Top up the settlement account (offline) or pick a cheaper vehicle_class, then retry.',\n BOOKING_FAILED: 'elife rejected after settlement. The message contains a ref: for manual reconciliation. Do NOT auto-retry.',\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\n },\n};\n\n/** `ride-elife get` schema (§4.4.1.3 get schema). Read-only, supports `--watch`. */\nexport const rideGetSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'get',\n description: 'Retrieve a ride order status by id; with --watch, poll until a terminal status',\n flags: {\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' },\n watch: { type: 'bool', required: false, default: false, description: 'Poll until a terminal status, emitting one NDJSON line per update' },\n 'watch-interval': { type: 'int', required: false, default: DEFAULT_WATCH_INTERVAL_SECONDS, description: 'Seconds between polls when --watch is set' },\n 'watch-timeout': { type: 'int', required: false, default: 600, description: 'Max seconds to poll before giving up' },\n },\n response: {\n ride_id: { type: 'string|int', description: 'Ride identifier' },\n status: { type: 'string', description: 'Pending / Accepted / On my way / Waiting / On board / At destination / Rejected / Cancelled / Customer no show / Driver no show' },\n source: { type: 'string', description: \"'local_cache' when served from the local fallback; 'mock' in sandbox\" },\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport ride' },\n from_location: { type: 'object', description: 'Pickup { lat, lng, name, address } (v3 snake_case, NOT elife from/to)' },\n to_location: { type: 'object', description: 'Dropoff { lat, lng, name, address }' },\n pickup_time: { type: 'int|string', description: 'Pickup time' },\n vehicle_class: { type: 'string|null', description: 'Vehicle class' },\n price: { type: 'object', description: '{ amount, currency, quote_id }' },\n final_amount: { type: 'float|null', description: 'Final settled fare (realtime, after final-fare settlement)' },\n final_settlement_status: { type: 'string', description: 'pending / settled / no_adjustment / settlement_pending / not_applicable' },\n driver: { type: 'object|null', description: '{ name, phone_number } — available after a driver is assigned' },\n vehicle: { type: 'object|null', description: '{ make, model, color, license_plate, image_url } — available after a driver is assigned' },\n created_at: { type: 'string', description: 'Order creation time' },\n },\n example: {\n command: 'agenzo-merchant-cli ride-elife get --order-id EL-20260527-1023456',\n output_summary:\n 'Returns current status and driver/vehicle info. Terminal statuses: At destination, Cancelled, Rejected, Customer no show, Driver no show.',\n },\n polling: {\n recommended_interval_seconds: DEFAULT_WATCH_INTERVAL_SECONDS,\n terminal_statuses: [...TERMINAL_STATUSES],\n in_progress_statuses: ['Pending', 'Accepted', 'On my way', 'Waiting', 'On board'],\n field_availability: {\n driver: \"Populated from status 'Accepted' onwards (after a driver is dispatched). Null in 'Pending'.\",\n vehicle: \"Populated from status 'Accepted' onwards. Null in 'Pending'.\",\n },\n },\n error_recovery: {\n VEHICLE_UNAVAILABLE: 'Order not found. Verify --order-id is the ride_id from book. Do NOT retry.',\n BOOKING_FAILED: 'Transient elife error. Retry once after 5s.',\n },\n};\n\n/** `ride-elife cancel` schema (§4.4.1.3 cancel schema). Write op (W/Y). */\nexport const cancelSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'cancel',\n description: 'Cancel a ride order by id (a cancellation fee may apply depending on ride status)',\n flags: {\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' },\n 'idempotency-key': {\n type: 'string',\n required: true,\n description: 'Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated',\n },\n },\n response: {\n ride_id: { type: 'string|int', description: 'Cancelled ride id' },\n ride_stat: { type: 'string', description: \"Status after cancellation (typically 'Cancelled')\" },\n cancellation: {\n type: 'object|null',\n description: 'Cancellation details',\n properties: {\n cancellation_fee: { type: 'float', description: 'Fee charged for cancellation' },\n reversal_amount: { type: 'float', description: 'Amount reversed/refunded' },\n currency: { type: 'string', description: 'ISO 4217 currency code' },\n },\n },\n refund_amount: { type: 'float', description: 'Amount credited back to the settlement balance (paid − cancellation_fee)' },\n },\n example: {\n command: 'agenzo-merchant-cli ride-elife cancel --order-id EL-20260527-1023456 --idempotency-key cancel-456',\n output_summary: 'Returns cancellation fee and refund amount.',\n },\n error_recovery: {\n CANCELLATION_NOT_ALLOWED: 'The ride is in a non-cancellable state. Do NOT retry; query status with `ride-elife get`.',\n PARAM_IDEMPOTENCY_KEY_REQUIRED: 'Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes.',\n },\n};\n\n/** `ride-elife list-orders` schema (§4.4.1.3 list-orders schema). Read-only. */\nexport const listOrdersSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: NOUN,\n verb: 'list-orders',\n description: 'List previously placed ride orders with optional filters and pagination',\n flags: {\n status: { type: 'string', required: false, description: 'Filter by ride status (case-sensitive server casing)' },\n 'order-type': { type: 'string', required: false, description: 'Filter by order type (e.g. realtime / airport)' },\n page: { type: 'int', required: false, default: 1, description: 'Page number', constraints: '>= 1' },\n 'page-size': { type: 'int', required: false, default: 20, description: 'Items per page', constraints: '>= 1' },\n },\n response: {\n orders: {\n type: 'array',\n description: 'List of ride orders (slim list-item shape)',\n items: {\n order_id: { type: 'string', description: 'Internal order id' },\n ride_id: { type: 'string', description: 'Ride id (same as ride_id from book)' },\n status: { type: 'string', description: 'Current ride status' },\n vehicle_class: { type: 'string', description: 'Vehicle class' },\n is_scheduled: { type: 'bool', description: 'true = scheduled/airport, false = realtime' },\n scheduled_at: { type: 'string', description: 'ISO 8601 datetime; empty for realtime orders' },\n price_amount: { type: 'float|null', description: 'Price in decimal currency units (NOT cents)' },\n final_amount: { type: 'float|null', description: 'Final settled amount' },\n price_currency: { type: 'string', description: 'ISO 4217 currency code' },\n payment_status: { type: 'string', description: 'Payment status' },\n final_settlement_status: { type: 'string', description: 'pending / settled / no_adjustment / settlement_pending / not_applicable' },\n cancellation_fee: { type: 'float|null', description: 'Cancellation fee for cancelled orders; null otherwise' },\n provider: { type: 'string', description: 'Service provider (elife)' },\n created_at: { type: 'string|null', description: 'Order creation time (ISO 8601)' },\n updated_at: { type: 'string|null', description: 'Last update time (ISO 8601)' },\n },\n },\n total: { type: 'int', description: 'Total matching orders' },\n page: { type: 'int', description: 'Current page' },\n page_size: { type: 'int', description: 'Items per page' },\n },\n example: {\n command: 'agenzo-merchant-cli ride-elife list-orders --status Pending --page 1 --page-size 10',\n output_summary: 'Returns a paginated list of ride orders with status and amount info.',\n },\n error_recovery: {\n INTERNAL_ERROR: 'Transient backend error. Retry once after a short delay.',\n PARAM_INVALID: 'Ensure --page / --page-size are positive integers, then retry.',\n },\n};\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { QuoteResponse, VehicleClass } from '../types/api.js';\nimport { attachSchemaHelp, quoteSchema } from '../verb-schema.js';\n\n// ============================================================\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\n// ============================================================\n\n/**\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\n * (requirement 2.1 / design §4.4.1.3) — a catalog code (exit 1), never\n * `PARAM_REQUIRED` (not in the cli-core error catalog).\n */\nfunction need(value: string | undefined, flag: string): string {\n if (value === undefined) {\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\n }\n return value;\n}\n\n/**\n * Number-ify a coordinate / numeric flag. Non-finite input maps to\n * `PARAM_INVALID`. Coordinates are sent as numbers, never strings (§4.4.1.3).\n */\nfunction num(value: string | undefined, flag: string): number {\n const n = Number(need(value, flag));\n if (!Number.isFinite(n)) {\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\n }\n return n;\n}\n\n// ============================================================\n// Output helper (table summary)\n// ============================================================\n\n/**\n * Render the quote as a table for `--format table`. Each vehicle class is one\n * row; amounts are decimal currency units (NOT cents) — printed verbatim.\n */\nfunction formatQuote(data: QuoteResponse): string {\n const classes: VehicleClass[] = data.vehicle_classes ?? [];\n if (classes.length === 0) {\n return Formatter.status('info', 'No vehicle classes available for this route');\n }\n\n const headers = ['Vehicle Class', 'Price', 'Currency', 'Quote ID', 'Pax', 'Luggage'];\n const rows = classes.map((vc) => [\n String(vc.vehicle_class ?? '-'),\n String(vc.price?.amount ?? '-'),\n String(vc.price?.currency ?? '-'),\n String(vc.price?.quote_id ?? '-'),\n String(vc.passenger_capacity ?? '-'),\n String(vc.luggage_capacity ?? '-'),\n ]);\n\n const lines: [string, string][] = [\n ['Airport transfer', String(data.is_airport_transfer ?? false)],\n ];\n if (data.airport_direction) {\n lines.push(['Airport direction', String(data.airport_direction)]);\n }\n if (data.meet_and_greet) {\n const mg = data.meet_and_greet;\n const mgPrice = mg.price ? ` (${mg.price.amount} ${mg.price.currency})` : '';\n lines.push(['Meet & greet', `${mg.available ? 'available' : 'unavailable'}${mgPrice}`]);\n }\n\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(lines)}`;\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife quote` — request fare quotes between two points (§4.4.1.3).\n *\n * Read-only (no idempotency key). Builds the `/ride/quote` body from flags\n * (coordinates number-ified, missing required → `PARAM_INVALID`), POSTs with\n * the `X-Api-Key` auth, and renders `QuoteResponse` via `renderWithContext`\n * (json carries the profile/endpoint envelope). The progress line is emitted\n * through `notify` so it goes to stderr and stays silent in json mode.\n */\nexport function registerQuoteCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('quote')\n .description('Request fare quotes for a ride between two points')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--pickup-lat <lat>', 'Pickup latitude')\n .option('--pickup-lng <lng>', 'Pickup longitude')\n .option('--pickup-name <name>', 'Pickup location name')\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\n .option('--dropoff-name <name>', 'Dropoff location name')\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\n .option('--passenger-name <name>', 'Lead passenger full name')\n .option('--passenger-phone <phone>', 'Passenger phone (E.164)')\n .option('--passenger-count <n>', 'Passenger count')\n .option('--luggage-count <n>', 'Luggage count')\n .option('--passenger-email <email>', 'Passenger email')\n .option('--children-count <n>', 'Children count');\n\n attachSchemaHelp(cmd, quoteSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // Build request body. Coordinates are number-ified; pickup_time accepts the\n // literal \"now\" or epoch seconds. Missing required fields throw\n // PARAM_INVALID before any request is sent.\n const body: Record<string, unknown> = {\n pickup: {\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\n },\n dropoff: {\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\n },\n pickup_time:\n opts.pickupTime === 'now'\n ? 'now'\n : num(opts.pickupTime as string | undefined, 'pickup-time'),\n };\n\n // Optional passenger / luggage / children fields — included only when set.\n if (opts.passengerName) body.passenger_name = opts.passengerName as string;\n if (opts.passengerPhone) body.passenger_phone = opts.passengerPhone as string;\n if (opts.passengerCount !== undefined) {\n body.passenger_count = num(opts.passengerCount as string, 'passenger-count');\n }\n if (opts.luggageCount !== undefined) {\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\n }\n if (opts.childrenCount !== undefined) {\n body.children_count = num(opts.childrenCount as string, 'children-count');\n }\n if (opts.passengerEmail !== undefined) {\n body.passenger_email = opts.passengerEmail as string;\n }\n\n // Progress line: stderr in table mode, silent in json mode.\n notify(format, 'loading', 'Fetching quotes...');\n\n const result = await deps.apiClient.post<QuoteResponse>(\n '/ride/quote',\n { type: 'api-key', key: apiKey },\n body,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<QuoteResponse> = {\n data,\n text: () => formatQuote(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport { confirm } from '@inquirer/prompts';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { BookResponse } from '../types/api.js';\nimport { attachSchemaHelp, bookSchema } from '../verb-schema.js';\nimport { resolveIdempotencyKey } from '../idempotency.js';\n\n// ============================================================\n// Input helpers (ride-domain — body assembly stays in app per req 4.4)\n// ============================================================\n\n/**\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\n * (requirement 2.2 / design §4.4.1.3) — a catalog code (exit 1), mirroring the\n * sibling `quote` command's convention.\n */\nfunction need(value: string | undefined, flag: string): string {\n if (value === undefined) {\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\n }\n return value;\n}\n\n/** Number-ify a numeric flag. Non-finite input maps to `PARAM_INVALID`. */\nfunction num(value: string | undefined, flag: string): number {\n const n = Number(need(value, flag));\n if (!Number.isFinite(n)) {\n throw new CliError('PARAM_INVALID', `--${flag} must be a number.`);\n }\n return n;\n}\n\n/**\n * Number-ify a seat count and enforce the 0–5 range (design §4.4.1.3 book\n * schema). Out-of-range values map to `PARAM_INVALID`.\n */\nfunction seatCount(value: string, flag: string): number {\n const n = num(value, flag);\n if (!Number.isInteger(n) || n < 0 || n > 5) {\n throw new CliError('PARAM_INVALID', `--${flag} must be an integer between 0 and 5.`);\n }\n return n;\n}\n\n// ============================================================\n// Output helper (table summary)\n// ============================================================\n\n/**\n * Render a booked ride as a key/value block for `--format table`. Amounts are\n * decimal currency units (NOT cents) — printed verbatim.\n */\nfunction formatBook(data: BookResponse): string {\n const lines: [string, string][] = [\n ['Ride ID', String(data.ride_id ?? '-')],\n ['Order ID', String(data.order_id ?? '-')],\n ['Status', String(data.status ?? '-')],\n ['Scheduled', String(data.is_scheduled ?? false)],\n ['Order type', String(data.order_type ?? '-')],\n ];\n if (data.price) {\n lines.push(['Price', `${data.price.amount} ${data.price.currency}`]);\n if (data.price.quote_id) lines.push(['Quote ID', String(data.price.quote_id)]);\n }\n lines.push(['Payment status', String(data.payment_status ?? '-')]);\n // Mode-dependent: monthly_settlement returns billing_entry_id, pay_per_call\n // echoes back payment_order_id.\n if (data.billing_entry_id) lines.push(['Billing entry', String(data.billing_entry_id)]);\n if (data.payment_order_id) lines.push(['Payment order', String(data.payment_order_id)]);\n\n return Formatter.keyValue(lines);\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife book` — book a ride against a previously returned quote\n * (§4.4.1.3 book schema + §4.4.2.1). Write op (W/Y).\n *\n * Funding is decided server-side by the developer's `billing_mode`:\n * - monthly_settlement: no payment handle; fare is deducted from the\n * settlement account (payment_status=ON_ACCOUNT).\n * - pay_per_call: pass `--payment-order-id` (a PAID order from payment-cli).\n * The CLI MUST NOT accept `--payment-method-id` or card info — the merchant\n * domain never holds a payment credential, so the request body carries at most\n * an optional `payment_order_id` (design Property 5).\n *\n * `POST /ride/book` with `X-Api-Key` auth + the `Idempotency-Key` header (key\n * forwarded verbatim, never in the body). `--yes` skips the confirm; a missing\n * `--idempotency-key` under `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED`\n * before any request is sent. Renders `BookResponse` via `renderWithContext`\n * (json carries the profile/endpoint envelope); the progress line goes to\n * stderr via `notify` and stays silent in json mode.\n */\nexport function registerBookCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('book')\n .description('Book a ride using a quote_id returned by quote')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--quote-id <id>', 'Quote id from `ride-elife quote`')\n .option('--vehicle-class <class>', 'Chosen vehicle class')\n .option('--price-amount <amount>', 'Fare in decimal currency units (not cents)')\n .option('--price-currency <currency>', 'Currency code (default USD)')\n .option('--payment-order-id <id>', 'Paid payment order id (pay_per_call mode only)')\n .option('--passenger-name <name>', 'Passenger full name')\n .option('--passenger-phone <phone>', 'Passenger phone')\n .option('--passenger-email <email>', 'Passenger email')\n .option('--luggage-count <n>', 'Luggage count')\n .option('--special-requests <text>', 'Free-text special requests')\n .option('--pickup-lat <lat>', 'Pickup latitude')\n .option('--pickup-lng <lng>', 'Pickup longitude')\n .option('--pickup-name <name>', 'Pickup location name')\n .option('--dropoff-lat <lat>', 'Dropoff latitude')\n .option('--dropoff-lng <lng>', 'Dropoff longitude')\n .option('--dropoff-name <name>', 'Dropoff location name')\n .option('--pickup-time <time>', 'Pickup time: epoch seconds, or \"now\"')\n .option('--meet-and-greet', 'Enable meet & greet service')\n .option('--meet-and-greet-price <amount>', 'Meet & greet surcharge')\n .option('--welcome-sign <text>', 'Welcome sign text')\n .option('--child-seat-count <n>', 'Number of child seats needed (0-5)')\n .option('--infant-seat-count <n>', 'Number of infant seats needed (0-5)')\n .option('--toddler-seat-count <n>', 'Number of toddler seats needed (0-5)')\n .option('--arrival-flight-no <no>', 'Arrival flight number')\n .option('--arrival-airline <airline>', 'Arrival airline')\n .option('--departure-flight-no <no>', 'Departure flight number')\n .option('--departure-airline <airline>', 'Departure airline')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n attachSchemaHelp(cmd, bookSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n const isYes = Boolean(opts.yes);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // Build request body. Required fields throw PARAM_INVALID before any\n // request is sent (mirrors the sibling `quote` command). The body carries\n // NO payment_method_id / card info — at most an optional payment_order_id\n // (design Property 5); funding is decided server-side by billing_mode.\n const quoteId = need(opts.quoteId as string | undefined, 'quote-id');\n const body: Record<string, unknown> = {\n quote_id: quoteId,\n vehicle_class: need(opts.vehicleClass as string | undefined, 'vehicle-class'),\n price_amount: num(opts.priceAmount as string | undefined, 'price-amount'),\n price_currency: (opts.priceCurrency as string | undefined) ?? 'USD',\n passenger_name: need(opts.passengerName as string | undefined, 'passenger-name'),\n passenger_phone: need(opts.passengerPhone as string | undefined, 'passenger-phone'),\n };\n\n // pay_per_call: optional paid payment order id (the only payment handle the\n // merchant CLI ever forwards). monthly_settlement omits it entirely.\n if (opts.paymentOrderId) body.payment_order_id = opts.paymentOrderId as string;\n if (opts.passengerEmail) body.passenger_email = opts.passengerEmail as string;\n if (opts.luggageCount !== undefined) {\n body.luggage_count = num(opts.luggageCount as string, 'luggage-count');\n }\n if (opts.specialRequests) body.special_requests = opts.specialRequests as string;\n\n // Pickup / dropoff / pickup_time are included only when supplied (they must\n // match the originating quote). Coordinates are number-ified.\n if (opts.pickupLat || opts.pickupLng || opts.pickupName) {\n body.pickup = {\n lat: num(opts.pickupLat as string | undefined, 'pickup-lat'),\n lng: num(opts.pickupLng as string | undefined, 'pickup-lng'),\n name: need(opts.pickupName as string | undefined, 'pickup-name'),\n };\n }\n if (opts.dropoffLat || opts.dropoffLng || opts.dropoffName) {\n body.dropoff = {\n lat: num(opts.dropoffLat as string | undefined, 'dropoff-lat'),\n lng: num(opts.dropoffLng as string | undefined, 'dropoff-lng'),\n name: need(opts.dropoffName as string | undefined, 'dropoff-name'),\n };\n }\n if (opts.pickupTime) {\n body.pickup_time =\n opts.pickupTime === 'now' ? 'now' : num(opts.pickupTime as string, 'pickup-time');\n }\n\n if (opts.meetAndGreet) body.meet_and_greet = true;\n if (opts.meetAndGreetPrice !== undefined) {\n body.meet_and_greet_price = num(opts.meetAndGreetPrice as string, 'meet-and-greet-price');\n }\n if (opts.welcomeSign) body.welcome_sign = opts.welcomeSign as string;\n if (opts.childSeatCount !== undefined) {\n body.child_seat_count = seatCount(opts.childSeatCount as string, 'child-seat-count');\n }\n if (opts.infantSeatCount !== undefined) {\n body.infant_seat_count = seatCount(opts.infantSeatCount as string, 'infant-seat-count');\n }\n if (opts.toddlerSeatCount !== undefined) {\n body.toddler_seat_count = seatCount(opts.toddlerSeatCount as string, 'toddler-seat-count');\n }\n if (opts.arrivalFlightNo || opts.arrivalAirline) {\n body.arrival_flight = {\n flight_no: opts.arrivalFlightNo as string | undefined,\n airline: opts.arrivalAirline as string | undefined,\n };\n }\n if (opts.departureFlightNo || opts.departureAirline) {\n body.departure_flight = {\n flight_no: opts.departureFlightNo as string | undefined,\n airline: opts.departureAirline as string | undefined,\n };\n }\n\n // Confirm before the write unless --yes. The warning/prompt go to stderr;\n // declining maps to CLIENT_ABORTED (exit 5) via the top-level envelope.\n if (!isYes) {\n const confirmed = await confirm({\n message: `Book ride with quote ${quoteId}?`,\n default: true,\n });\n if (!confirmed) {\n throw new CliError('CLIENT_ABORTED', 'Booking cancelled by user.');\n }\n }\n\n // Idempotency key (requirement 5.3): resolved before the request. Under\n // --yes a missing key is a hard error and no request is sent. The key is\n // sent as a header, never in the body.\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\n yes: isYes,\n commandPath: 'ride-elife book',\n });\n\n // Progress line: stderr in table mode, silent in json mode.\n notify(format, 'loading', 'Booking ride...');\n\n const result = await deps.apiClient.post<BookResponse>(\n '/ride/book',\n { type: 'api-key', key: apiKey },\n body,\n { 'Idempotency-Key': idempotencyKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<BookResponse> = {\n data,\n text: () => formatBook(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","/**\n * Idempotency key resolution for write commands (`ride-elife book` / `cancel`)\n * — requirement 5.3 / §6.1, design Property 3.\n *\n * The error type is reused from `@agenzo/cli-core` (`IdempotencyKeyRequiredError`\n * → `PARAM_IDEMPOTENCY_KEY_REQUIRED`) so the merchant CLI does not re-define it.\n * The resolve/normalize logic stays in the app because it is merchant-domain\n * policy (per requirement 4.4): the §6.1 key format `[A-Za-z0-9_-]{1,128}`, the\n * `--yes`-missing hard error vs. interactive prompt branch, and the rule that\n * the key is forwarded verbatim as the `Idempotency-Key` HTTP header and is\n * never placed in the request body.\n *\n * The CLI NEVER auto-generates a key: under `--yes` a missing key is a hard\n * error thrown before any request is sent; otherwise the caller is prompted.\n */\nimport {\n CliError,\n IdempotencyKeyRequiredError,\n PromptEngine,\n} from '@agenzo/cli-core';\n\n/**\n * §6.1 idempotency key format: 1–128 characters drawn from `[A-Za-z0-9_-]`.\n */\nexport const IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;\n\n/** Human-readable rule reused in validation messages and prompt feedback. */\nexport const IDEMPOTENCY_KEY_RULE = 'Use 1-128 characters from [A-Za-z0-9_-].';\n\n/**\n * Validate + normalize a caller-supplied idempotency key. A malformed key maps\n * to `PARAM_INVALID` (catalog code, exit 1) — never silently corrected and\n * never auto-generated.\n */\nexport function normalizeIdempotencyKey(key: string): string {\n const trimmed = key.trim();\n if (!IDEMPOTENCY_KEY_PATTERN.test(trimmed)) {\n throw new CliError(\n 'PARAM_INVALID',\n `Invalid idempotency key: \"${key}\". ${IDEMPOTENCY_KEY_RULE}`,\n );\n }\n return trimmed;\n}\n\n/**\n * Resolve the idempotency key for a write operation (requirement 5.3). The CLI\n * never generates one:\n * - supplied via `--idempotency-key` → validated + normalized;\n * - absent under `--yes` → hard error (`PARAM_IDEMPOTENCY_KEY_REQUIRED`,\n * reused from cli-core) thrown before any request is sent;\n * - absent otherwise → collected interactively, then validated.\n *\n * The returned key is forwarded verbatim as the `Idempotency-Key` header by the\n * caller — it never enters the request body.\n */\nexport async function resolveIdempotencyKey(\n flagValue: string | undefined,\n opts: { yes: boolean; commandPath: string },\n): Promise<string> {\n if (flagValue !== undefined) {\n return normalizeIdempotencyKey(flagValue);\n }\n if (opts.yes) {\n throw new IdempotencyKeyRequiredError(opts.commandPath);\n }\n const entered = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => IDEMPOTENCY_KEY_PATTERN.test(v.trim()) || IDEMPOTENCY_KEY_RULE,\n });\n return normalizeIdempotencyKey(entered);\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { GetOrderResponse } from '../types/api.js';\nimport {\n DEFAULT_WATCH_INTERVAL_SECONDS,\n DEFAULT_WATCH_TIMEOUT_SECONDS,\n resolveSeconds,\n watchRideStatus,\n} from './watch.js';\nimport { attachSchemaHelp, rideGetSchema } from '../verb-schema.js';\n\n// ============================================================\n// Input helpers (ride-domain — stays in app per req 4.4)\n// ============================================================\n\n/**\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\n * (requirement 3.1 / §4.4.1.3) — a catalog code (exit 1), mirroring the\n * sibling quote/book commands' convention.\n */\nfunction need(value: string | undefined, flag: string): string {\n if (value === undefined) {\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\n }\n return value;\n}\n\n// ============================================================\n// Output helper (table summary, non-watch path only)\n// ============================================================\n\n/**\n * Render a single ride order as a key/value block for `--format table`.\n * Pickup/dropoff are `from_location`/`to_location` (v3 snake_case, NOT the\n * elife `from`/`to` aliases). Amounts are decimal currency units (NOT cents).\n */\nfunction formatGetOrder(data: GetOrderResponse): string {\n const lines: [string, string][] = [\n ['Ride ID', String(data.ride_id ?? '-')],\n ['Status', String(data.status ?? '-')],\n ];\n if (data.source) lines.push(['Source', String(data.source)]);\n if (data.is_scheduled !== undefined) lines.push(['Scheduled', String(data.is_scheduled)]);\n if (data.from_location) {\n lines.push(['From', String(data.from_location.name ?? '-')]);\n }\n if (data.to_location) {\n lines.push(['To', String(data.to_location.name ?? '-')]);\n }\n if (data.pickup_time !== undefined) lines.push(['Pickup time', String(data.pickup_time)]);\n if (data.vehicle_class) lines.push(['Vehicle class', String(data.vehicle_class)]);\n if (data.price) {\n lines.push(['Price', `${data.price.amount} ${data.price.currency}`]);\n }\n if (data.final_amount !== undefined && data.final_amount !== null) {\n lines.push(['Final amount', String(data.final_amount)]);\n }\n if (data.final_settlement_status) {\n lines.push(['Settlement', String(data.final_settlement_status)]);\n }\n if (data.driver) {\n const driver = data.driver;\n const phone = driver.phone_number ? ` (${driver.phone_number})` : '';\n lines.push(['Driver', `${driver.name ?? '-'}${phone}`]);\n }\n if (data.vehicle) {\n const v = data.vehicle;\n const desc = [v.color, v.make, v.model].filter(Boolean).join(' ') || '-';\n const plate = v.license_plate ? ` [${v.license_plate}]` : '';\n lines.push(['Vehicle', `${desc}${plate}`]);\n }\n if (data.created_at) lines.push(['Created at', String(data.created_at)]);\n\n return Formatter.keyValue(lines);\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife get` — fetch a ride order status by id (§4.4.1.3 get schema).\n * Read-only (no idempotency key).\n *\n * Two modes:\n * - Non-`--watch`: a single `GET /ride/<id>/status` → `CommandResult` +\n * `renderWithContext` (json carries the profile/endpoint envelope).\n * - `--watch`: hands off to `watch.ts`, which polls until a terminal status\n * or timeout, writing each result as ONE NDJSON line on stdout. The watch\n * stream is NOT wrapped in the profile/endpoint envelope (it is a line\n * stream); on timeout the final line is `{ watch_status:'timeout', ... }`\n * (design Property 2).\n *\n * Named `registerRideGetCommand` to avoid clashing with the `services get`\n * registration.\n */\nexport function registerRideGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('get')\n .description('Retrieve a ride order status by id (repeatable for polling)')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--order-id <id>', 'Ride order id (the ride_id returned by `ride-elife book`)')\n .option('--watch', 'Poll until a terminal status, emitting one NDJSON line per update')\n .option(\n '--watch-interval <seconds>',\n `Seconds between polls when --watch is set (default ${DEFAULT_WATCH_INTERVAL_SECONDS})`,\n )\n .option(\n '--watch-timeout <seconds>',\n `Max seconds to poll before giving up (default ${DEFAULT_WATCH_TIMEOUT_SECONDS})`,\n );\n\n attachSchemaHelp(cmd, rideGetSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n const orderId = need(opts.orderId as string | undefined, 'order-id');\n\n // --watch: NDJSON line stream (no profile/endpoint envelope). The stream\n // itself is the progress, so no spinner/notify is emitted.\n if (opts.watch) {\n await watchRideStatus(deps.apiClient, apiKey, orderId, {\n intervalSeconds: resolveSeconds(\n opts.watchInterval as string | undefined,\n DEFAULT_WATCH_INTERVAL_SECONDS,\n ),\n timeoutSeconds: resolveSeconds(\n opts.watchTimeout as string | undefined,\n DEFAULT_WATCH_TIMEOUT_SECONDS,\n ),\n });\n return;\n }\n\n // Single-shot: progress line on stderr (silent in json mode).\n notify(format, 'loading', 'Fetching ride status...');\n\n const result = await deps.apiClient.get<GetOrderResponse>(\n `/ride/${encodeURIComponent(orderId)}/status`,\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<GetOrderResponse> = {\n data,\n text: () => formatGetOrder(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport { confirm } from '@inquirer/prompts';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { CancelResponse } from '../types/api.js';\nimport { attachSchemaHelp, cancelSchema } from '../verb-schema.js';\nimport { resolveIdempotencyKey } from '../idempotency.js';\n\n// ============================================================\n// Input helpers (ride-domain — stays in app per req 4.4)\n// ============================================================\n\n/**\n * Require a flag value. Missing required input maps to `PARAM_INVALID`\n * (requirement 3.3 / §4.4.1.3 cancel schema) — a catalog code (exit 1),\n * mirroring the sibling quote/book/get commands' convention.\n */\nfunction need(value: string | undefined, flag: string): string {\n if (value === undefined) {\n throw new CliError('PARAM_INVALID', `Missing required --${flag}.`);\n }\n return value;\n}\n\n// ============================================================\n// Output helper (table summary)\n// ============================================================\n\n/**\n * Render a cancelled ride as a key/value block for `--format table`. Amounts\n * are decimal currency units (NOT cents) — printed verbatim. `cancellation`\n * may be null when the backend reports no fee/reversal breakdown.\n */\nfunction formatCancel(data: CancelResponse): string {\n const lines: [string, string][] = [\n ['Ride ID', String(data.ride_id ?? '-')],\n ['Status', String(data.ride_stat ?? '-')],\n ];\n if (data.cancellation) {\n const c = data.cancellation;\n lines.push(['Cancellation fee', `${c.cancellation_fee} ${c.currency}`]);\n lines.push(['Reversal amount', `${c.reversal_amount} ${c.currency}`]);\n }\n if (data.refund_amount !== undefined && data.refund_amount !== null) {\n lines.push(['Refund amount', String(data.refund_amount)]);\n }\n\n return Formatter.keyValue(lines);\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife cancel` — cancel a ride order by id (§4.4.1.3 cancel schema).\n * Write op (W/Y).\n *\n * `POST /ride/<order-id>/cancel` with NO request body, `X-Api-Key` auth, and\n * the `Idempotency-Key` header (key forwarded verbatim, never in the body).\n * Cancelling may incur a fee, so the non-`--yes` path MUST confirm before the\n * write; `--yes` skips the confirmation. A missing `--idempotency-key` under\n * `--yes` throws `PARAM_IDEMPOTENCY_KEY_REQUIRED` before any request is sent;\n * non-`--yes` prompts for it. Declining the confirmation maps to\n * `CLIENT_ABORTED` (exit 5) via the top-level envelope. Renders\n * `CancelResponse` via `renderWithContext` (json carries the profile/endpoint\n * envelope); the progress line goes to stderr via `notify` and stays silent in\n * json mode.\n */\nexport function registerCancelCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('cancel')\n .description('Cancel a ride order by id (may incur a cancellation fee)')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--order-id <id>', 'Ride order id to cancel (the ride_id returned by book)')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n attachSchemaHelp(cmd, cancelSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n const isYes = Boolean(opts.yes);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // Required input throws PARAM_INVALID before any request is sent (mirrors\n // the sibling get/book commands).\n const orderId = need(opts.orderId as string | undefined, 'order-id');\n\n // Confirm before the write unless --yes. Cancelling may incur a fee, so the\n // prompt warns explicitly (requirement 3.3). The warning/prompt go to\n // stderr; declining maps to CLIENT_ABORTED (exit 5) via the top-level\n // envelope.\n if (!isYes) {\n const confirmed = await confirm({\n message: `Cancel ride ${orderId}? This may incur a fee.`,\n default: false,\n });\n if (!confirmed) {\n throw new CliError('CLIENT_ABORTED', 'Cancellation aborted by user.');\n }\n }\n\n // Idempotency key (requirement 5.3): resolved before the request. Under\n // --yes a missing key is a hard error and no request is sent. The key is\n // sent as a header, never in the body.\n const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey as string | undefined, {\n yes: isYes,\n commandPath: 'ride-elife cancel',\n });\n\n // Progress line: stderr in table mode, silent in json mode.\n notify(format, 'loading', 'Cancelling ride...');\n\n // POST /ride/<id>/cancel carries NO body — only the Idempotency-Key header.\n const result = await deps.apiClient.post<CancelResponse>(\n `/ride/${encodeURIComponent(orderId)}/cancel`,\n { type: 'api-key', key: apiKey },\n undefined,\n { 'Idempotency-Key': idempotencyKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<CancelResponse> = {\n data,\n text: () => formatCancel(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { ListOrdersResponse, RideOrderListItem } from '../types/api.js';\nimport { attachSchemaHelp, listOrdersSchema } from '../verb-schema.js';\n\n// ============================================================\n// Input helpers (ride-domain — stays in app per req 4.4)\n// ============================================================\n\nconst DEFAULT_PAGE = '1';\nconst DEFAULT_PAGE_SIZE = '20';\n\n/**\n * Number-ify a pagination flag. Non-finite / non-integer / non-positive input\n * maps to `PARAM_INVALID` (catalog code, exit 1) — mirroring the sibling\n * quote/get/cancel commands' convention. Returns the canonical string form to\n * be passed through as a query parameter.\n */\nfunction positiveInt(value: string, flag: string): string {\n const n = Number(value);\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\n throw new CliError('PARAM_INVALID', `--${flag} must be a positive integer.`);\n }\n return String(n);\n}\n\n// ============================================================\n// Output helper (table summary)\n// ============================================================\n\n/**\n * Render the order list as a table for `--format table`. Each order is one\n * row; amounts are decimal currency units (NOT cents) — printed verbatim.\n */\nfunction formatOrders(data: ListOrdersResponse): string {\n const orders: RideOrderListItem[] = data.orders ?? [];\n if (orders.length === 0) {\n return Formatter.status('info', 'No ride orders found');\n }\n\n const headers = ['Order ID', 'Ride ID', 'Status', 'Vehicle Class', 'Price', 'Currency', 'Payment'];\n const rows = orders.map((o) => [\n String(o.order_id ?? '-'),\n String(o.ride_id ?? '-'),\n String(o.status ?? '-'),\n String(o.vehicle_class ?? '-'),\n String(o.price_amount ?? '-'),\n String(o.price_currency ?? '-'),\n String(o.payment_status ?? '-'),\n ]);\n\n const summary: [string, string][] = [\n ['Total', String(data.total ?? '-')],\n ['Page', String(data.page ?? '-')],\n ['Page size', String(data.page_size ?? '-')],\n ];\n\n return `${Formatter.table(headers, rows)}\\n${Formatter.keyValue(summary)}`;\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `ride-elife list-orders` — list previously placed ride orders (§4.4.1.3\n * list-orders schema). Read-only (no idempotency key).\n *\n * Passes `--page`(default 1) / `--page-size`(default 20) / `--status` /\n * `--order-type` through as query parameters to `GET /ride/orders` with the\n * `X-Api-Key` auth, and renders `ListOrdersResponse` via `renderWithContext`\n * (json carries the profile/endpoint envelope). `page`/`page-size` are\n * validated as positive integers (invalid → `PARAM_INVALID`); `status` /\n * `order-type` are forwarded verbatim only when set. The progress line is\n * emitted through `notify` so it goes to stderr and stays silent in json mode.\n */\nexport function registerListOrdersCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('list-orders')\n .description('List previously placed ride orders')\n .option('--api-key <key>', 'API Key for authentication (X-Api-Key)')\n .option('--page <page>', 'Page number', DEFAULT_PAGE)\n .option('--page-size <size>', 'Page size', DEFAULT_PAGE_SIZE)\n .option('--status <status>', 'Filter by order status')\n .option('--order-type <type>', 'Filter by order type');\n\n attachSchemaHelp(cmd, listOrdersSchema);\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // Build query params. page/page-size are validated as positive integers\n // (invalid → PARAM_INVALID before any request); status/order-type are\n // forwarded verbatim only when set. Sent as a query string, never a body.\n const params: Record<string, string> = {\n page: positiveInt((opts.page as string | undefined) ?? DEFAULT_PAGE, 'page'),\n page_size: positiveInt((opts.pageSize as string | undefined) ?? DEFAULT_PAGE_SIZE, 'page-size'),\n };\n if (opts.status !== undefined) params.status = opts.status as string;\n if (opts.orderType !== undefined) params.order_type = opts.orderType as string;\n\n // Progress line: stderr in table mode, silent in json mode.\n notify(format, 'loading', 'Fetching orders...');\n\n const result = await deps.apiClient.get<ListOrdersResponse>(\n '/ride/orders',\n { type: 'api-key', key: apiKey },\n params,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<ListOrdersResponse> = {\n data,\n text: () => formatOrders(data),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","/**\n * Built-in static capability registry (D4, merchant-domain only).\n *\n * NOTE: this is a CLI-bundled, single-merchant catalog — NOT a live backend\n * discovery feed. It does not reflect which services are enabled for the\n * current API key, nor the developer's billing mode (that is a per-developer\n * property decided by the backend, surfaced via the `book` response /\n * error codes, not advertised here). The §4.4.1 backend `/services` discovery\n * endpoint (BACK-063) + top-level `billing` block + `page` cursor are pending\n * impl; until they land, `services list/get` read this table.\n *\n * Each entry describes a CLI-exposed service: which `cli_noun` group hosts it,\n * the verbs it offers (with one-line descriptions), the recommended call\n * `workflow`, and discovery hints. `services list` renders a summary of these\n * entries and `services get <service-id>` returns one in full.\n *\n * `ServiceCapability` / the registry are merchant-domain specific (only\n * merchant-cli uses them) and stay in the app — they are NOT lifted to\n * `@agenzo/cli-core`.\n */\n\n/** Discovery hints for a capability (§4.4.1 schema; `schema_url` reserved for backend feed). */\nexport interface ServiceDiscovery {\n /** Command an agent can run to discover the verbs in detail. */\n help_command: string;\n /** Reserved for the backend discovery feed's per-verb JSON schema URL (pending impl). */\n schema_url?: string;\n}\n\nexport interface ServiceCapability {\n service_id: string;\n name: string;\n description: string;\n /** Service category (e.g. `ride`); part of the §4.4.1 schema form. */\n category: string;\n version: string;\n /** Upstream capability provider. */\n provider: string;\n /** Top-level CLI noun (command group) that hosts this service's verbs (`<category>-<provider>`). */\n cli_noun: string;\n /** Verb names exposed under `cli_noun`. */\n verbs: string[];\n /** One-line description per verb, keyed by verb name. */\n verb_descriptions: Record<string, string>;\n /** Ordered call sequence; `[cancel]` is optional. */\n workflow: string[];\n /** ISO date the capability became available. */\n since: string;\n discovery: ServiceDiscovery;\n}\n\n/** Static registry. This iteration ships a single `ride-elife` capability. */\nexport const SERVICE_REGISTRY: ServiceCapability[] = [\n {\n service_id: 'ride-elife',\n name: 'Ride hailing (eLife)',\n description: 'On-demand ride ordering: quote a fare, book it, poll status, and cancel.',\n category: 'ride',\n version: '1.0.0',\n provider: 'elife',\n cli_noun: 'ride-elife',\n verbs: ['quote', 'book', 'get', 'cancel', 'list-orders'],\n verb_descriptions: {\n quote: 'Request fare quotes for a ride between two points.',\n book: 'Book a ride using a quote_id returned by quote.',\n get: 'Retrieve a ride order by id (poll for status changes with --watch).',\n cancel: 'Cancel a ride order by id (may incur a fee).',\n 'list-orders': 'List previously placed ride orders.',\n },\n workflow: ['quote', 'book', 'get (poll for status)', 'cancel (optional)'],\n since: '2026-06-01',\n discovery: { help_command: 'agenzo-merchant-cli ride-elife --help' },\n },\n];\n\n/** Look up a capability by its service_id. Returns undefined when not found. */\nexport function findService(serviceId: string): ServiceCapability | undefined {\n return SERVICE_REGISTRY.find((s) => s.service_id === serviceId);\n}\n","import { Command } from 'commander';\nimport { ConfigManager, Formatter, resolveFormat, renderWithContext } from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport { SERVICE_REGISTRY, type ServiceCapability } from './registry.js';\n\n/**\n * Summary view of a registry entry for `services list` (§4.4.1.1): the\n * discovery-relevant subset — service_id/name/category/provider/cli_noun/\n * version/verbs/since/discovery — without the heavier verb_descriptions /\n * workflow detail (those are returned in full by `services get`).\n */\ninterface ServiceListItem {\n service_id: string;\n name: string;\n category: string;\n provider: string;\n cli_noun: string;\n version: string;\n verbs: string[];\n since: string;\n discovery: ServiceCapability['discovery'];\n}\n\nfunction toListItem(s: ServiceCapability): ServiceListItem {\n return {\n service_id: s.service_id,\n name: s.name,\n category: s.category,\n provider: s.provider,\n cli_noun: s.cli_noun,\n version: s.version,\n verbs: s.verbs,\n since: s.since,\n discovery: s.discovery,\n };\n}\n\n/**\n * `services list` — list available merchant capabilities (§4.4.1.1).\n *\n * Read-only, no `--idempotency-key`. Data source is the CLI-bundled registry\n * (D4), not a live backend feed. Output is wrapped by `renderWithContext` so\n * json carries the profile/endpoint envelope; the table form renders a\n * one-line-per-service summary on stdout.\n */\nexport function registerServicesListCommand(parent: Command): void {\n const cmd = parent\n .command('list')\n .description('List available merchant services from the registry');\n\n cmd.action(async () => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const services = SERVICE_REGISTRY.map(toListItem);\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<{ services: ServiceListItem[] }> = {\n data: { services },\n text: () => {\n if (services.length === 0) {\n return Formatter.status('info', 'No services found');\n }\n const headers = ['Service ID', 'Name', 'Category', 'Provider', 'Version', 'Verbs'];\n const rows = services.map((s) => [\n s.service_id,\n s.name,\n s.category,\n s.provider,\n s.version,\n s.verbs.join(', '),\n ]);\n return Formatter.table(headers, rows);\n },\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport {\n ConfigManager,\n Formatter,\n CliError,\n resolveFormat,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport { findService, type ServiceCapability } from './registry.js';\n\n/**\n * Render the full capability as a key/value block for table output.\n */\nfunction formatServiceGet(s: ServiceCapability): string {\n const lines: [string, string][] = [\n ['Service ID', s.service_id],\n ['Name', s.name],\n ['Description', s.description],\n ['Category', s.category],\n ['Version', s.version],\n ['Provider', s.provider],\n ['CLI Noun', s.cli_noun],\n ['Verbs', s.verbs.join(', ')],\n ['Workflow', s.workflow.join(' → ')],\n ['Since', s.since],\n ['Help', s.discovery.help_command],\n ];\n const verbDetail = s.verbs\n .map((v) => ` ${v}: ${s.verb_descriptions[v] ?? ''}`)\n .join('\\n');\n return `${Formatter.keyValue(lines)}\\nVerb descriptions:\\n${verbDetail}`;\n}\n\n/**\n * `services get <service-id>` — return a single capability's full metadata\n * (§4.4.1.2), including verb_descriptions / workflow / discovery.\n *\n * Read-only, reads the CLI-bundled registry (D4). A hit is rendered via\n * `renderWithContext` (json carries the profile/endpoint envelope); a miss\n * throws cli-core's `CliError` with code `SERVICE_NOT_FOUND` (exit 1).\n */\nexport function registerServiceGetCommand(parent: Command): void {\n const cmd = parent\n .command('get <service-id>')\n .description('Retrieve a single merchant service by id');\n\n cmd.action(async (serviceId: string) => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n const service = findService(serviceId);\n if (!service) {\n throw new CliError(\n 'SERVICE_NOT_FOUND',\n `Service '${serviceId}' was not found in the registry. Run \"services list\" to see available services.`,\n );\n }\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<ServiceCapability> = {\n data: service,\n text: () => formatServiceGet(service),\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n"],"mappings":"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","names":["readFile","writeFile","mkdir","chmod","join","homedir","join","homedir","mkdir","chmod","readFile","writeFile","need","num","need","confirm","need","confirm"]}
|