@agenzo/token-cli 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../../packages/cli-core/errors/error-catalog.ts","../../../packages/cli-core/errors/errors.ts","../../../packages/cli-core/version/version.ts","../../../packages/cli-core/api-client/client.ts","../../../packages/cli-core/credential-store/credential-store.ts","../../../packages/cli-core/key-store/key-store.ts","../../../packages/cli-core/config/config-manager.ts","../../../packages/cli-core/exit/exit.ts","../../../packages/cli-core/formatter/formatter.ts","../../../packages/cli-core/formatter/output.ts","../../../packages/cli-core/formatter/render-context.ts","../../../packages/cli-core/prompt-engine/prompt-engine.ts","../src/payment-methods/prompts.ts","../src/verb-schema.ts","../src/payment-methods/add.ts","../src/payment-methods/list.ts","../src/payment-methods/get.ts","../src/payment-methods/disable.ts","../src/payment-tokens/create.ts","../src/payment-tokens/list.ts","../src/payment-tokens/get.ts","../src/payment-tokens/revoke.ts"],"sourcesContent":["import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n Formatter,\n CliError,\n UserCancelError,\n toErrorEnvelope,\n resolveFormat,\n PromptEngine,\n renderWithContext,\n type OutputFormat,\n type CommandResult,\n exitCodeFor,\n getCurrentVersion,\n} from '@agenzo/cli-core';\n\n// payment-methods commands\nimport { registerAddCommand } from './payment-methods/add.js';\nimport { registerListCommand as registerPmListCommand } from './payment-methods/list.js';\nimport { registerGetCommand as registerPmGetCommand } from './payment-methods/get.js';\nimport { registerDisableCommand as registerPmDisableCommand } from './payment-methods/disable.js';\n\n// payment-tokens commands\nimport { registerCreateCommand } from './payment-tokens/create.js';\nimport { registerListCommand as registerPtListCommand } from './payment-tokens/list.js';\nimport { registerGetCommand as registerPtGetCommand } from './payment-tokens/get.js';\nimport { registerRevokeCommand } from './payment-tokens/revoke.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. token-cli authenticates per-command via\n // `--api-key` (X-Api-Key); there is no Bearer session / AuthService / keystore.\n const configManager = new ConfigManager(undefined, '/api/token/v1');\n await configManager.ensureDirectories();\n\n const apiBaseUrl = await configManager.getApiBaseUrl();\n const apiClient = new ApiClient({ baseUrl: apiBaseUrl });\n\n // Shared deps object — API Key is supplied per-command, so commands only\n // 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-token-cli')\n .version(getCurrentVersion())\n .description(\n 'Agenzo token plane: payment methods (card binding + 3DS) and payment tokens (VCN / Network Token / X402)',\n )\n .option('--verbose', 'Show verbose logs')\n .option('--yes', 'Skip confirmation prompts (for automation/AI Agents)')\n .option(\n '--format <format>',\n 'Output format: json | table (default: table; or set AGENZO_FORMAT)',\n );\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 // payment-methods command group\n const pmCmd = program.command('payment-methods').description('Payment method management');\n registerAddCommand(pmCmd, deps);\n registerPmListCommand(pmCmd, deps);\n registerPmGetCommand(pmCmd, deps);\n registerPmDisableCommand(pmCmd, deps);\n\n // payment-tokens command group\n const ptCmd = program.command('payment-tokens').description('Payment token management');\n registerCreateCommand(ptCmd, deps);\n registerPtListCommand(ptCmd, deps);\n registerPtGetCommand(ptCmd, deps);\n registerRevokeCommand(ptCmd, deps);\n\n // services command group — proxy platform discovery endpoint\n const svcCmd = program.command('services').description('Token service discovery');\n svcCmd\n .command('list')\n .description('List available token services from platform catalog')\n .option('--api-key <key>', 'API Key for authentication')\n .action(async () => {\n const opts = svcCmd.parent!.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password', envVar: 'AGENZO_API_KEY',\n });\n // Discovery 端点在 /api/discovery/v1,需要绕过 token-cli 的 /api/token/v1 前缀\n const host = (await configManager.load()).api_host || 'http://localhost:8001'\n const discoveryClient = new ApiClient({ baseUrl: `${host}/api/discovery/v1` })\n const result = await discoveryClient.get<any>(\n '/catalog',\n { type: 'api-key', key: apiKey },\n { category: 'payment' },\n );\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n const cmdResult: CommandResult<any> = { text: () => JSON.stringify(result.data, null, 2),\n data: result.data,\n };\n await renderWithContext(cmdResult, { format }, configManager);\n });\n svcCmd\n .command('get <service_id>')\n .description('Get a token service capability by ID')\n .option('--api-key <key>', 'API Key for authentication')\n .action(async (serviceId: string) => {\n const opts = svcCmd.parent!.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password', envVar: 'AGENZO_API_KEY',\n });\n const host2 = (await configManager.load()).api_host || 'http://localhost:8001'\n const discoveryClient2 = new ApiClient({ baseUrl: `${host2}/api/discovery/v1` })\n const result = await discoveryClient2.get<any>(\n `/catalog/${serviceId}`,\n { type: 'api-key', key: apiKey },\n );\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n const cmdResult: CommandResult<any> = { text: () => JSON.stringify(result.data, null, 2),\n data: result.data,\n };\n await renderWithContext(cmdResult, { format }, configManager);\n });\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); if an error was thrown before parsing, falls back to\n * `resolveFormat(undefined)` (which consults `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: 'VCN creation is not supported yet. Coming soon.',\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 // 透传上游注入的 W3C trace 上下文(orchestrator 经 TRACEPARENT env 传入),\n // 保证 orchestrator → CLI → 后端全链路 trace 不断链。\n const traceparent = process.env.TRACEPARENT;\n if (traceparent) {\n headers['traceparent'] = traceparent;\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 * flag 未提供时优先从该环境变量取值,用于非交互调用方(如 orchestrator\n * 经 AGENZO_API_KEY 注入凭证,避免命令行明文)。命中则直接返回,不进 prompt。\n */\n envVar?: string;\n}\n\nexport class PromptEngine {\n /** Return flagValue if provided, else env fallback, else 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.envVar) {\n const envValue = process.env[config.envVar];\n if (envValue !== undefined && envValue !== '') {\n return envValue;\n }\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 { password } from '@inquirer/prompts';\nimport { PromptEngine } from '@agenzo/cli-core';\n\n// ============================================================\n// Payment-method interactive prompts (token-cli domain)\n// ============================================================\n//\n// These were relocated out of @agenzo/cli-core's PromptEngine: collecting card\n// number / expiry / CVV is token-cli payment-method business, not a generic\n// interactive fallback. cli-core keeps only the general `PromptEngine.resolveInput`.\n\n/** Always collect CVV interactively with masked display. */\nexport async function collectCvv(): Promise<string> {\n return password({\n message: 'CVV:',\n mask: '*',\n });\n}\n\n/** Collect payment method params based on type. */\nexport async function collectPaymentMethodParams(\n type: string,\n flags: Record<string, string | undefined>,\n): Promise<Record<string, string>> {\n const params: Record<string, string> = { type };\n\n const email = await PromptEngine.resolveInput(flags.cardEmail ?? flags.email, {\n message: 'Email (for 3DS verification):',\n });\n params.email = email;\n\n if (type === 'card') {\n params.card_number = await PromptEngine.resolveInput(flags.cardNumber, {\n message: 'Card number:',\n });\n params.expiry_date = await PromptEngine.resolveInput(flags.expiry, {\n message: 'Expiry (MMYY):',\n });\n // CVV: use flag if provided, otherwise collect interactively\n if (flags.cvv) {\n params.cvv = flags.cvv;\n } else {\n params.cvv = await collectCvv();\n }\n }\n\n return params;\n}\n","/**\n * `--help --format json` verb-level schema — token domain.\n *\n * Mirrors the mechanism from merchant-cli/src/verb-schema.ts:\n * `attachSchemaHelp` overrides commander's `helpInformation` to emit\n * a JSON schema when `--format json` is explicitly present in argv.\n */\nimport type { Command } from 'commander';\n\nconst CLI_NAME = 'agenzo-token-cli';\n\n// ============================================================\n// Schema shape (reuse from merchant-cli convention)\n// ============================================================\n\nexport interface FlagSchema {\n type: string;\n required: boolean | 'conditional';\n default?: unknown;\n description: string;\n constraints?: string;\n source?: string;\n from?: string;\n}\n\nexport interface ExampleSchema {\n command: string;\n output_summary: string;\n}\n\nexport interface VerbSchema {\n cli: string;\n noun: string;\n verb: string;\n description: string;\n flags: Record<string, FlagSchema>;\n response: Record<string, unknown>;\n example: ExampleSchema;\n error_recovery?: Record<string, string>;\n}\n\n// ============================================================\n// Emit + attach mechanism\n// ============================================================\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\nexport function emitSchema(schema: VerbSchema): void {\n console.log(JSON.stringify(schema, null, 2));\n}\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// payment-methods verb schemas\n// ============================================================\n\nexport const pmAddSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: 'payment-methods',\n verb: 'add',\n description: 'Add a payment method (card binding + 3DS verification)',\n flags: {\n 'card-number': { type: 'string', required: true, description: 'Card number (PAN)' },\n 'exp-month': { type: 'string', required: true, description: 'Expiration month (MM)' },\n 'exp-year': { type: 'string', required: true, description: 'Expiration year (YY or YYYY)' },\n 'cardholder-name': { type: 'string', required: true, description: 'Name on the card' },\n 'member-id': { type: 'string', required: false, description: 'Member ID to associate the card with' },\n 'api-key': { type: 'string', required: true, description: 'API Key for authentication', source: 'config' },\n },\n response: {\n id: { type: 'string', description: 'Payment method ID' },\n status: { type: 'string', description: 'PENDING / ACTIVE / FAILED' },\n card_brand: { type: 'string', description: 'visa / mastercard / ...' },\n last_four: { type: 'string', description: 'Last 4 digits of card' },\n verification_url: { type: 'string|null', description: '3DS verification URL (when PENDING)' },\n },\n example: {\n command: 'agenzo-token-cli payment-methods add --card-number 4111111111111111 --exp-month 12 --exp-year 2027 --cardholder-name \"Alice Test\"',\n output_summary: 'Returns payment method ID and 3DS verification URL. Complete 3DS to activate.',\n },\n error_recovery: {\n INVALID_CARD: 'Card number failed Luhn check or is not supported. Verify and retry.',\n EVO_ERROR: 'Upstream payment processor error. Retry after a short delay.',\n },\n};\n\nexport const pmListSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: 'payment-methods',\n verb: 'list',\n description: 'List payment methods for the authenticated developer',\n flags: {\n 'member': { type: 'string', required: false, description: 'Filter by member ID' },\n 'api-key': { type: 'string', required: true, description: 'API Key for authentication', source: 'config' },\n },\n response: {\n payment_methods: {\n type: 'array',\n description: 'List of payment methods',\n items: {\n id: { type: 'string', description: 'Payment method ID' },\n status: { type: 'string', description: 'PENDING / ACTIVE / DISABLED' },\n card_brand: { type: 'string', description: 'Card brand' },\n last_four: { type: 'string', description: 'Last 4 digits' },\n created_at: { type: 'string', description: 'Creation time (ISO 8601)' },\n },\n },\n },\n example: {\n command: 'agenzo-token-cli payment-methods list',\n output_summary: 'Returns array of payment methods with status and card info.',\n },\n};\n\nexport const pmGetSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: 'payment-methods',\n verb: 'get',\n description: 'Get a payment method by ID',\n flags: {\n 'pm-id': { type: 'string', required: true, description: 'Payment method ID' },\n 'api-key': { type: 'string', required: true, description: 'API Key for authentication', source: 'config' },\n },\n response: {\n id: { type: 'string', description: 'Payment method ID' },\n status: { type: 'string', description: 'PENDING / ACTIVE / DISABLED / FAILED / EXPIRED' },\n card_brand: { type: 'string', description: 'Card brand' },\n last_four: { type: 'string', description: 'Last 4 digits' },\n member_id: { type: 'string|null', description: 'Associated member ID' },\n created_at: { type: 'string', description: 'Creation time' },\n },\n example: {\n command: 'agenzo-token-cli payment-methods get pm_01HZXD...',\n output_summary: 'Returns full payment method details including 3DS verification status.',\n },\n};\n\nexport const pmDisableSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: 'payment-methods',\n verb: 'disable',\n description: 'Disable a payment method (cascades revoke on active payment tokens)',\n flags: {\n 'pm-id': { type: 'string', required: true, description: 'Payment method ID to disable' },\n 'api-key': { type: 'string', required: true, description: 'API Key for authentication', source: 'config' },\n },\n response: {\n id: { type: 'string', description: 'Disabled payment method ID' },\n status: { type: 'string', description: 'DISABLED' },\n revoked_tokens_count: { type: 'int', description: 'Number of payment tokens revoked by cascade' },\n },\n example: {\n command: 'agenzo-token-cli payment-methods disable pm_01HZXD...',\n output_summary: 'Disables the payment method and revokes any active tokens bound to it.',\n },\n};\n\n// ============================================================\n// payment-tokens verb schemas\n// ============================================================\n\nexport const ptCreateSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: 'payment-tokens',\n verb: 'create',\n description: 'Create a payment token (VCN, Network Token cryptogram, or x402 USDC signature)',\n flags: {\n 'type': { type: 'string', required: true, description: 'Token type: vcn / network_token / x402', constraints: 'vcn | network_token | x402' },\n 'payment-method-id': { type: 'string', required: true, description: 'Source payment method ID (must be ACTIVE)' },\n 'amount': { type: 'string', required: 'conditional', description: 'Amount in minor units (required for vcn and x402)' },\n 'currency': { type: 'string', required: false, default: 'USD', description: 'ISO 4217 currency code' },\n 'member-id': { type: 'string', required: false, description: 'Member ID' },\n 'external-transaction-id': { type: 'string', required: false, description: 'External reference for reconciliation' },\n 'pay-to': { type: 'string', required: 'conditional', description: 'Recipient address (required for x402)' },\n 'nonce': { type: 'string', required: 'conditional', description: 'Nonce bytes32 hex (required for x402)' },\n 'network': { type: 'string', required: 'conditional', description: 'Chain network (required for x402, e.g. base-sepolia)' },\n 'deadline': { type: 'int', required: 'conditional', description: 'Epoch seconds deadline (required for x402)' },\n 'api-key': { type: 'string', required: true, description: 'API Key for authentication', source: 'config' },\n },\n response: {\n id: { type: 'string', description: 'Payment token ID' },\n type: { type: 'string', description: 'vcn / network_token / x402' },\n status: { type: 'string', description: 'ACTIVE / REVOKED / EXPIRED' },\n token_data: { type: 'object', description: 'Type-specific token payload (cryptogram / VCN number / x402 signature)' },\n expires_at: { type: 'string|null', description: 'Expiration time (ISO 8601)' },\n },\n example: {\n command: 'agenzo-token-cli payment-tokens create --type network_token --payment-method-id pm_01HZXD...',\n output_summary: 'Returns token ID and cryptogram/VCN/signature data for payment execution.',\n },\n error_recovery: {\n INVALID_PAYMENT_METHOD: 'Payment method is not ACTIVE or not found. Verify status with payment-methods get.',\n UNSUPPORTED_TOKEN_TYPE: 'Use vcn, network_token, or x402.',\n },\n};\n\nexport const ptListSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: 'payment-tokens',\n verb: 'list',\n description: 'List payment tokens for the authenticated developer',\n flags: {\n 'type': { type: 'string', required: false, description: 'Filter by token type (vcn / network_token / x402)' },\n 'member-id': { type: 'string', required: false, description: 'Filter by member ID' },\n 'payment-method-id': { type: 'string', required: false, description: 'Filter by source payment method' },\n 'api-key': { type: 'string', required: true, description: 'API Key for authentication', source: 'config' },\n },\n response: {\n payment_tokens: {\n type: 'array',\n description: 'List of payment tokens',\n items: {\n id: { type: 'string', description: 'Token ID' },\n type: { type: 'string', description: 'Token type' },\n status: { type: 'string', description: 'ACTIVE / REVOKED / EXPIRED' },\n payment_method_id: { type: 'string', description: 'Source payment method' },\n created_at: { type: 'string', description: 'Creation time' },\n },\n },\n },\n example: {\n command: 'agenzo-token-cli payment-tokens list --type network_token',\n output_summary: 'Returns array of payment tokens filtered by type.',\n },\n};\n\nexport const ptGetSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: 'payment-tokens',\n verb: 'get',\n description: 'Get a payment token by ID',\n flags: {\n 'payment-token-id': { type: 'string', required: true, description: 'Payment token ID' },\n 'api-key': { type: 'string', required: true, description: 'API Key for authentication', source: 'config' },\n },\n response: {\n id: { type: 'string', description: 'Token ID' },\n type: { type: 'string', description: 'Token type' },\n status: { type: 'string', description: 'ACTIVE / REVOKED / EXPIRED' },\n token_data: { type: 'object', description: 'Type-specific payload' },\n payment_method_id: { type: 'string', description: 'Source payment method' },\n created_at: { type: 'string', description: 'Creation time' },\n expires_at: { type: 'string|null', description: 'Expiration time' },\n },\n example: {\n command: 'agenzo-token-cli payment-tokens get pt_01HZXD...',\n output_summary: 'Returns full token details including token_data payload.',\n },\n};\n\nexport const ptRevokeSchema: VerbSchema = {\n cli: CLI_NAME,\n noun: 'payment-tokens',\n verb: 'revoke',\n description: 'Revoke an active payment token',\n flags: {\n 'payment-token-id': { type: 'string', required: true, description: 'Payment token ID to revoke' },\n 'api-key': { type: 'string', required: true, description: 'API Key for authentication', source: 'config' },\n },\n response: {\n id: { type: 'string', description: 'Revoked token ID' },\n status: { type: 'string', description: 'REVOKED' },\n },\n example: {\n command: 'agenzo-token-cli payment-tokens revoke pt_01HZXD...',\n output_summary: 'Marks the token as REVOKED. Cannot be undone.',\n },\n};\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n IdempotencyKeyRequiredError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult, OutputFormat } from '@agenzo/cli-core';\nimport type { PaymentMethod } from '../types/api.js';\nimport { collectPaymentMethodParams } from './prompts.js';\nimport { attachSchemaHelp, pmAddSchema } from '../verb-schema.js';\n\n// ============================================================\n// Constants\n// ============================================================\n\n/** Polling interval for 3DS verification status (milliseconds). */\nconst POLL_INTERVAL_MS = 3000;\n\n/** Maximum polling duration for 3DS verification (15 minutes in ms). */\nconst POLL_TIMEOUT_MS = 15 * 60 * 1000;\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `payment-methods add` — bind a card and run 3DS verification (§3.4.0.1).\n *\n * Flags: --api-key, --type (default card), --email, --card-number, --expiry (MMYY), --cvv.\n * Missing values collected via PromptEngine.collectPaymentMethodParams.\n *\n * POST /payment-methods/create (X-Api-Key + Idempotency-Key).\n * If status==='PENDING', polls GET /payment-methods/verification/status until\n * ACTIVE (success), FAILED, or 15-minute timeout.\n *\n * Output (§3.4.0.1):\n * ✓ Payment method created + keyValue + ℹ Complete 3DS verification...\n * ✓ Payment method activated + details (on 3DS success)\n * ✗ 3DS verification failed (on 3DS failure)\n * Timeout hint message (on 15-min timeout)\n */\nexport function registerAddCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('add')\n .description('Add a payment method (card binding + 3DS)')\n .option('--api-key <key>', 'API Key for authentication')\n .option('--type <type>', 'Payment method type (default: card)', 'card')\n .option('--email <email>', 'Email for 3DS verification')\n .option('--card-number <number>', 'Card number')\n .option('--expiry <mmyy>', 'Expiry date (MMYY format)')\n .option('--cvv <cvv>', 'Card CVV')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n attachSchemaHelp(cmd, pmAddSchema);\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 // --- Resolve API key ---\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password', envVar: 'AGENZO_API_KEY',\n });\n\n // --- Resolve payment method type ---\n const type = (opts.type as string) || 'card';\n\n // --- Collect card params via PromptEngine ---\n const flags: Record<string, string | undefined> = {\n email: opts.email as string | undefined,\n cardNumber: opts.cardNumber as string | undefined,\n expiry: opts.expiry as string | undefined,\n cvv: opts.cvv as string | undefined,\n };\n const params = await collectPaymentMethodParams(type, flags);\n\n // --- Idempotency key (required for write, Requirement 6.3) ---\n let idempotencyKey = opts.idempotencyKey as string | undefined;\n if (!idempotencyKey) {\n if (isYes) {\n throw new IdempotencyKeyRequiredError('payment-methods add');\n }\n idempotencyKey = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => v.trim().length > 0 || 'Idempotency key is required',\n });\n }\n\n const extraHeaders: Record<string, string> = {\n 'Idempotency-Key': idempotencyKey,\n };\n\n // --- POST /payment-methods/create ---\n const result = await deps.apiClient.post<PaymentMethod>(\n '/payment-methods/create',\n { type: 'api-key', key: apiKey },\n params,\n extraHeaders,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const pm = result.data;\n\n // --- Output: created state ---\n notify(format, 'success', 'Payment method created');\n\n const createdResult: CommandResult<PaymentMethod> = {\n data: pm,\n text: () => {\n const lines: [string, string][] = [\n ['ID', pm.id],\n ['Type', pm.type],\n ['Status', pm.status],\n ];\n if (pm.brand) lines.push(['Brand', pm.brand]);\n if (pm.first6) lines.push(['First 6', pm.first6]);\n if (pm.last4) lines.push(['Last 4', pm.last4]);\n return Formatter.keyValue(lines);\n },\n };\n\n const configManager = new ConfigManager();\n await renderWithContext(createdResult, { format }, configManager);\n\n // Hint about 3DS (after keyValue output)\n notify(format, 'info', 'Complete 3DS verification via email to activate');\n\n // --- 3DS polling (only for type=card and PENDING status) ---\n if (type === 'card' && pm.status === 'PENDING') {\n const finalStatus = await poll3dsVerification(\n deps.apiClient,\n apiKey,\n pm.id,\n format,\n );\n\n if (finalStatus === 'ACTIVE') {\n // Fetch the updated payment method for full details\n const getResult = await deps.apiClient.get<PaymentMethod>(\n `/payment-methods/${pm.id}`,\n { type: 'api-key', key: apiKey },\n );\n\n if (getResult.success) {\n const activatedPm = getResult.data;\n notify(format, 'success', 'Payment method activated');\n\n const activatedResult: CommandResult<PaymentMethod> = {\n data: activatedPm,\n text: () => {\n const lines: [string, string][] = [\n ['ID', activatedPm.id],\n ['Type', activatedPm.type],\n ['Status', activatedPm.status],\n ];\n if (activatedPm.brand) lines.push(['Brand', activatedPm.brand]);\n if (activatedPm.first6) lines.push(['First 6', activatedPm.first6]);\n if (activatedPm.last4) lines.push(['Last 4', activatedPm.last4]);\n return Formatter.keyValue(lines);\n },\n };\n\n await renderWithContext(activatedResult, { format }, configManager);\n } else {\n // 3DS already reported ACTIVE, but the follow-up detail GET failed.\n // Emit a degraded terminal state from what we already know (the\n // create response + known-ACTIVE status) rather than exiting silently.\n notify(format, 'success', 'Payment method activated');\n\n const degraded: PaymentMethod = { ...pm, status: 'ACTIVE' };\n const degradedResult: CommandResult<PaymentMethod> = {\n data: degraded,\n text: () => {\n const lines: [string, string][] = [\n ['ID', degraded.id],\n ['Type', degraded.type],\n ['Status', degraded.status],\n ];\n if (degraded.brand) lines.push(['Brand', degraded.brand]);\n if (degraded.first6) lines.push(['First 6', degraded.first6]);\n if (degraded.last4) lines.push(['Last 4', degraded.last4]);\n return Formatter.keyValue(lines);\n },\n };\n\n await renderWithContext(degradedResult, { format }, configManager);\n }\n } else if (finalStatus === 'FAILED') {\n notify(format, 'error', '3DS verification failed');\n } else if (finalStatus === 'TIMEOUT') {\n notify(\n format,\n 'info',\n `Verification timed out (15 min). Check status with: agenzo-token-cli payment-methods get ${pm.id} --api-key <your_key>`,\n );\n }\n }\n });\n}\n\n// ============================================================\n// 3DS Polling Helper\n// ============================================================\n\n/**\n * Poll GET /payment-methods/verification/status?payment_method_id=<id> every\n * 3000ms until ACTIVE, FAILED, or 15-minute timeout.\n *\n * Returns the terminal status: 'ACTIVE' | 'FAILED' | 'TIMEOUT'.\n */\nasync function poll3dsVerification(\n apiClient: ApiClient,\n apiKey: string,\n paymentMethodId: string,\n format: OutputFormat,\n): Promise<'ACTIVE' | 'FAILED' | 'TIMEOUT'> {\n const startTime = Date.now();\n\n notify(format, 'info', 'Waiting for 3DS verification...');\n\n while (Date.now() - startTime < POLL_TIMEOUT_MS) {\n await sleep(POLL_INTERVAL_MS);\n\n const result = await apiClient.get<{ status: string }>(\n '/payment-methods/verification/status',\n { type: 'api-key', key: apiKey },\n { payment_method_id: paymentMethodId },\n );\n\n if (result.success) {\n const status = result.data.status;\n if (status === 'ACTIVE') {\n return 'ACTIVE';\n }\n if (status === 'FAILED') {\n return 'FAILED';\n }\n // Still PENDING — continue polling\n }\n // On API error during polling, continue trying (transient failures)\n }\n\n return 'TIMEOUT';\n}\n\n/** Simple async sleep utility. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { PaymentMethod } from '../types/api.js';\nimport { attachSchemaHelp, pmListSchema } from '../verb-schema.js';\n\n/**\n * `payment-methods list` — list payment methods (§3.4.0.2).\n *\n * GET /payment-methods with X-Api-Key header.\n * Optional --member flag maps to ?member_id= query param.\n * Table headers: ID / Type / Brand / First 6 / Last 4 / Status.\n * Empty list → info message (no table). Missing brand/first6/last4 → `-`.\n */\nexport function registerListCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('list')\n .description('List payment methods')\n .option('--api-key <key>', 'API Key for authentication')\n .option('--member <member_id>', 'Filter by member ID');\n\n attachSchemaHelp(cmd, pmListSchema);\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', envVar: 'AGENZO_API_KEY',\n });\n\n // Build query params\n const params: Record<string, string> = {};\n if (opts.member) {\n params.member_id = opts.member as string;\n }\n\n const result = await deps.apiClient.get<PaymentMethod[]>(\n '/payment-methods',\n { type: 'api-key', key: apiKey },\n Object.keys(params).length > 0 ? params : undefined,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const methods = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<{ payment_methods: PaymentMethod[] }> = {\n data: { payment_methods: methods },\n text: () => {\n if (methods.length === 0) {\n return Formatter.status('info', 'No payment methods found');\n }\n const headers = ['ID', 'Type', 'Brand', 'First 6', 'Last 4', 'Status'];\n const rows = methods.map((m) => [\n m.id,\n m.type,\n m.brand || '-',\n m.first6 || '-',\n m.last4 || '-',\n m.status,\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 ApiClient,\n ConfigManager,\n Formatter,\n PromptEngine,\n resolveFormat,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { PaymentMethod } from '../types/api.js';\nimport { attachSchemaHelp, pmGetSchema } from '../verb-schema.js';\n\n/**\n * `payment-methods get <pm_id>` — show a single payment method (§3.4.0.3).\n *\n * Reads: GET /payment-methods/<pm_id> (X-Api-Key).\n * Output: keyValue. Brand / First 6 / Last 4 appear only when their\n * corresponding fields are non-empty/non-null (conditional inclusion).\n */\nexport function registerGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('get <pm_id>')\n .description('Get a payment method by ID')\n .option('--api-key <key>', 'API key for authentication');\n\n attachSchemaHelp(cmd, pmGetSchema);\n cmd.action(async (pmId: string) => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n // Resolve API key — prompt interactively if not provided via flag\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password', envVar: 'AGENZO_API_KEY',\n });\n\n // GET /payment-methods/<pm_id>\n const result = await deps.apiClient.get<PaymentMethod>(\n `/payment-methods/${pmId}`,\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const pm = result.data;\n\n // Build keyValue entries — Brand/First 6/Last 4 only when non-empty\n const entries: [string, string][] = [\n ['ID', pm.id],\n ['Type', pm.type],\n ];\n\n if (pm.brand) {\n entries.push(['Brand', pm.brand]);\n }\n if (pm.first6) {\n entries.push(['First 6', pm.first6]);\n }\n if (pm.last4) {\n entries.push(['Last 4', pm.last4]);\n }\n\n entries.push(['Status', pm.status]);\n entries.push(['Created', Formatter.formatTime(pm.created_at)]);\n\n const configManager = new ConfigManager();\n const cmdResult: CommandResult<PaymentMethod> = {\n data: pm,\n text: () => Formatter.keyValue(entries),\n };\n\n await renderWithContext(cmdResult, { format }, configManager);\n });\n}\n","import { renderWithContext } from '@agenzo/cli-core';\nimport { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n IdempotencyKeyRequiredError,\n} from '@agenzo/cli-core';\nimport type { CommandResult, DisableResult } from '@agenzo/cli-core';\nimport { attachSchemaHelp, pmDisableSchema } from '../verb-schema.js';\n\n/**\n * `payment-methods disable <pm_id>` — disable a payment method (§3.4.0.4).\n *\n * POST /payment-methods/<pm_id>/disable (no body).\n * Output: `✓ Payment method <id> disabled` + Status + Revoked tokens.\n * Idempotency: --idempotency-key required in --yes mode (Requirement 6.3).\n */\nexport function registerDisableCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('disable <pm_id>')\n .description('Disable a payment method')\n .option('--api-key <key>', 'API key for authentication')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n attachSchemaHelp(cmd, pmDisableSchema);\n cmd.action(async (pmId: string) => {\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', envVar: 'AGENZO_API_KEY',\n });\n\n // Idempotency key handling (Requirement 6.3):\n // In --yes mode, --idempotency-key is mandatory — never auto-generate, never send request.\n // In interactive mode, prompt if not provided.\n let idempotencyKey = opts.idempotencyKey as string | undefined;\n if (!idempotencyKey) {\n if (opts.yes) {\n throw new IdempotencyKeyRequiredError('payment-methods disable');\n }\n idempotencyKey = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => v.trim().length > 0 || 'Idempotency key is required',\n });\n }\n\n const extraHeaders: Record<string, string> = {\n 'Idempotency-Key': idempotencyKey,\n };\n\n const result = await deps.apiClient.post<DisableResult>(\n `/payment-methods/${pmId}/disable`,\n { type: 'api-key', key: apiKey },\n undefined,\n extraHeaders,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n // Status line → stderr (json mode stays silent per §5)\n notify(format, 'success', `Payment method ${pmId} disabled`);\n\n const cmdResult: CommandResult<DisableResult> = {\n data,\n text: () =>\n Formatter.keyValue([\n ['Status', data.status],\n ['Revoked tokens', String(data.revoked_tokens_count ?? 0)],\n ]),\n };\n\n const configManager = new ConfigManager();\n await renderWithContext(cmdResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport { confirm, select } from '@inquirer/prompts';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n IdempotencyKeyRequiredError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult, OutputFormat } from '@agenzo/cli-core';\nimport type { PaymentMethod } from '../types/api.js';\nimport { attachSchemaHelp, ptCreateSchema } from '../verb-schema.js';\n\n// ============================================================\n// Constants\n// ============================================================\n\n/** Default network-token fee in cents when /config/network-token-fee is unreachable. */\nconst DEFAULT_NT_FEE_CENTS = 500;\n\n/** Smallest USDC unit (1 USDC = 1_000_000 micro-units). */\nconst USDC_UNIT = 1_000_000;\n\n// ============================================================\n// Helpers (token-domain-specific — stays in app per requirement 5.5)\n// ============================================================\n\n/**\n * Map CLI `--type` flag value to the server-side `type` field.\n * `network-token` → `network_token`; unknown values pass through unchanged.\n */\nexport function mapTokenType(cliType: string): string {\n if (cliType === 'network-token') return 'network_token';\n return cliType;\n}\n\n/**\n * Convert a USD amount string (e.g. \"12.50\") to integer cents using\n * string-based parsing to avoid floating-point drift.\n *\n * Accepts formats: \"12\", \"12.5\", \"12.50\", \".50\", \"0.01\".\n * Throws PARAM_INVALID on non-numeric / out-of-range.\n */\nexport function usdToCents(amountStr: string): number {\n const trimmed = amountStr.trim();\n\n // Validate format: optional digits, optional decimal point with up to 2 fractional digits\n if (!/^\\d*\\.?\\d{0,2}$/.test(trimmed) || trimmed === '' || trimmed === '.') {\n throw new CliError('PARAM_INVALID', `Invalid amount format: \"${amountStr}\". Expected a decimal like \"12.50\".`);\n }\n\n const parts = trimmed.split('.');\n const integerPart = parts[0] || '0';\n let fractionalPart = parts[1] || '0';\n\n // Pad fractional to exactly 2 digits\n fractionalPart = fractionalPart.padEnd(2, '0');\n\n const integerCents = parseInt(integerPart, 10) * 100;\n const fractionalCents = parseInt(fractionalPart, 10);\n return integerCents + fractionalCents;\n}\n\n/**\n * Resolve the payment method to use, following 4-level priority:\n * 1. --payment-method-id (explicit)\n * 2. --card (match last4 against ACTIVE cards)\n * 3. Single ACTIVE card → auto-select\n * 4. Multiple ACTIVE cards → interactive select\n *\n * Throws CLIENT_NO_PAYMENT_METHOD when no ACTIVE cards exist.\n * Throws CLIENT_CARD_NOT_MATCHED when --card doesn't match any ACTIVE card.\n */\nexport async function resolvePaymentMethod(\n apiClient: ApiClient,\n apiKey: string,\n opts: {\n paymentMethodId?: string;\n card?: string;\n yes?: boolean;\n },\n): Promise<string> {\n // Priority 1: explicit --payment-method-id\n if (opts.paymentMethodId) {\n return opts.paymentMethodId;\n }\n\n // Need to fetch ACTIVE cards for priorities 2–4\n const result = await apiClient.get<PaymentMethod[]>(\n '/payment-methods',\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const activeCards = result.data.filter((m) => m.status === 'ACTIVE');\n\n if (activeCards.length === 0) {\n throw new CliError(\n 'CLIENT_NO_PAYMENT_METHOD',\n 'No active payment methods found. Add one with: agenzo-token-cli payment-methods add --api-key <your_key>',\n );\n }\n\n // Priority 2: --card (match last4)\n if (opts.card) {\n const matched = activeCards.find((m) => m.last4 === opts.card);\n if (!matched) {\n throw new CliError(\n 'CLIENT_CARD_NOT_MATCHED',\n `No active card ending in ${opts.card}. Available: ${activeCards.map((m) => m.last4 || '????').join(', ')}`,\n );\n }\n return matched.id;\n }\n\n // Priority 3: single card → auto-select\n if (activeCards.length === 1) {\n return activeCards[0].id;\n }\n\n // Priority 4: multiple cards → interactive select\n if (opts.yes) {\n // In --yes mode we cannot prompt; if there's ambiguity, we cannot proceed\n throw new CliError(\n 'PARAM_INVALID',\n 'Multiple active payment methods found. Specify --payment-method-id or --card to disambiguate.',\n );\n }\n\n const selected = await select({\n message: 'Select a payment method:',\n choices: activeCards.map((m) => ({\n name: `${m.id} (${m.brand || m.type} ****${m.last4 || '????'})`,\n value: m.id,\n })),\n });\n\n return selected;\n}\n\n/**\n * Format a payment token for human-readable output (§3.4.1 create output).\n * Renders differently per type: VCN / Network Token / X402.\n *\n * NOTE: The server response wraps type-specific data under `data.vcn`,\n * `data.network_token`, or `data.x402` (nested). This formatter reads\n * from that nested structure directly.\n */\nexport function formatPaymentToken(data: Record<string, unknown>): string {\n const type = data.type as string;\n const lines: [string, string][] = [];\n\n if (type === 'vcn') {\n const vcn = data.vcn as Record<string, unknown> | undefined ?? data;\n lines.push(['Payment Token ID', String(data.id || vcn.id || '')]);\n lines.push(['Type', 'VCN']);\n lines.push(['Card Number', String(vcn.card_number || '')]);\n lines.push(['Expiry', String(vcn.expiry || '')]);\n lines.push(['CVC', String(vcn.cvc || '')]);\n lines.push(['Limit', `$${formatCentsToUsd(vcn.amount_limit as number)}`]);\n lines.push(['Currency', String(vcn.currency || 'USD')]);\n lines.push(['Status', String(vcn.status || data.status || '')]);\n } else if (type === 'network_token') {\n const nt = data.network_token as Record<string, unknown> | undefined ?? data;\n lines.push(['Payment Token ID', String(data.id || nt.id || '')]);\n lines.push(['Type', 'Network Token']);\n lines.push(['Brand', String(nt.payment_brand || nt.brand || '')]);\n lines.push(['ECI', String(nt.eci || '')]);\n lines.push(['Cryptogram', String(nt.token_cryptogram || nt.cryptogram || '')]);\n lines.push(['Expiry', String(nt.expiry_date || nt.expiry || '')]);\n lines.push(['Value', String(nt.value || '')]);\n } else if (type === 'x402') {\n const x402 = data.x402 as Record<string, unknown> | undefined ?? data;\n lines.push(['Payment Token ID', String(data.id || x402.id || '')]);\n lines.push(['Type', 'X402']);\n lines.push(['Signature Value', String(x402.signature_value || '')]);\n lines.push(['Status', String(x402.status || data.status || '')]);\n } else {\n // Unknown type: best-effort\n lines.push(['Payment Token ID', String(data.id || '')]);\n lines.push(['Type', String(type || 'unknown')]);\n lines.push(['Status', String(data.status || '')]);\n }\n\n return Formatter.keyValue(lines);\n}\n\n/** Format cents back to USD string (e.g. 1250 → \"12.50\"). */\nfunction formatCentsToUsd(cents: number | undefined): string {\n if (cents === undefined || cents === null) return '0.00';\n const dollars = Math.floor(cents / 100);\n const remainder = cents % 100;\n return `${dollars}.${String(remainder).padStart(2, '0')}`;\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `payment-tokens create` — generate a VCN / Network Token / X402 credential\n * (§3.4.1).\n */\nexport function registerCreateCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('create')\n .description('Create a payment token (VCN / Network Token / X402)')\n .option('--api-key <key>', 'API Key for authentication')\n .option('--type <type>', 'Token type: vcn | network-token | x402')\n .option('--payment-method-id <id>', 'Payment method ID to use')\n .option('--card <last4>', 'Match payment method by last 4 digits')\n .option('--member <member_id>', 'Member ID')\n .option('--amount <amount>', 'Amount in USD (VCN / X402)')\n .option('--currency <currency>', 'Currency (default: USD)')\n .option('--pay-to <address>', 'Pay-to address (X402)')\n .option('--nonce <nonce>', 'Nonce (X402)')\n .option('--network <network>', 'Network (X402)')\n .option('--deadline <deadline>', 'Deadline (X402)')\n .option('--external-tx-id <id>', 'External transaction ID')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n attachSchemaHelp(cmd, ptCreateSchema);\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 // --- Resolve API key ---\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password', envVar: 'AGENZO_API_KEY',\n });\n\n // --- Resolve token type ---\n const cliType = await PromptEngine.resolveInput(opts.type as string | undefined, {\n message: 'Token type:',\n type: 'select',\n choices: [\n { name: 'VCN (Virtual Card Number)', value: 'vcn' },\n { name: 'Network Token', value: 'network-token' },\n { name: 'X402 (USDC on-chain)', value: 'x402' },\n ],\n });\n const serverType = mapTokenType(cliType);\n\n // --- Resolve payment method (4-level priority) ---\n const paymentMethodId = await resolvePaymentMethod(deps.apiClient, apiKey, {\n paymentMethodId: opts.paymentMethodId as string | undefined,\n card: opts.card as string | undefined,\n yes: isYes,\n });\n\n // --- Resolve member ---\n let member: string | undefined = opts.member as string | undefined;\n if (!member && !isYes) {\n // In interactive mode, prompt for member (optional — allow empty)\n const memberInput = await PromptEngine.resolveInput(undefined, {\n message: 'Member ID (optional, press Enter to skip):',\n validate: () => true, // always valid (optional)\n });\n if (memberInput.trim()) {\n member = memberInput.trim();\n }\n }\n // In --yes mode, if --member not provided, omit it (don't prompt).\n\n // --- Type-specific branch logic ---\n let freezeAmountCents: number | undefined;\n let feeCents: number | undefined;\n let feeDisplay: string | undefined;\n let freezeDisplay: string | undefined;\n // Body fields that vary by type\n const typeBody: Record<string, unknown> = {};\n\n if (serverType === 'vcn') {\n // VCN branch: feature gate + amount + fee\n await checkVcnFeatureEnabled(deps.apiClient, apiKey);\n\n const amountStr = await PromptEngine.resolveInput(opts.amount as string | undefined, {\n message: 'Amount (USD, e.g. 25.00):',\n validate: (v) => {\n try {\n const cents = usdToCents(v);\n if (cents < 1 || cents > 50000) {\n return 'Amount must be between $0.01 and $500.00';\n }\n return true;\n } catch {\n return 'Invalid amount format. Use a decimal like \"25.00\"';\n }\n },\n });\n\n const cents = usdToCents(amountStr);\n if (cents < 1 || cents > 50000) {\n throw new CliError(\n 'PARAM_INVALID',\n 'Amount must be between $0.01 and $500.00',\n );\n }\n\n feeCents = Math.max(1, Math.round(cents * 0.05));\n freezeAmountCents = cents + feeCents;\n feeDisplay = `$${formatCentsToUsd(feeCents)}`;\n freezeDisplay = `$${formatCentsToUsd(freezeAmountCents)}`;\n\n typeBody.amount = cents;\n // §3.4.1: --currency omitted → do NOT send; server applies its default.\n if (opts.currency) {\n typeBody.currency = opts.currency as string;\n }\n } else if (serverType === 'network_token') {\n // Network-token branch: fetch fee config (fallback to default)\n feeCents = await fetchNetworkTokenFee(deps.apiClient, apiKey);\n freezeAmountCents = feeCents;\n feeDisplay = `$${formatCentsToUsd(feeCents)}`;\n freezeDisplay = feeDisplay;\n } else if (serverType === 'x402') {\n // X402 branch: USDC amount + fee\n const amountStr = await PromptEngine.resolveInput(opts.amount as string | undefined, {\n message: 'Amount (USDC):',\n validate: (v) => {\n const n = parseFloat(v);\n if (isNaN(n) || n <= 0) return 'Amount must be a positive number';\n return true;\n },\n });\n\n const amountUsdc = parseFloat(amountStr);\n const amountUnits = Math.round(amountUsdc * USDC_UNIT);\n // Fee = max(0.01 USDC units, amount * 5%)\n const minFeeUnits = Math.round(0.01 * USDC_UNIT); // 10000 units = $0.01\n const percentFeeUnits = Math.round(amountUnits * 0.05);\n const feeUnits = Math.max(minFeeUnits, percentFeeUnits);\n const freezeUnits = amountUnits + feeUnits;\n\n feeDisplay = `${(feeUnits / USDC_UNIT).toFixed(6)} USDC`;\n freezeDisplay = `${(freezeUnits / USDC_UNIT).toFixed(6)} USDC`;\n\n typeBody.amount = amountUnits;\n typeBody.pay_to = await PromptEngine.resolveInput(opts.payTo as string | undefined, {\n message: 'Pay-to address:',\n });\n typeBody.nonce = await PromptEngine.resolveInput(opts.nonce as string | undefined, {\n message: 'Nonce:',\n });\n typeBody.network = await PromptEngine.resolveInput(opts.network as string | undefined, {\n message: 'Network:',\n });\n const deadlineStr = await PromptEngine.resolveInput(opts.deadline as string | undefined, {\n message: 'Deadline (Unix timestamp):',\n validate: (v) =>\n /^\\d+$/.test(v.trim()) || 'Deadline must be a Unix timestamp (integer seconds)',\n });\n // §3.4.1 request body requires `deadline: <number>` — coerce and validate\n // (covers both the --deadline flag path and the interactive path).\n const deadlineNum = Number(deadlineStr.trim());\n if (!Number.isInteger(deadlineNum) || deadlineNum <= 0) {\n throw new CliError(\n 'PARAM_INVALID',\n `Invalid deadline: \"${deadlineStr}\". Expected a Unix timestamp (integer seconds).`,\n );\n }\n typeBody.deadline = deadlineNum;\n }\n\n // --- Confirmation (unless --yes) ---\n if (!isYes) {\n const warningLines = [`Freeze: ${freezeDisplay}`, `Fee: ${feeDisplay}`];\n notify(format, 'warning', warningLines.join(' | '));\n\n const confirmed = await confirm({\n message: 'Proceed with token creation?',\n default: true,\n });\n if (!confirmed) {\n throw new CliError('CLIENT_ABORTED', 'Token creation cancelled by user');\n }\n }\n\n // --- Idempotency key (required for write) ---\n let idempotencyKey = opts.idempotencyKey as string | undefined;\n if (!idempotencyKey) {\n if (isYes) {\n throw new IdempotencyKeyRequiredError('payment-tokens create');\n }\n idempotencyKey = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => v.trim().length > 0 || 'Idempotency key is required',\n });\n }\n\n // --- Build request body ---\n const body: Record<string, unknown> = {\n type: serverType,\n payment_method_id: paymentMethodId,\n ...typeBody,\n };\n if (member) {\n body.member_id = member;\n }\n if (opts.externalTxId) {\n // platform CreatePaymentTokenRequest 字段名是 external_transaction_id;\n // 之前误写成 external_tx_id 会被 Pydantic(extra=ignore) 静默丢弃。\n body.external_transaction_id = opts.externalTxId as string;\n }\n\n const extraHeaders: Record<string, string> = {\n 'Idempotency-Key': idempotencyKey,\n };\n\n // --- POST /payment-tokens/create ---\n const result = await deps.apiClient.post<Record<string, unknown>>(\n '/payment-tokens/create',\n { type: 'api-key', key: apiKey },\n body,\n extraHeaders,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const tokenData = result.data;\n // Ensure type is on the top-level data for formatPaymentToken\n if (!tokenData.type) {\n tokenData.type = serverType;\n }\n\n // --- Output ---\n notify(format, 'success', 'Payment token created');\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<Record<string, unknown>> = {\n data: tokenData,\n text: () => {\n let output = formatPaymentToken(tokenData);\n // X402: append info message about X-PAYMENT header\n if (serverType === 'x402') {\n output += '\\n' + Formatter.status('info', 'Use the Signature Value in the X-PAYMENT request header');\n }\n return output;\n },\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n\n// ============================================================\n// Type-branch helpers\n// ============================================================\n\n/**\n * VCN feature gate: GET /features/vcn — if disabled, throw TOKEN_FEATURE_DISABLED.\n */\nasync function checkVcnFeatureEnabled(apiClient: ApiClient, apiKey: string): Promise<void> {\n const result = await apiClient.get<{ enabled: boolean }>(\n '/features/vcn',\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n // If the endpoint fails, treat as feature disabled (conservative)\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n if (!result.data.enabled) {\n throw new CliError(\n 'TOKEN_FEATURE_DISABLED',\n 'VCN creation is not supported yet. Coming soon.',\n );\n }\n}\n\n/**\n * Fetch network-token fee from /config/network-token-fee.\n * Falls back to DEFAULT_NT_FEE_CENTS (500) if unreachable.\n */\nasync function fetchNetworkTokenFee(apiClient: ApiClient, apiKey: string): Promise<number> {\n try {\n const result = await apiClient.get<{ fee_cents: number }>(\n '/config/network-token-fee',\n { type: 'api-key', key: apiKey },\n );\n\n if (result.success && typeof result.data.fee_cents === 'number') {\n return result.data.fee_cents;\n }\n // Unreachable / unexpected shape → fallback\n return DEFAULT_NT_FEE_CENTS;\n } catch {\n // Network error / timeout → fallback\n return DEFAULT_NT_FEE_CENTS;\n }\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport { attachSchemaHelp, ptListSchema } from '../verb-schema.js';\n\n// ============================================================\n// getSummary — per-type summary for table rendering (§3.4.2)\n// ============================================================\n\n/**\n * Render a one-line summary for a payment token in the list table.\n *\n * - vcn: `<first6>****<last4> $<limit/100>` (e.g. \"411111****1234 $25.00\")\n * - network_token: `<brand>` (e.g. \"Visa\")\n * - x402: `<amount> <network>` (e.g. \"1000000 Base\")\n */\nfunction getSummary(token: Record<string, unknown>): string {\n const type = token.type as string;\n\n if (type === 'vcn') {\n const first6 = String(token.first6 || token.first_six || '');\n const last4 = String(token.last4 || token.last_four || '');\n const limit = token.amount_limit as number | undefined ?? token.limit as number | undefined;\n const limitDisplay = limit !== undefined && limit !== null\n ? `$${(limit / 100).toFixed(2)}`\n : '';\n return `${first6}****${last4} ${limitDisplay}`.trim();\n }\n\n if (type === 'network_token') {\n const nt = token.network_token as Record<string, unknown> | undefined;\n return String(nt?.payment_brand || token.brand || '');\n }\n\n if (type === 'x402') {\n const amount = String(token.amount ?? '');\n const network = String(token.network || '');\n return `${amount} ${network}`.trim();\n }\n\n return '';\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `payment-tokens list` — list payment tokens (§3.4.2).\n *\n * GET /payment-tokens with X-Api-Key header.\n * Optional --type flag maps to ?type= query param.\n * Optional --member flag maps to ?member_id= query param.\n * Table headers: Token ID / Type / Status / Summary.\n * Empty list → `ℹ No payment tokens found` (no table).\n */\nexport function registerListCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('list')\n .description('List payment tokens')\n .option('--api-key <key>', 'API Key for authentication')\n .option('--type <type>', 'Filter by token type')\n .option('--member <member_id>', 'Filter by member ID');\n\n attachSchemaHelp(cmd, ptListSchema);\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', envVar: 'AGENZO_API_KEY',\n });\n\n // Build query params\n const params: Record<string, string> = {};\n if (opts.type) {\n params.type = opts.type as string;\n }\n if (opts.member) {\n params.member_id = opts.member as string;\n }\n\n const result = await deps.apiClient.get<Record<string, unknown>[]>(\n '/payment-tokens',\n { type: 'api-key', key: apiKey },\n Object.keys(params).length > 0 ? params : undefined,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const tokens = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<{ payment_tokens: Record<string, unknown>[] }> = {\n data: { payment_tokens: tokens },\n text: () => {\n if (tokens.length === 0) {\n return Formatter.status('info', 'No payment tokens found');\n }\n const headers = ['Token ID', 'Type', 'Status', 'Summary'];\n const rows = tokens.map((t) => [\n String(t.id || ''),\n String(t.type || ''),\n String(t.status || ''),\n getSummary(t),\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 ApiClient,\n ConfigManager,\n Formatter,\n PromptEngine,\n resolveFormat,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport { attachSchemaHelp, ptGetSchema } from '../verb-schema.js';\n\n// ============================================================\n// Formatter — SEPARATE from create's `formatPaymentToken` (Property 7)\n// ============================================================\n\ninterface FormatPaymentTokenGetOptions {\n revealSensitive?: boolean;\n}\n\nfunction asString(value: unknown): string {\n return typeof value === 'string' ? value : '';\n}\n\nfunction maskPan(value: string, lastFour?: string): string {\n const suffix = lastFour || value.slice(-4);\n if (!suffix) return '';\n const maskedLength = Math.max(value.length - suffix.length, 4);\n return `${'*'.repeat(maskedLength)}${suffix}`;\n}\n\nfunction maskCvc(value: string): string {\n return value ? '***' : '';\n}\n\nfunction maskVcnFields(vcn: Record<string, unknown>): Record<string, unknown> {\n const masked = { ...vcn };\n const lastFour = asString(masked.last_four ?? masked.last4);\n\n if (typeof masked.card_number === 'string') {\n masked.card_number = maskPan(masked.card_number, lastFour);\n }\n if (typeof masked.pan === 'string') {\n masked.pan = maskPan(masked.pan, lastFour);\n }\n if (typeof masked.cvc === 'string') {\n masked.cvc = maskCvc(masked.cvc);\n }\n if (typeof masked.cvv === 'string') {\n masked.cvv = maskCvc(masked.cvv);\n }\n\n return masked;\n}\n\n/** Build the JSON payload for `payment-tokens get`, masking VCN secrets by default. */\nexport function buildPaymentTokenGetPayload(\n data: Record<string, unknown>,\n opts: FormatPaymentTokenGetOptions = {},\n): Record<string, unknown> {\n if (opts.revealSensitive || data.type !== 'vcn') {\n return data;\n }\n\n const payload = { ...data };\n if (payload.vcn && typeof payload.vcn === 'object') {\n payload.vcn = maskVcnFields(payload.vcn as Record<string, unknown>);\n return payload;\n }\n\n return maskVcnFields(payload);\n}\n\n/**\n * Format a payment token for the `get` command output (§3.4.3).\n *\n * CRITICAL: This MUST remain a standalone formatter — do NOT converge\n * with `formatPaymentToken` in create.ts. The differences are intentional\n * per design Property 7:\n *\n * - Top key: `Token ID` (create uses `Payment Token ID`)\n * - VCN: includes a `Last 4` line (create does not)\n * - VCN `Limit` / `Balance`: numeric values WITHOUT `$` prefix\n * (create uses `$` prefix for `Limit`)\n *\n * By default VCN PAN/CVC are masked. Use `--reveal` to intentionally print\n * full VCN credentials for a payment flow that needs to use them.\n */\nexport function formatPaymentTokenGet(\n data: Record<string, unknown>,\n opts: FormatPaymentTokenGetOptions = {},\n): string {\n const type = data.type as string;\n const lines: [string, string][] = [];\n\n if (type === 'vcn') {\n const vcn = (data.vcn as Record<string, unknown> | undefined) ?? data;\n const lastFour = asString(vcn.last_four ?? vcn.last4);\n const cardNumber = asString(vcn.card_number ?? vcn.pan);\n const cvc = asString(vcn.cvc ?? vcn.cvv);\n lines.push(['Token ID', String(data.id || vcn.id || '')]);\n lines.push(['Type', 'VCN']);\n lines.push([\n 'Card Number',\n opts.revealSensitive ? cardNumber : maskPan(cardNumber, lastFour),\n ]);\n lines.push(['Last 4', lastFour]);\n lines.push(['Expiry', String(vcn.expiry || '')]);\n lines.push(['CVC', opts.revealSensitive ? cvc : maskCvc(cvc)]);\n // Limit and Balance: numeric cents → USD string, NO `$` prefix\n lines.push(['Limit', formatCentsPlain(vcn.amount_limit as number)]);\n lines.push(['Balance', formatCentsPlain(vcn.balance as number)]);\n lines.push(['Currency', String(vcn.currency || 'USD')]);\n lines.push(['Status', String(vcn.status || data.status || '')]);\n } else if (type === 'network_token') {\n const nt = (data.network_token as Record<string, unknown> | undefined) ?? data;\n lines.push(['Token ID', String(data.id || nt.id || '')]);\n lines.push(['Type', 'Network Token']);\n lines.push(['Brand', String(nt.payment_brand || nt.brand || '')]);\n lines.push(['ECI', String(nt.eci || '')]);\n lines.push(['Cryptogram', String(nt.token_cryptogram || nt.cryptogram || '')]);\n lines.push(['Expiry', String(nt.expiry_date || nt.expiry || '')]);\n lines.push(['Value', String(nt.value || '')]);\n } else if (type === 'x402') {\n const x402 = (data.x402 as Record<string, unknown> | undefined) ?? data;\n lines.push(['Token ID', String(data.id || x402.id || '')]);\n lines.push(['Type', 'X402']);\n lines.push(['Signature Value', String(x402.signature_value || '')]);\n lines.push(['Status', String(x402.status || data.status || '')]);\n } else {\n // Unknown type: best-effort\n lines.push(['Token ID', String(data.id || '')]);\n lines.push(['Type', String(type || 'unknown')]);\n lines.push(['Status', String(data.status || '')]);\n }\n\n return Formatter.keyValue(lines);\n}\n\n/**\n * Format cents as plain USD string without `$` prefix (e.g. 1250 → \"12.50\").\n * This is the key difference from create's `formatCentsToUsd` which is used\n * with a `$` prefix in `Limit`.\n */\nfunction formatCentsPlain(cents: number | undefined | null): string {\n if (cents === undefined || cents === null) return '0.00';\n const dollars = Math.floor(cents / 100);\n const remainder = cents % 100;\n return `${dollars}.${String(remainder).padStart(2, '0')}`;\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `payment-tokens get <payment_token_id>` — show a payment token (§3.4.3).\n *\n * Reads: GET /payment-tokens/<id> (X-Api-Key).\n * Output: keyValue with formatting that DIFFERS from create output (Property 7).\n */\nexport function registerGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('get <payment_token_id>')\n .description('Get a payment token by ID')\n .option('--api-key <key>', 'API key for authentication')\n .option('--reveal', 'Reveal full VCN card number and CVC in the output');\n\n attachSchemaHelp(cmd, ptGetSchema);\n cmd.action(async (paymentTokenId: string) => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n // Resolve API key — prompt interactively if not provided via flag\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password', envVar: 'AGENZO_API_KEY',\n });\n\n // GET /payment-tokens/<id>\n const result = await deps.apiClient.get<Record<string, unknown>>(\n `/payment-tokens/${paymentTokenId}`,\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const revealSensitive = Boolean(opts.reveal);\n const tokenData = buildPaymentTokenGetPayload(result.data, { revealSensitive });\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<Record<string, unknown>> = {\n data: tokenData,\n text: () => formatPaymentTokenGet(result.data, { revealSensitive }),\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 IdempotencyKeyRequiredError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { RevokeResult } from '../types/api.js';\nimport { attachSchemaHelp, ptRevokeSchema } from '../verb-schema.js';\n\n/**\n * `payment-tokens revoke <payment_token_id>` — revoke a payment token (§3.4.4).\n *\n * POST /payment-tokens/<id>/revoke (no body).\n * Two output states:\n * 1. Immediate revoke: `✓ Payment token revoked` + Token ID / Status / Revoked At\n * 2. Delayed revoke (X402, status==='ACTIVE' && expires_at non-null):\n * `✓ Revoke scheduled (cryptogram will auto-expire)` + Token ID / Status / Expires At (+message)\n *\n * Idempotency: --idempotency-key required in --yes mode (Requirement 6.3).\n */\nexport function registerRevokeCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('revoke <payment_token_id>')\n .description('Revoke a payment token')\n .option('--api-key <key>', 'API key for authentication')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n attachSchemaHelp(cmd, ptRevokeSchema);\n cmd.action(async (paymentTokenId: string) => {\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', envVar: 'AGENZO_API_KEY',\n });\n\n // Idempotency key handling (Requirement 6.3):\n // In --yes mode, --idempotency-key is mandatory — never auto-generate, never send request.\n // In interactive mode, prompt if not provided.\n let idempotencyKey = opts.idempotencyKey as string | undefined;\n if (!idempotencyKey) {\n if (opts.yes) {\n throw new IdempotencyKeyRequiredError('payment-tokens revoke');\n }\n idempotencyKey = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => v.trim().length > 0 || 'Idempotency key is required',\n });\n }\n\n const extraHeaders: Record<string, string> = {\n 'Idempotency-Key': idempotencyKey,\n };\n\n const result = await deps.apiClient.post<RevokeResult>(\n `/payment-tokens/${paymentTokenId}/revoke`,\n { type: 'api-key', key: apiKey },\n undefined,\n extraHeaders,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n // Determine output state:\n // Delayed revoke (X402): status is still ACTIVE and expires_at is present\n // Immediate revoke: all other cases\n const isDelayedRevoke = data.status === 'ACTIVE' && data.expires_at != null;\n\n if (isDelayedRevoke) {\n // Delayed revoke (X402 cryptogram will auto-expire)\n notify(format, 'success', 'Revoke scheduled (cryptogram will auto-expire)');\n\n const kvPairs: [string, string][] = [\n ['Token ID', data.id],\n ['Status', data.status],\n ['Expires At', Formatter.formatTime(data.expires_at)],\n ];\n if (data.message) {\n kvPairs.push(['Message', data.message]);\n }\n\n const cmdResult: CommandResult<RevokeResult> = {\n data,\n text: () => Formatter.keyValue(kvPairs),\n };\n\n const configManager = new ConfigManager();\n await renderWithContext(cmdResult, { format }, configManager);\n } else {\n // Immediate revoke\n notify(format, 'success', 'Payment token revoked');\n\n const cmdResult: CommandResult<RevokeResult> = {\n data,\n text: () =>\n Formatter.keyValue([\n ['Token ID', data.id],\n ['Status', data.status],\n ['Revoked At', Formatter.formatTime(data.revoked_at)],\n ]),\n };\n\n const configManager = new ConfigManager();\n await renderWithContext(cmdResult, { format }, configManager);\n }\n });\n}\n"],"mappings":"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","names":["readFile","writeFile","mkdir","chmod","join","homedir","join","homedir","mkdir","chmod","readFile","writeFile","password","password","select","select","cents","registerListCommand","registerGetCommand","registerListCommand","registerGetCommand"]}
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/payment-methods/prompts.ts","../src/payment-methods/add.ts","../src/payment-methods/list.ts","../src/payment-methods/get.ts","../src/payment-methods/disable.ts","../src/payment-tokens/create.ts","../src/payment-tokens/list.ts","../src/payment-tokens/get.ts","../src/payment-tokens/revoke.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// payment-methods commands\nimport { registerAddCommand } from './payment-methods/add.js';\nimport { registerListCommand as registerPmListCommand } from './payment-methods/list.js';\nimport { registerGetCommand as registerPmGetCommand } from './payment-methods/get.js';\nimport { registerDisableCommand as registerPmDisableCommand } from './payment-methods/disable.js';\n\n// payment-tokens commands\nimport { registerCreateCommand } from './payment-tokens/create.js';\nimport { registerListCommand as registerPtListCommand } from './payment-tokens/list.js';\nimport { registerGetCommand as registerPtGetCommand } from './payment-tokens/get.js';\nimport { registerRevokeCommand } from './payment-tokens/revoke.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. token-cli authenticates per-command via\n // `--api-key` (X-Api-Key); there is no Bearer session / AuthService / keystore.\n const configManager = new ConfigManager(undefined, '/api/token/v1');\n await configManager.ensureDirectories();\n\n const apiBaseUrl = await configManager.getApiBaseUrl();\n const apiClient = new ApiClient({ baseUrl: apiBaseUrl });\n\n // Shared deps object — API Key is supplied per-command, so commands only\n // 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-token-cli')\n .version(getCurrentVersion())\n .description(\n 'Agenzo token plane: payment methods (add payment method + 3DS) and payment tokens (VCN / Network Token / X402)',\n )\n .option('--verbose', 'Show verbose logs')\n .option('--yes', 'Skip confirmation prompts (for automation/AI Agents)')\n .option(\n '--format <format>',\n 'Output format: json | table (default: table; or set AGENZO_FORMAT)',\n );\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 // payment-methods command group\n const pmCmd = program.command('payment-methods').description('Payment method management');\n registerAddCommand(pmCmd, deps);\n registerPmListCommand(pmCmd, deps);\n registerPmGetCommand(pmCmd, deps);\n registerPmDisableCommand(pmCmd, deps);\n\n // payment-tokens command group\n const ptCmd = program.command('payment-tokens').description('Payment token management');\n registerCreateCommand(ptCmd, deps);\n registerPtListCommand(ptCmd, deps);\n registerPtGetCommand(ptCmd, deps);\n registerRevokeCommand(ptCmd, deps);\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); if an error was thrown before parsing, falls back to\n * `resolveFormat(undefined)` (which consults `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 * Unified outward-facing CLI error-code catalog (cli-design §8, single source of truth).\n *\n * Every outward code has both a string code (the preferred routing key) and a\n * numeric code (compact, convenient for log aggregation). The two map 1:1, bound\n * by {@link CODE_NUM}. String codes are grouped by domain prefix; numeric codes\n * are segmented by the same domains (§8.3).\n *\n * Note: `UPGRADE_REQUIRED` (CLI too old) and `CLIENT_ABORTED` (user-initiated\n * cancel) are non-business codes detected locally by the CLI. They are not part\n * of the §8.4 business dictionary and are allocated at the tail of the CLIENT range.\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 business codes (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) — produced locally by the 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 // Non-business code (detected locally by the CLI)\n | 'UPGRADE_REQUIRED';\n\n/**\n * String code → numeric code (§8.4). Each outward code's numeric value is\n * uniquely bound by this table; once published it is append-only (never changed).\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: 'VCN creation is not supported yet. Coming soon.',\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 // Allow HTTP for Docker internal container-to-container traffic (gated by env var)\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 { password } from '@inquirer/prompts';\nimport { PromptEngine } from '@agenzo/cli-core';\n\n// ============================================================\n// Payment-method interactive prompts (token-cli domain)\n// ============================================================\n//\n// These were relocated out of @agenzo/cli-core's PromptEngine: collecting card\n// number / expiry / CVV is token-cli payment-method business, not a generic\n// interactive fallback. cli-core keeps only the general `PromptEngine.resolveInput`.\n\n/** Always collect CVV interactively with masked display. */\nexport async function collectCvv(): Promise<string> {\n return password({\n message: 'CVV:',\n mask: '*',\n });\n}\n\n/** Collect payment method params based on type. */\nexport async function collectPaymentMethodParams(\n type: string,\n flags: Record<string, string | undefined>,\n): Promise<Record<string, string>> {\n const params: Record<string, string> = { type };\n\n const email = await PromptEngine.resolveInput(flags.cardEmail ?? flags.email, {\n message: 'Email (for 3DS verification):',\n });\n params.email = email;\n\n if (type === 'card') {\n params.card_number = await PromptEngine.resolveInput(flags.cardNumber, {\n message: 'Card number:',\n });\n params.expiry_date = await PromptEngine.resolveInput(flags.expiry, {\n message: 'Expiry (MMYY):',\n });\n // CVV: use flag if provided, otherwise collect interactively\n if (flags.cvv) {\n params.cvv = flags.cvv;\n } else {\n params.cvv = await collectCvv();\n }\n }\n\n return params;\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n IdempotencyKeyRequiredError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult, OutputFormat } from '@agenzo/cli-core';\nimport type { DropinCreateResponse, PaymentMethod } from '../types/api.js';\nimport { collectPaymentMethodParams } from './prompts.js';\n\n// ============================================================\n// Constants\n// ============================================================\n\n// Manual mode (3DS via email): the user clicks the magic link in their\n// inbox, so polling is short and tight.\nconst MANUAL_POLL_INTERVAL_MS = 3000;\nconst MANUAL_POLL_TIMEOUT_MS = 15 * 60 * 1000; // 15 minutes\n\n// Drop-in mode (v3): the add-payment-method form is rendered by the Drop-in\n// SDK inside the developer's own front-end, so the operator may need longer\n// to finish in the browser. The backend flips the PM to EXPIRED if the user\n// does not complete in time.\nconst DROPIN_POLL_INTERVAL_MS = 5000;\nconst DROPIN_POLL_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\n\n// Backend writes one of these into PaymentMethod.status when the verification\n// flow reaches a final state. We stop polling on any of them. EXPIRED only\n// ever applies to dropin PMs (manual PMs never expire server-side).\nconst TERMINAL_STATUSES = new Set(['ACTIVE', 'FAILED', 'EXPIRED']);\n\ntype AddDeps = { apiClient: ApiClient };\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `payment-methods add` — add a payment method (§3.4.0.1).\n *\n * Two modes, selected via `--mode`:\n *\n * - `manual` (default): the CLI collects card details (--email / --card-number\n * / --expiry / --cvv), POSTs /payment-methods/create, then polls 3DS\n * verification until ACTIVE / FAILED / 15-minute timeout.\n * - `dropin`: the CLI mints a Drop-in session (POST /payment-methods/dropin/create\n * with the developer email), prints the session id so the caller can render\n * the add-payment UI in their own front-end via the Drop-in SDK, then polls\n * the same verification/status endpoint until ACTIVE / FAILED / EXPIRED /\n * 30-minute timeout. No card details / idempotency key are needed.\n */\nexport function registerAddCommand(parent: Command, deps: AddDeps): void {\n const cmd = parent\n .command('add')\n .description('Add a payment method (manual 3DS or Drop-in session)')\n .option('--api-key <key>', 'API Key for authentication')\n .option('--type <type>', 'Payment method type (default: card)', 'card')\n .option(\n '--mode <mode>',\n 'Add mode: \"manual\" (default; CLI collects card details and polls 3DS) or \"dropin\" (mint a Drop-in session and poll until the user finishes adding the payment method in the browser)',\n 'manual',\n )\n .option(\n '--email <email>',\n 'Manual mode: email for 3DS verification. Dropin mode: email used as the Drop-in session reference.',\n )\n .option('--card-number <number>', 'Card number (manual mode only)')\n .option('--expiry <mmyy>', 'Expiry date (MMYY format) (manual mode only)')\n .option('--cvv <cvv>', 'Card CVV (manual mode only)')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header (manual mode only)',\n );\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 mode = String(opts.mode ?? 'manual').toLowerCase();\n if (mode !== 'manual' && mode !== 'dropin') {\n throw new CliError(\n 'PARAM_INVALID',\n `Unknown --mode \"${opts.mode}\". Expected \"manual\" or \"dropin\".`,\n );\n }\n\n if (mode === 'dropin') {\n await handleDropinMode(deps, opts, format);\n return;\n }\n\n await handleManualMode(deps, opts, format, isYes);\n });\n}\n\n// ============================================================\n// Manual mode (collect card details + 3DS polling)\n// ============================================================\n\n/**\n * Manual mode: collect card details, POST /payment-methods/create, then poll\n * 3DS verification status until ACTIVE / FAILED / 15-minute timeout.\n */\nasync function handleManualMode(\n deps: AddDeps,\n opts: Record<string, unknown>,\n format: OutputFormat,\n isYes: boolean,\n): Promise<void> {\n // --- Resolve API key ---\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // --- Resolve payment method type ---\n const type = (opts.type as string) || 'card';\n\n // --- Collect card params via PromptEngine ---\n const flags: Record<string, string | undefined> = {\n email: opts.email as string | undefined,\n cardNumber: opts.cardNumber as string | undefined,\n expiry: opts.expiry as string | undefined,\n cvv: opts.cvv as string | undefined,\n };\n const params = await collectPaymentMethodParams(type, flags);\n\n // --- Idempotency key (required for write, Requirement 6.3) ---\n let idempotencyKey = opts.idempotencyKey as string | undefined;\n if (!idempotencyKey) {\n if (isYes) {\n throw new IdempotencyKeyRequiredError('payment-methods add');\n }\n idempotencyKey = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => v.trim().length > 0 || 'Idempotency key is required',\n });\n }\n\n const extraHeaders: Record<string, string> = {\n 'Idempotency-Key': idempotencyKey,\n };\n\n // --- POST /payment-methods/create ---\n const result = await deps.apiClient.post<PaymentMethod>(\n '/payment-methods/create',\n { type: 'api-key', key: apiKey },\n params,\n extraHeaders,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const pm = result.data;\n\n // --- Output: created state ---\n notify(format, 'success', 'Payment method created');\n\n const createdResult: CommandResult<PaymentMethod> = {\n data: pm,\n text: () => {\n const lines: [string, string][] = [\n ['ID', pm.id],\n ['Type', pm.type],\n ['Status', pm.status],\n ];\n if (pm.brand) lines.push(['Brand', pm.brand]);\n if (pm.first6) lines.push(['First 6', pm.first6]);\n if (pm.last4) lines.push(['Last 4', pm.last4]);\n return Formatter.keyValue(lines);\n },\n };\n\n const configManager = new ConfigManager();\n await renderWithContext(createdResult, { format }, configManager);\n\n // Hint about 3DS (after keyValue output)\n notify(format, 'info', 'Complete 3DS verification via email to activate');\n\n // --- 3DS polling (only for type=card and PENDING status) ---\n if (type === 'card' && pm.status === 'PENDING') {\n const finalStatus = await poll3dsVerification(deps.apiClient, apiKey, pm.id, format);\n\n if (finalStatus === 'ACTIVE') {\n // Fetch the updated payment method for full details\n const getResult = await deps.apiClient.get<PaymentMethod>(\n `/payment-methods/${pm.id}`,\n { type: 'api-key', key: apiKey },\n );\n\n if (getResult.success) {\n const activatedPm = getResult.data;\n notify(format, 'success', 'Payment method activated');\n\n const activatedResult: CommandResult<PaymentMethod> = {\n data: activatedPm,\n text: () => {\n const lines: [string, string][] = [\n ['ID', activatedPm.id],\n ['Type', activatedPm.type],\n ['Status', activatedPm.status],\n ];\n if (activatedPm.brand) lines.push(['Brand', activatedPm.brand]);\n if (activatedPm.first6) lines.push(['First 6', activatedPm.first6]);\n if (activatedPm.last4) lines.push(['Last 4', activatedPm.last4]);\n return Formatter.keyValue(lines);\n },\n };\n\n await renderWithContext(activatedResult, { format }, configManager);\n } else {\n // 3DS already reported ACTIVE, but the follow-up detail GET failed.\n // Emit a degraded terminal state from what we already know (the\n // create response + known-ACTIVE status) rather than exiting silently.\n notify(format, 'success', 'Payment method activated');\n\n const degraded: PaymentMethod = { ...pm, status: 'ACTIVE' };\n const degradedResult: CommandResult<PaymentMethod> = {\n data: degraded,\n text: () => {\n const lines: [string, string][] = [\n ['ID', degraded.id],\n ['Type', degraded.type],\n ['Status', degraded.status],\n ];\n if (degraded.brand) lines.push(['Brand', degraded.brand]);\n if (degraded.first6) lines.push(['First 6', degraded.first6]);\n if (degraded.last4) lines.push(['Last 4', degraded.last4]);\n return Formatter.keyValue(lines);\n },\n };\n\n await renderWithContext(degradedResult, { format }, configManager);\n }\n } else if (finalStatus === 'FAILED') {\n notify(format, 'error', '3DS verification failed');\n } else if (finalStatus === 'TIMEOUT') {\n notify(\n format,\n 'info',\n `Verification timed out (15 min). Check status with: agenzo-token-cli payment-methods get ${pm.id} --api-key <your_key>`,\n );\n }\n }\n}\n\n// ============================================================\n// Drop-in mode (mint Drop-in session + poll)\n// ============================================================\n\n/**\n * Drop-in mode: mint a Drop-in session and hand the add-payment-method UI off\n * to the developer's own front-end (which embeds the Drop-in SDK using the\n * session id). The CLI then polls the same verification/status endpoint manual\n * mode uses until the PM reaches a terminal status or the 30-minute timeout.\n */\nasync function handleDropinMode(\n deps: AddDeps,\n opts: Record<string, unknown>,\n format: OutputFormat,\n): Promise<void> {\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n const email = await PromptEngine.resolveInput(opts.email as string | undefined, {\n message: 'Email:',\n });\n\n const configManager = new ConfigManager();\n\n // 1) Create the Drop-in session (API Key auth). The backend creates a\n // PENDING PM keyed by pm_id and mints the session for the front-end SDK.\n const sessionResult = await deps.apiClient.post<DropinCreateResponse>(\n '/payment-methods/dropin/create',\n { type: 'api-key', key: apiKey },\n { email },\n );\n\n if (!sessionResult.success) {\n throw CliError.fromApi(sessionResult, { auth: 'api-key' });\n }\n\n const session = sessionResult.data;\n const pmId = session.id;\n\n // 2) Print the session id so the caller can initialise the front-end SDK.\n notify(format, 'success', 'Drop-in session created');\n\n const createdResult: CommandResult<DropinCreateResponse> = {\n data: session,\n text: () => Formatter.keyValue([['Session ID', session.session_id || '-']]),\n };\n await renderWithContext(createdResult, { format }, configManager);\n\n notify(\n format,\n 'info',\n 'Use the Session ID to add the payment method in the browser via the Drop-in SDK',\n );\n\n // 3) Poll verification/status (same endpoint manual mode uses) until the PM\n // reaches a terminal status or we time out at 30 minutes.\n const finalPm = await pollVerificationStatus(deps.apiClient, apiKey, pmId, {\n intervalMs: DROPIN_POLL_INTERVAL_MS,\n timeoutMs: DROPIN_POLL_TIMEOUT_MS,\n });\n\n if (finalPm.status === 'ACTIVE') {\n notify(format, 'success', 'Payment method activated');\n const activated: CommandResult<PaymentMethod> = {\n data: finalPm,\n text: () =>\n Formatter.keyValue([\n ['PM ID', finalPm.id],\n ['Brand', finalPm.brand ?? '-'],\n ['First 6', finalPm.first6 ?? '-'],\n ['Last 4', finalPm.last4 ?? '-'],\n ['Status', finalPm.status],\n ]),\n };\n await renderWithContext(activated, { format }, configManager);\n return;\n }\n\n if (finalPm.status === 'FAILED') {\n notify(format, 'error', 'Failed to add payment method');\n await renderPmId(finalPm.id, format, configManager);\n process.exitCode = 1;\n return;\n }\n\n if (finalPm.status === 'EXPIRED') {\n notify(format, 'error', 'Session expired before the payment method was added');\n await renderPmId(finalPm.id, format, configManager);\n process.exitCode = 1;\n return;\n }\n\n // Timed out without reaching a terminal status — PM is still PENDING\n // server-side. The operator can re-run with the same email to resume\n // (PENDING dropin PMs are overwritten/reused).\n notify(\n format,\n 'error',\n 'Adding payment method did not complete within 30 minutes. Re-run with the same email to resume.',\n );\n await renderPmId(pmId, format, configManager);\n process.exitCode = 1;\n}\n\n/** Render `{ id }` as the terminal payload (PM ID line in table, JSON in json). */\nasync function renderPmId(\n id: string,\n format: OutputFormat,\n configManager: ConfigManager,\n): Promise<void> {\n const result: CommandResult<{ id: string }> = {\n data: { id },\n text: () => Formatter.keyValue([['PM ID', id]]),\n };\n await renderWithContext(result, { format }, configManager);\n}\n\n// ============================================================\n// Polling helpers\n// ============================================================\n\n/**\n * Poll GET /payment-methods/verification/status?payment_method_id=<id> every\n * 3000ms until ACTIVE, FAILED, or 15-minute timeout (manual / 3DS mode).\n *\n * Returns the terminal status: 'ACTIVE' | 'FAILED' | 'TIMEOUT'.\n */\nasync function poll3dsVerification(\n apiClient: ApiClient,\n apiKey: string,\n paymentMethodId: string,\n format: OutputFormat,\n): Promise<'ACTIVE' | 'FAILED' | 'TIMEOUT'> {\n const startTime = Date.now();\n\n notify(format, 'info', 'Waiting for 3DS verification...');\n\n while (Date.now() - startTime < MANUAL_POLL_TIMEOUT_MS) {\n await sleep(MANUAL_POLL_INTERVAL_MS);\n\n const result = await apiClient.get<{ status: string }>(\n '/payment-methods/verification/status',\n { type: 'api-key', key: apiKey },\n { payment_method_id: paymentMethodId },\n );\n\n if (result.success) {\n const status = result.data.status;\n if (status === 'ACTIVE') {\n return 'ACTIVE';\n }\n if (status === 'FAILED') {\n return 'FAILED';\n }\n // Still PENDING — continue polling\n }\n // On API error during polling, continue trying (transient failures)\n }\n\n return 'TIMEOUT';\n}\n\ninterface PollOptions {\n intervalMs: number;\n timeoutMs: number;\n}\n\n/**\n * Poll GET /payment-methods/verification/status?payment_method_id=<id> at\n * `intervalMs` until the PM reaches a terminal status (ACTIVE / FAILED /\n * EXPIRED) or `timeoutMs` elapses (dropin mode).\n *\n * Returns the final PaymentMethod on a terminal status, or\n * `{ id, status: 'PENDING' }` on timeout so callers can branch on the final\n * status uniformly. Transient poll errors are ignored (next tick retries).\n */\nasync function pollVerificationStatus(\n apiClient: ApiClient,\n apiKey: string,\n pmId: string,\n options: PollOptions,\n): Promise<PaymentMethod> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < options.timeoutMs) {\n const result = await apiClient.get<PaymentMethod>(\n '/payment-methods/verification/status',\n { type: 'api-key', key: apiKey },\n { payment_method_id: pmId },\n );\n\n if (result.success && TERMINAL_STATUSES.has(result.data.status)) {\n return result.data;\n }\n\n await sleep(options.intervalMs);\n }\n\n return { id: pmId, status: 'PENDING' } as PaymentMethod;\n}\n\n/** Simple async sleep utility. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { PaymentMethod } from '../types/api.js';\n\n/**\n * `payment-methods list` — list payment methods (§3.4.0.2).\n *\n * GET /payment-methods with X-Api-Key header.\n * Optional --member flag maps to ?member_id= query param.\n * Table headers: ID / Type / Brand / First 6 / Last 4 / Status.\n * Empty list → info message (no table). Missing brand/first6/last4 → `-`.\n */\nexport function registerListCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('list')\n .description('List payment methods')\n .option('--api-key <key>', 'API Key for authentication')\n .option('--member <member_id>', 'Filter by member ID');\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\n const params: Record<string, string> = {};\n if (opts.member) {\n params.member_id = opts.member as string;\n }\n\n const result = await deps.apiClient.get<PaymentMethod[]>(\n '/payment-methods',\n { type: 'api-key', key: apiKey },\n Object.keys(params).length > 0 ? params : undefined,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const methods = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<{ payment_methods: PaymentMethod[] }> = {\n data: { payment_methods: methods },\n text: () => {\n if (methods.length === 0) {\n return Formatter.status('info', 'No payment methods found');\n }\n const headers = ['ID', 'Type', 'Brand', 'First 6', 'Last 4', 'Status'];\n const rows = methods.map((m) => [\n m.id,\n m.type,\n m.brand || '-',\n m.first6 || '-',\n m.last4 || '-',\n m.status,\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 ApiClient,\n ConfigManager,\n Formatter,\n PromptEngine,\n resolveFormat,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { PaymentMethod } from '../types/api.js';\n\n/**\n * `payment-methods get <pm_id>` — show a single payment method (§3.4.0.3).\n *\n * Reads: GET /payment-methods/<pm_id> (X-Api-Key).\n * Output: keyValue. Brand / First 6 / Last 4 appear only when their\n * corresponding fields are non-empty/non-null (conditional inclusion).\n */\nexport function registerGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('get <pm_id>')\n .description('Get a payment method by ID')\n .option('--api-key <key>', 'API key for authentication');\n\n cmd.action(async (pmId: string) => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n // Resolve API key — prompt interactively if not provided via flag\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // GET /payment-methods/<pm_id>\n const result = await deps.apiClient.get<PaymentMethod>(\n `/payment-methods/${pmId}`,\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const pm = result.data;\n\n // Build keyValue entries — Brand/First 6/Last 4 only when non-empty\n const entries: [string, string][] = [\n ['ID', pm.id],\n ['Type', pm.type],\n ];\n\n if (pm.brand) {\n entries.push(['Brand', pm.brand]);\n }\n if (pm.first6) {\n entries.push(['First 6', pm.first6]);\n }\n if (pm.last4) {\n entries.push(['Last 4', pm.last4]);\n }\n\n entries.push(['Status', pm.status]);\n entries.push(['Created', Formatter.formatTime(pm.created_at)]);\n\n const configManager = new ConfigManager();\n const cmdResult: CommandResult<PaymentMethod> = {\n data: pm,\n text: () => Formatter.keyValue(entries),\n };\n\n await renderWithContext(cmdResult, { format }, configManager);\n });\n}\n","import { renderWithContext } from '@agenzo/cli-core';\nimport { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n IdempotencyKeyRequiredError,\n} from '@agenzo/cli-core';\nimport type { CommandResult, DisableResult } from '@agenzo/cli-core';\n\n/**\n * `payment-methods disable <pm_id>` — disable a payment method (§3.4.0.4).\n *\n * POST /payment-methods/<pm_id>/disable (no body).\n * Output: `✓ Payment method <id> disabled` + Status + Revoked tokens.\n * Idempotency: --idempotency-key required in --yes mode (Requirement 6.3).\n */\nexport function registerDisableCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('disable <pm_id>')\n .description('Disable a payment method')\n .option('--api-key <key>', 'API key for authentication')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n cmd.action(async (pmId: string) => {\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 // Idempotency key handling (Requirement 6.3):\n // In --yes mode, --idempotency-key is mandatory — never auto-generate, never send request.\n // In interactive mode, prompt if not provided.\n let idempotencyKey = opts.idempotencyKey as string | undefined;\n if (!idempotencyKey) {\n if (opts.yes) {\n throw new IdempotencyKeyRequiredError('payment-methods disable');\n }\n idempotencyKey = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => v.trim().length > 0 || 'Idempotency key is required',\n });\n }\n\n const extraHeaders: Record<string, string> = {\n 'Idempotency-Key': idempotencyKey,\n };\n\n const result = await deps.apiClient.post<DisableResult>(\n `/payment-methods/${pmId}/disable`,\n { type: 'api-key', key: apiKey },\n undefined,\n extraHeaders,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n // Status line → stderr (json mode stays silent per §5)\n notify(format, 'success', `Payment method ${pmId} disabled`);\n\n const cmdResult: CommandResult<DisableResult> = {\n data,\n text: () =>\n Formatter.keyValue([\n ['Status', data.status],\n ['Revoked tokens', String(data.revoked_tokens_count ?? 0)],\n ]),\n };\n\n const configManager = new ConfigManager();\n await renderWithContext(cmdResult, { format }, configManager);\n });\n}\n","import { Command } from 'commander';\nimport { confirm, select } from '@inquirer/prompts';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n notify,\n CliError,\n IdempotencyKeyRequiredError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult, OutputFormat } from '@agenzo/cli-core';\nimport type { PaymentMethod } from '../types/api.js';\n\n// ============================================================\n// Constants\n// ============================================================\n\n/** Default network-token fee in cents when /config/network-token-fee is unreachable. */\nconst DEFAULT_NT_FEE_CENTS = 500;\n\n/** Smallest USDC unit (1 USDC = 1_000_000 micro-units). */\nconst USDC_UNIT = 1_000_000;\n\n// ============================================================\n// Helpers (token-domain-specific — stays in app per requirement 5.5)\n// ============================================================\n\n/**\n * Map CLI `--type` flag value to the server-side `type` field.\n * `network-token` → `network_token`; unknown values pass through unchanged.\n */\nexport function mapTokenType(cliType: string): string {\n if (cliType === 'network-token') return 'network_token';\n return cliType;\n}\n\n/**\n * Convert a USD amount string (e.g. \"12.50\") to integer cents using\n * string-based parsing to avoid floating-point drift.\n *\n * Accepts formats: \"12\", \"12.5\", \"12.50\", \".50\", \"0.01\".\n * Throws PARAM_INVALID on non-numeric / out-of-range.\n */\nexport function usdToCents(amountStr: string): number {\n const trimmed = amountStr.trim();\n\n // Validate format: optional digits, optional decimal point with up to 2 fractional digits\n if (!/^\\d*\\.?\\d{0,2}$/.test(trimmed) || trimmed === '' || trimmed === '.') {\n throw new CliError('PARAM_INVALID', `Invalid amount format: \"${amountStr}\". Expected a decimal like \"12.50\".`);\n }\n\n const parts = trimmed.split('.');\n const integerPart = parts[0] || '0';\n let fractionalPart = parts[1] || '0';\n\n // Pad fractional to exactly 2 digits\n fractionalPart = fractionalPart.padEnd(2, '0');\n\n const integerCents = parseInt(integerPart, 10) * 100;\n const fractionalCents = parseInt(fractionalPart, 10);\n return integerCents + fractionalCents;\n}\n\n/**\n * Resolve the payment method to use, following 4-level priority:\n * 1. --payment-method-id (explicit)\n * 2. --card (match last4 against ACTIVE cards)\n * 3. Single ACTIVE card → auto-select\n * 4. Multiple ACTIVE cards → interactive select\n *\n * Throws CLIENT_NO_PAYMENT_METHOD when no ACTIVE cards exist.\n * Throws CLIENT_CARD_NOT_MATCHED when --card doesn't match any ACTIVE card.\n */\nexport async function resolvePaymentMethod(\n apiClient: ApiClient,\n apiKey: string,\n opts: {\n paymentMethodId?: string;\n card?: string;\n yes?: boolean;\n },\n): Promise<string> {\n // Priority 1: explicit --payment-method-id\n if (opts.paymentMethodId) {\n return opts.paymentMethodId;\n }\n\n // Need to fetch ACTIVE cards for priorities 2–4\n const result = await apiClient.get<PaymentMethod[]>(\n '/payment-methods',\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const activeCards = result.data.filter((m) => m.status === 'ACTIVE');\n\n if (activeCards.length === 0) {\n throw new CliError(\n 'CLIENT_NO_PAYMENT_METHOD',\n 'No active payment methods found. Add one with: agenzo-token-cli payment-methods add --api-key <your_key>',\n );\n }\n\n // Priority 2: --card (match last4)\n if (opts.card) {\n const matched = activeCards.find((m) => m.last4 === opts.card);\n if (!matched) {\n throw new CliError(\n 'CLIENT_CARD_NOT_MATCHED',\n `No active card ending in ${opts.card}. Available: ${activeCards.map((m) => m.last4 || '????').join(', ')}`,\n );\n }\n return matched.id;\n }\n\n // Priority 3: single card → auto-select\n if (activeCards.length === 1) {\n return activeCards[0].id;\n }\n\n // Priority 4: multiple cards → interactive select\n if (opts.yes) {\n // In --yes mode we cannot prompt; if there's ambiguity, we cannot proceed\n throw new CliError(\n 'PARAM_INVALID',\n 'Multiple active payment methods found. Specify --payment-method-id or --card to disambiguate.',\n );\n }\n\n const selected = await select({\n message: 'Select a payment method:',\n choices: activeCards.map((m) => ({\n name: `${m.id} (${m.brand || m.type} ****${m.last4 || '????'})`,\n value: m.id,\n })),\n });\n\n return selected;\n}\n\n/**\n * Format a payment token for human-readable output (§3.4.1 create output).\n * Renders differently per type: VCN / Network Token / X402.\n *\n * NOTE: The server response wraps type-specific data under `data.vcn`,\n * `data.network_token`, or `data.x402` (nested). This formatter reads\n * from that nested structure directly.\n */\nexport function formatPaymentToken(data: Record<string, unknown>): string {\n const type = data.type as string;\n const lines: [string, string][] = [];\n\n if (type === 'vcn') {\n const vcn = data.vcn as Record<string, unknown> | undefined ?? data;\n lines.push(['Payment Token ID', String(data.id || vcn.id || '')]);\n lines.push(['Type', 'VCN']);\n lines.push(['Card Number', String(vcn.card_number || '')]);\n lines.push(['Expiry', String(vcn.expiry || '')]);\n lines.push(['CVC', String(vcn.cvc || '')]);\n lines.push(['Limit', `$${formatCentsToUsd(vcn.amount_limit as number)}`]);\n lines.push(['Currency', String(vcn.currency || 'USD')]);\n lines.push(['Status', String(vcn.status || data.status || '')]);\n } else if (type === 'network_token') {\n const nt = data.network_token as Record<string, unknown> | undefined ?? data;\n lines.push(['Payment Token ID', String(data.id || nt.id || '')]);\n lines.push(['Type', 'Network Token']);\n lines.push(['Brand', String(nt.payment_brand || nt.brand || '')]);\n lines.push(['ECI', String(nt.eci || '')]);\n lines.push(['Cryptogram', String(nt.token_cryptogram || nt.cryptogram || '')]);\n lines.push(['Expiry', String(nt.expiry_date || nt.expiry || '')]);\n lines.push(['Value', String(nt.value || '')]);\n } else if (type === 'x402') {\n const x402 = data.x402 as Record<string, unknown> | undefined ?? data;\n lines.push(['Payment Token ID', String(data.id || x402.id || '')]);\n lines.push(['Type', 'X402']);\n lines.push(['Signature Value', String(x402.signature_value || '')]);\n lines.push(['Status', String(x402.status || data.status || '')]);\n } else {\n // Unknown type: best-effort\n lines.push(['Payment Token ID', String(data.id || '')]);\n lines.push(['Type', String(type || 'unknown')]);\n lines.push(['Status', String(data.status || '')]);\n }\n\n return Formatter.keyValue(lines);\n}\n\n/** Format cents back to USD string (e.g. 1250 → \"12.50\"). */\nfunction formatCentsToUsd(cents: number | undefined): string {\n if (cents === undefined || cents === null) return '0.00';\n const dollars = Math.floor(cents / 100);\n const remainder = cents % 100;\n return `${dollars}.${String(remainder).padStart(2, '0')}`;\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `payment-tokens create` — generate a VCN / Network Token / X402 credential\n * (§3.4.1).\n */\nexport function registerCreateCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('create')\n .description('Create a payment token (VCN / Network Token / X402)')\n .option('--api-key <key>', 'API Key for authentication')\n .option('--type <type>', 'Token type: vcn | network-token | x402')\n .option('--payment-method-id <id>', 'Payment method ID to use')\n .option('--card <last4>', 'Match payment method by last 4 digits')\n .option('--member <member_id>', 'Member ID')\n .option('--amount <amount>', 'Amount in USD (VCN / X402)')\n .option('--currency <currency>', 'Currency (default: USD)')\n .option('--pay-to <address>', 'Pay-to address (X402)')\n .option('--nonce <nonce>', 'Nonce (X402)')\n .option('--network <network>', 'Network (X402)')\n .option('--deadline <deadline>', 'Deadline (X402)')\n .option('--external-tx-id <id>', 'External transaction ID')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\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 // --- Resolve API key ---\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // --- Resolve token type ---\n const cliType = await PromptEngine.resolveInput(opts.type as string | undefined, {\n message: 'Token type:',\n type: 'select',\n choices: [\n { name: 'VCN (Virtual Card Number)', value: 'vcn' },\n { name: 'Network Token', value: 'network-token' },\n { name: 'X402 (USDC on-chain)', value: 'x402' },\n ],\n });\n const serverType = mapTokenType(cliType);\n\n // --- Resolve payment method (4-level priority) ---\n const paymentMethodId = await resolvePaymentMethod(deps.apiClient, apiKey, {\n paymentMethodId: opts.paymentMethodId as string | undefined,\n card: opts.card as string | undefined,\n yes: isYes,\n });\n\n // --- Resolve member ---\n let member: string | undefined = opts.member as string | undefined;\n if (!member && !isYes) {\n // In interactive mode, prompt for member (optional — allow empty)\n const memberInput = await PromptEngine.resolveInput(undefined, {\n message: 'Member ID (optional, press Enter to skip):',\n validate: () => true, // always valid (optional)\n });\n if (memberInput.trim()) {\n member = memberInput.trim();\n }\n }\n // In --yes mode, if --member not provided, omit it (don't prompt).\n\n // --- Type-specific branch logic ---\n let freezeAmountCents: number | undefined;\n let feeCents: number | undefined;\n let feeDisplay: string | undefined;\n let freezeDisplay: string | undefined;\n // Body fields that vary by type\n const typeBody: Record<string, unknown> = {};\n\n if (serverType === 'vcn') {\n // VCN branch: feature gate + amount + fee\n await checkVcnFeatureEnabled(deps.apiClient, apiKey);\n\n const amountStr = await PromptEngine.resolveInput(opts.amount as string | undefined, {\n message: 'Amount (USD, e.g. 25.00):',\n validate: (v) => {\n try {\n const cents = usdToCents(v);\n if (cents < 1 || cents > 50000) {\n return 'Amount must be between $0.01 and $500.00';\n }\n return true;\n } catch {\n return 'Invalid amount format. Use a decimal like \"25.00\"';\n }\n },\n });\n\n const cents = usdToCents(amountStr);\n if (cents < 1 || cents > 50000) {\n throw new CliError(\n 'PARAM_INVALID',\n 'Amount must be between $0.01 and $500.00',\n );\n }\n\n feeCents = Math.max(1, Math.round(cents * 0.05));\n freezeAmountCents = cents + feeCents;\n feeDisplay = `$${formatCentsToUsd(feeCents)}`;\n freezeDisplay = `$${formatCentsToUsd(freezeAmountCents)}`;\n\n typeBody.amount = cents;\n // §3.4.1: --currency omitted → do NOT send; server applies its default.\n if (opts.currency) {\n typeBody.currency = opts.currency as string;\n }\n } else if (serverType === 'network_token') {\n // Network-token branch: fetch fee config (fallback to default)\n feeCents = await fetchNetworkTokenFee(deps.apiClient, apiKey);\n freezeAmountCents = feeCents;\n feeDisplay = `$${formatCentsToUsd(feeCents)}`;\n freezeDisplay = feeDisplay;\n } else if (serverType === 'x402') {\n // X402 branch: USDC amount + fee\n const amountStr = await PromptEngine.resolveInput(opts.amount as string | undefined, {\n message: 'Amount (USDC):',\n validate: (v) => {\n const n = parseFloat(v);\n if (isNaN(n) || n <= 0) return 'Amount must be a positive number';\n return true;\n },\n });\n\n const amountUsdc = parseFloat(amountStr);\n const amountUnits = Math.round(amountUsdc * USDC_UNIT);\n // Fee = max(0.01 USDC units, amount * 5%)\n const minFeeUnits = Math.round(0.01 * USDC_UNIT); // 10000 units = $0.01\n const percentFeeUnits = Math.round(amountUnits * 0.05);\n const feeUnits = Math.max(minFeeUnits, percentFeeUnits);\n const freezeUnits = amountUnits + feeUnits;\n\n feeDisplay = `${(feeUnits / USDC_UNIT).toFixed(6)} USDC`;\n freezeDisplay = `${(freezeUnits / USDC_UNIT).toFixed(6)} USDC`;\n\n typeBody.amount = amountUnits;\n typeBody.pay_to = await PromptEngine.resolveInput(opts.payTo as string | undefined, {\n message: 'Pay-to address:',\n });\n typeBody.nonce = await PromptEngine.resolveInput(opts.nonce as string | undefined, {\n message: 'Nonce:',\n });\n typeBody.network = await PromptEngine.resolveInput(opts.network as string | undefined, {\n message: 'Network:',\n });\n const deadlineStr = await PromptEngine.resolveInput(opts.deadline as string | undefined, {\n message: 'Deadline (Unix timestamp):',\n validate: (v) =>\n /^\\d+$/.test(v.trim()) || 'Deadline must be a Unix timestamp (integer seconds)',\n });\n // §3.4.1 request body requires `deadline: <number>` — coerce and validate\n // (covers both the --deadline flag path and the interactive path).\n const deadlineNum = Number(deadlineStr.trim());\n if (!Number.isInteger(deadlineNum) || deadlineNum <= 0) {\n throw new CliError(\n 'PARAM_INVALID',\n `Invalid deadline: \"${deadlineStr}\". Expected a Unix timestamp (integer seconds).`,\n );\n }\n typeBody.deadline = deadlineNum;\n }\n\n // --- Confirmation (unless --yes) ---\n if (!isYes) {\n const warningLines = [`Freeze: ${freezeDisplay}`, `Fee: ${feeDisplay}`];\n notify(format, 'warning', warningLines.join(' | '));\n\n const confirmed = await confirm({\n message: 'Proceed with token creation?',\n default: true,\n });\n if (!confirmed) {\n throw new CliError('CLIENT_ABORTED', 'Token creation cancelled by user');\n }\n }\n\n // --- Idempotency key (required for write) ---\n let idempotencyKey = opts.idempotencyKey as string | undefined;\n if (!idempotencyKey) {\n if (isYes) {\n throw new IdempotencyKeyRequiredError('payment-tokens create');\n }\n idempotencyKey = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => v.trim().length > 0 || 'Idempotency key is required',\n });\n }\n\n // --- Build request body ---\n const body: Record<string, unknown> = {\n type: serverType,\n payment_method_id: paymentMethodId,\n ...typeBody,\n };\n if (member) {\n body.member_id = member;\n }\n if (opts.externalTxId) {\n body.external_tx_id = opts.externalTxId as string;\n }\n\n const extraHeaders: Record<string, string> = {\n 'Idempotency-Key': idempotencyKey,\n };\n\n // --- POST /payment-tokens/create ---\n const result = await deps.apiClient.post<Record<string, unknown>>(\n '/payment-tokens/create',\n { type: 'api-key', key: apiKey },\n body,\n extraHeaders,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const tokenData = result.data;\n // Ensure type is on the top-level data for formatPaymentToken\n if (!tokenData.type) {\n tokenData.type = serverType;\n }\n\n // --- Output ---\n notify(format, 'success', 'Payment token created');\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<Record<string, unknown>> = {\n data: tokenData,\n text: () => {\n let output = formatPaymentToken(tokenData);\n // X402: append info message about X-PAYMENT header\n if (serverType === 'x402') {\n output += '\\n' + Formatter.status('info', 'Use the Signature Value in the X-PAYMENT request header');\n }\n return output;\n },\n };\n\n await renderWithContext(commandResult, { format }, configManager);\n });\n}\n\n// ============================================================\n// Type-branch helpers\n// ============================================================\n\n/**\n * VCN feature gate: GET /features/vcn — if disabled, throw TOKEN_FEATURE_DISABLED.\n */\nasync function checkVcnFeatureEnabled(apiClient: ApiClient, apiKey: string): Promise<void> {\n const result = await apiClient.get<{ enabled: boolean }>(\n '/features/vcn',\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n // If the endpoint fails, treat as feature disabled (conservative)\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n if (!result.data.enabled) {\n throw new CliError(\n 'TOKEN_FEATURE_DISABLED',\n 'VCN creation is not supported yet. Coming soon.',\n );\n }\n}\n\n/**\n * Fetch network-token fee from /config/network-token-fee.\n * Falls back to DEFAULT_NT_FEE_CENTS (500) if unreachable.\n */\nasync function fetchNetworkTokenFee(apiClient: ApiClient, apiKey: string): Promise<number> {\n try {\n const result = await apiClient.get<{ fee_cents: number }>(\n '/config/network-token-fee',\n { type: 'api-key', key: apiKey },\n );\n\n if (result.success && typeof result.data.fee_cents === 'number') {\n return result.data.fee_cents;\n }\n // Unreachable / unexpected shape → fallback\n return DEFAULT_NT_FEE_CENTS;\n } catch {\n // Network error / timeout → fallback\n return DEFAULT_NT_FEE_CENTS;\n }\n}\n","import { Command } from 'commander';\nimport {\n ApiClient,\n ConfigManager,\n PromptEngine,\n Formatter,\n resolveFormat,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\n\n// ============================================================\n// getSummary — per-type summary for table rendering (§3.4.2)\n// ============================================================\n\n/**\n * Render a one-line summary for a payment token in the list table.\n *\n * - vcn: `<first6>****<last4> $<limit/100>` (e.g. \"411111****1234 $25.00\")\n * - network_token: `<brand>` (e.g. \"Visa\")\n * - x402: `<amount> <network>` (e.g. \"1000000 Base\")\n */\nfunction getSummary(token: Record<string, unknown>): string {\n const type = token.type as string;\n\n if (type === 'vcn') {\n const first6 = String(token.first6 || token.first_six || '');\n const last4 = String(token.last4 || token.last_four || '');\n const limit = token.amount_limit as number | undefined ?? token.limit as number | undefined;\n const limitDisplay = limit !== undefined && limit !== null\n ? `$${(limit / 100).toFixed(2)}`\n : '';\n return `${first6}****${last4} ${limitDisplay}`.trim();\n }\n\n if (type === 'network_token') {\n const nt = token.network_token as Record<string, unknown> | undefined;\n return String(nt?.payment_brand || token.brand || '');\n }\n\n if (type === 'x402') {\n const amount = String(token.amount ?? '');\n const network = String(token.network || '');\n return `${amount} ${network}`.trim();\n }\n\n return '';\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `payment-tokens list` — list payment tokens (§3.4.2).\n *\n * GET /payment-tokens with X-Api-Key header.\n * Optional --type flag maps to ?type= query param.\n * Optional --member flag maps to ?member_id= query param.\n * Table headers: Token ID / Type / Status / Summary.\n * Empty list → `ℹ No payment tokens found` (no table).\n */\nexport function registerListCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('list')\n .description('List payment tokens')\n .option('--api-key <key>', 'API Key for authentication')\n .option('--type <type>', 'Filter by token type')\n .option('--member <member_id>', 'Filter by member ID');\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\n const params: Record<string, string> = {};\n if (opts.type) {\n params.type = opts.type as string;\n }\n if (opts.member) {\n params.member_id = opts.member as string;\n }\n\n const result = await deps.apiClient.get<Record<string, unknown>[]>(\n '/payment-tokens',\n { type: 'api-key', key: apiKey },\n Object.keys(params).length > 0 ? params : undefined,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const tokens = result.data;\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<{ payment_tokens: Record<string, unknown>[] }> = {\n data: { payment_tokens: tokens },\n text: () => {\n if (tokens.length === 0) {\n return Formatter.status('info', 'No payment tokens found');\n }\n const headers = ['Token ID', 'Type', 'Status', 'Summary'];\n const rows = tokens.map((t) => [\n String(t.id || ''),\n String(t.type || ''),\n String(t.status || ''),\n getSummary(t),\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 ApiClient,\n ConfigManager,\n Formatter,\n PromptEngine,\n resolveFormat,\n CliError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\n\n// ============================================================\n// Formatter — SEPARATE from create's `formatPaymentToken` (Property 7)\n// ============================================================\n\ninterface FormatPaymentTokenGetOptions {\n revealSensitive?: boolean;\n}\n\nfunction asString(value: unknown): string {\n return typeof value === 'string' ? value : '';\n}\n\nfunction maskPan(value: string, lastFour?: string): string {\n const suffix = lastFour || value.slice(-4);\n if (!suffix) return '';\n const maskedLength = Math.max(value.length - suffix.length, 4);\n return `${'*'.repeat(maskedLength)}${suffix}`;\n}\n\nfunction maskCvc(value: string): string {\n return value ? '***' : '';\n}\n\nfunction maskVcnFields(vcn: Record<string, unknown>): Record<string, unknown> {\n const masked = { ...vcn };\n const lastFour = asString(masked.last_four ?? masked.last4);\n\n if (typeof masked.card_number === 'string') {\n masked.card_number = maskPan(masked.card_number, lastFour);\n }\n if (typeof masked.pan === 'string') {\n masked.pan = maskPan(masked.pan, lastFour);\n }\n if (typeof masked.cvc === 'string') {\n masked.cvc = maskCvc(masked.cvc);\n }\n if (typeof masked.cvv === 'string') {\n masked.cvv = maskCvc(masked.cvv);\n }\n\n return masked;\n}\n\n/** Build the JSON payload for `payment-tokens get`, masking VCN secrets by default. */\nexport function buildPaymentTokenGetPayload(\n data: Record<string, unknown>,\n opts: FormatPaymentTokenGetOptions = {},\n): Record<string, unknown> {\n if (opts.revealSensitive || data.type !== 'vcn') {\n return data;\n }\n\n const payload = { ...data };\n if (payload.vcn && typeof payload.vcn === 'object') {\n payload.vcn = maskVcnFields(payload.vcn as Record<string, unknown>);\n return payload;\n }\n\n return maskVcnFields(payload);\n}\n\n/**\n * Format a payment token for the `get` command output (§3.4.3).\n *\n * CRITICAL: This MUST remain a standalone formatter — do NOT converge\n * with `formatPaymentToken` in create.ts. The differences are intentional\n * per design Property 7:\n *\n * - Top key: `Token ID` (create uses `Payment Token ID`)\n * - VCN: includes a `Last 4` line (create does not)\n * - VCN `Limit` / `Balance`: numeric values WITHOUT `$` prefix\n * (create uses `$` prefix for `Limit`)\n *\n * By default VCN PAN/CVC are masked. Use `--reveal` to intentionally print\n * full VCN credentials for a payment flow that needs to use them.\n */\nexport function formatPaymentTokenGet(\n data: Record<string, unknown>,\n opts: FormatPaymentTokenGetOptions = {},\n): string {\n const type = data.type as string;\n const lines: [string, string][] = [];\n\n if (type === 'vcn') {\n const vcn = (data.vcn as Record<string, unknown> | undefined) ?? data;\n const lastFour = asString(vcn.last_four ?? vcn.last4);\n const cardNumber = asString(vcn.card_number ?? vcn.pan);\n const cvc = asString(vcn.cvc ?? vcn.cvv);\n lines.push(['Token ID', String(data.id || vcn.id || '')]);\n lines.push(['Type', 'VCN']);\n lines.push([\n 'Card Number',\n opts.revealSensitive ? cardNumber : maskPan(cardNumber, lastFour),\n ]);\n lines.push(['Last 4', lastFour]);\n lines.push(['Expiry', String(vcn.expiry || '')]);\n lines.push(['CVC', opts.revealSensitive ? cvc : maskCvc(cvc)]);\n // Limit and Balance: numeric cents → USD string, NO `$` prefix\n lines.push(['Limit', formatCentsPlain(vcn.amount_limit as number)]);\n lines.push(['Balance', formatCentsPlain(vcn.balance as number)]);\n lines.push(['Currency', String(vcn.currency || 'USD')]);\n lines.push(['Status', String(vcn.status || data.status || '')]);\n } else if (type === 'network_token') {\n const nt = (data.network_token as Record<string, unknown> | undefined) ?? data;\n lines.push(['Token ID', String(data.id || nt.id || '')]);\n lines.push(['Type', 'Network Token']);\n lines.push(['Brand', String(nt.payment_brand || nt.brand || '')]);\n lines.push(['ECI', String(nt.eci || '')]);\n lines.push(['Cryptogram', String(nt.token_cryptogram || nt.cryptogram || '')]);\n lines.push(['Expiry', String(nt.expiry_date || nt.expiry || '')]);\n lines.push(['Value', String(nt.value || '')]);\n } else if (type === 'x402') {\n const x402 = (data.x402 as Record<string, unknown> | undefined) ?? data;\n lines.push(['Token ID', String(data.id || x402.id || '')]);\n lines.push(['Type', 'X402']);\n lines.push(['Signature Value', String(x402.signature_value || '')]);\n lines.push(['Status', String(x402.status || data.status || '')]);\n } else {\n // Unknown type: best-effort\n lines.push(['Token ID', String(data.id || '')]);\n lines.push(['Type', String(type || 'unknown')]);\n lines.push(['Status', String(data.status || '')]);\n }\n\n return Formatter.keyValue(lines);\n}\n\n/**\n * Format cents as plain USD string without `$` prefix (e.g. 1250 → \"12.50\").\n * This is the key difference from create's `formatCentsToUsd` which is used\n * with a `$` prefix in `Limit`.\n */\nfunction formatCentsPlain(cents: number | undefined | null): string {\n if (cents === undefined || cents === null) return '0.00';\n const dollars = Math.floor(cents / 100);\n const remainder = cents % 100;\n return `${dollars}.${String(remainder).padStart(2, '0')}`;\n}\n\n// ============================================================\n// Command registration\n// ============================================================\n\n/**\n * `payment-tokens get <payment_token_id>` — show a payment token (§3.4.3).\n *\n * Reads: GET /payment-tokens/<id> (X-Api-Key).\n * Output: keyValue with formatting that DIFFERS from create output (Property 7).\n */\nexport function registerGetCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('get <payment_token_id>')\n .description('Get a payment token by ID')\n .option('--api-key <key>', 'API key for authentication')\n .option('--reveal', 'Reveal full VCN card number and CVC in the output');\n\n cmd.action(async (paymentTokenId: string) => {\n const opts = cmd.optsWithGlobals();\n const format = resolveFormat(opts.format as string | undefined);\n\n // Resolve API key — prompt interactively if not provided via flag\n const apiKey = await PromptEngine.resolveInput(opts.apiKey as string | undefined, {\n message: 'API Key:',\n type: 'password',\n });\n\n // GET /payment-tokens/<id>\n const result = await deps.apiClient.get<Record<string, unknown>>(\n `/payment-tokens/${paymentTokenId}`,\n { type: 'api-key', key: apiKey },\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const revealSensitive = Boolean(opts.reveal);\n const tokenData = buildPaymentTokenGetPayload(result.data, { revealSensitive });\n\n const configManager = new ConfigManager();\n const commandResult: CommandResult<Record<string, unknown>> = {\n data: tokenData,\n text: () => formatPaymentTokenGet(result.data, { revealSensitive }),\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 IdempotencyKeyRequiredError,\n renderWithContext,\n} from '@agenzo/cli-core';\nimport type { CommandResult } from '@agenzo/cli-core';\nimport type { RevokeResult } from '../types/api.js';\n\n/**\n * `payment-tokens revoke <payment_token_id>` — revoke a payment token (§3.4.4).\n *\n * POST /payment-tokens/<id>/revoke (no body).\n * Two output states:\n * 1. Immediate revoke: `✓ Payment token revoked` + Token ID / Status / Revoked At\n * 2. Delayed revoke (X402, status==='ACTIVE' && expires_at non-null):\n * `✓ Revoke scheduled (cryptogram will auto-expire)` + Token ID / Status / Expires At (+message)\n *\n * Idempotency: --idempotency-key required in --yes mode (Requirement 6.3).\n */\nexport function registerRevokeCommand(parent: Command, deps: { apiClient: ApiClient }): void {\n const cmd = parent\n .command('revoke <payment_token_id>')\n .description('Revoke a payment token')\n .option('--api-key <key>', 'API key for authentication')\n .option(\n '--idempotency-key <key>',\n 'Idempotency key forwarded verbatim as the Idempotency-Key header',\n );\n\n cmd.action(async (paymentTokenId: string) => {\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 // Idempotency key handling (Requirement 6.3):\n // In --yes mode, --idempotency-key is mandatory — never auto-generate, never send request.\n // In interactive mode, prompt if not provided.\n let idempotencyKey = opts.idempotencyKey as string | undefined;\n if (!idempotencyKey) {\n if (opts.yes) {\n throw new IdempotencyKeyRequiredError('payment-tokens revoke');\n }\n idempotencyKey = await PromptEngine.resolveInput(undefined, {\n message: 'Idempotency key (unique per write, for safe retry):',\n validate: (v) => v.trim().length > 0 || 'Idempotency key is required',\n });\n }\n\n const extraHeaders: Record<string, string> = {\n 'Idempotency-Key': idempotencyKey,\n };\n\n const result = await deps.apiClient.post<RevokeResult>(\n `/payment-tokens/${paymentTokenId}/revoke`,\n { type: 'api-key', key: apiKey },\n undefined,\n extraHeaders,\n );\n\n if (!result.success) {\n throw CliError.fromApi(result, { auth: 'api-key' });\n }\n\n const data = result.data;\n\n // Determine output state:\n // Delayed revoke (X402): status is still ACTIVE and expires_at is present\n // Immediate revoke: all other cases\n const isDelayedRevoke = data.status === 'ACTIVE' && data.expires_at != null;\n\n if (isDelayedRevoke) {\n // Delayed revoke (X402 cryptogram will auto-expire)\n notify(format, 'success', 'Revoke scheduled (cryptogram will auto-expire)');\n\n const kvPairs: [string, string][] = [\n ['Token ID', data.id],\n ['Status', data.status],\n ['Expires At', Formatter.formatTime(data.expires_at)],\n ];\n if (data.message) {\n kvPairs.push(['Message', data.message]);\n }\n\n const cmdResult: CommandResult<RevokeResult> = {\n data,\n text: () => Formatter.keyValue(kvPairs),\n };\n\n const configManager = new ConfigManager();\n await renderWithContext(cmdResult, { format }, configManager);\n } else {\n // Immediate revoke\n notify(format, 'success', 'Payment token revoked');\n\n const cmdResult: CommandResult<RevokeResult> = {\n data,\n text: () =>\n Formatter.keyValue([\n ['Token ID', data.id],\n ['Status', data.status],\n ['Revoked At', Formatter.formatTime(data.revoked_at)],\n ]),\n };\n\n const configManager = new ConfigManager();\n await renderWithContext(cmdResult, { format }, configManager);\n }\n });\n}\n"],"mappings":"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","names":["readFile","writeFile","mkdir","chmod","join","homedir","join","homedir","mkdir","chmod","readFile","writeFile","password","password","select","select","cents","registerListCommand","registerGetCommand","registerListCommand","registerGetCommand"]}