@itpay/cli 2.0.0 → 2.0.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/README.md CHANGED
@@ -8,7 +8,7 @@ itpay readyz
8
8
  itpay docs show quickstart
9
9
  ```
10
10
 
11
- This test release defaults to `https://test.itpay.ai`. Set
11
+ The CLI defaults to the production API at `https://api.itpay.ai`. Set
12
12
  `ITPAY_BACKEND_URL` only when intentionally using another backend.
13
13
 
14
14
  ## Commands
@@ -28,7 +28,7 @@ This test release defaults to `https://test.itpay.ai`. Set
28
28
  - `itpay services start <service_id>` — start a generic Service Execution run
29
29
  - `itpay services invoke <service_execution_id> --capability <capability_id> --input key=value` — invoke an agent-visible capability
30
30
  - `itpay services action <service_execution_id> --action <action_type> [--result-item <id>]` — record a human/agent service action
31
- - `itpay services checkout <service_execution_id> --capability <capability_id> --email <email> [--host <host>] [--json]` — create quote lock from Service Execution state, bind it to the server cart item when present, persist the handoff, and render the branded ItPay checkout
31
+ - `itpay services checkout <service_execution_id> --capability <capability_id> [--email <email>] [--host <host>] [--json]` — create quote lock from Service Execution state, require email only for capabilities that deliver a claim link, persist the handoff, and render the branded ItPay checkout
32
32
  - `itpay services checkout <service_execution_id> --resume --json` — reissue a lost or expired handoff for the same unpaid checkout without asking for contact information again
33
33
  - `itpay services next <service_execution_id> [--json]` — show the next recommended action from the Service Execution read model
34
34
  - `itpay services get <service_execution_id>` / `itpay services events <service_execution_id>` — read the redacted Service Execution timeline
@@ -54,7 +54,7 @@ Aliases: `tg` and `openclaw-telegram` map to `telegram`; `feishu_im` and `fs` ma
54
54
 
55
55
  ## Environment
56
56
 
57
- - `ITPAY_BACKEND_URL` — optional backend override (test-release default `https://test.itpay.ai`)
57
+ - `ITPAY_BACKEND_URL` — optional backend override (default `https://api.itpay.ai`)
58
58
  - `ITPAY_BEARER_TOKEN` — account-scoped session token (only needed for `orders`)
59
59
  - `ITPAY_AGENT_DEVICE_ID` — agent device id, used for cart/service execution quota identity and `client_context`
60
60
  - `ITPAY_CURRENCY` — checkout currency (default `CNY`)
@@ -1,4 +1,3 @@
1
- import { formatMoney } from "../render/output.js";
2
1
  import { resolveOutput } from "../render/sink.js";
3
2
  export async function runCatalogList(backend, options = {}) {
4
3
  const manifest = await backend.getCatalogManifest();
@@ -8,19 +7,46 @@ export async function runCatalogList(backend, options = {}) {
8
7
  out(JSON.stringify(manifest, null, 2) + "\n");
9
8
  return;
10
9
  }
11
- out(`Catalog: ${manifest.version} (${manifest.status}, ${items.length} items)\n\n`);
10
+ out(`ItPay 当前上线 ${items.length} 个服务(目录版本 ${manifest.version})\n\n`);
12
11
  for (const item of items) {
13
- out(` ${item.catalog_item_id}\n`);
14
- out(` title: ${item.title}\n`);
15
- out(` provider: ${item.provider} | type: ${item.service_type} | category: ${item.category}\n`);
12
+ out(` ${item.title}\n`);
13
+ if (item.description)
14
+ out(` ${item.description}\n`);
15
+ if (item.service_flow) {
16
+ const discovery = item.service_flow.discovery;
17
+ const primary = item.service_flow.primary_service;
18
+ out(`\n 先做什么:${discovery.title}\n`);
19
+ out(` ${discovery.description}\n`);
20
+ if (discovery.free_quota_limit !== undefined) {
21
+ out(` 每台已登记设备可免费使用 ${discovery.free_quota_limit} 次。\n`);
22
+ }
23
+ if (discovery.paid_continuation) {
24
+ const continuation = discovery.paid_continuation;
25
+ out(` 免费次数用完后:${formatProductMoney(continuation.amount_minor, continuation.currency)}/次,继续使用该辅助步骤;结果直接返回给 agent${continuation.delivery_email_required ? ",需要用户提供收件邮箱" : ",不需要邮箱"}。\n`);
26
+ }
27
+ out(`\n 确认主体后:${primary.title},${formatProductMoney(primary.amount_minor, primary.currency)}/次\n`);
28
+ out(` ${primary.description}\n`);
29
+ if (primary.delivery_description)
30
+ out(` ${primary.delivery_description}\n`);
31
+ }
32
+ out(`\n 服务 ID:${item.service_id ?? "未发布"}`);
16
33
  if (item.service_id)
17
- out(` service: ${item.service_id} (use: itpay services start ${item.service_id})\n`);
34
+ out(`(启动:itpay services start ${item.service_id})`);
35
+ out("\n");
18
36
  if (item.variants.length > 0) {
19
- out(` variants:\n`);
37
+ out(` 可购买项目:\n`);
20
38
  for (const variant of item.variants) {
21
- out(` - ${variant.catalog_variant_id} ${variant.title} ${variant.offer_id} ${formatMoney(variant.amount_minor, variant.currency)}\n`);
39
+ out(` - ${variant.catalog_variant_id} ${variant.title} ${variant.offer_id} ${formatProductMoney(variant.amount_minor, variant.currency)}\n`);
22
40
  }
23
41
  }
24
42
  out("\n");
25
43
  }
26
44
  }
45
+ function formatProductMoney(amountMinor, currency) {
46
+ return new Intl.NumberFormat("zh-CN", {
47
+ style: "currency",
48
+ currency,
49
+ minimumFractionDigits: 2,
50
+ maximumFractionDigits: 2,
51
+ }).format(amountMinor / 100);
52
+ }
@@ -106,9 +106,10 @@ export function buildServiceReadModelGuidance(model) {
106
106
  deliveryBindings: model.delivery_bindings,
107
107
  });
108
108
  }
109
- export function buildServiceInvokedGuidance(response) {
109
+ export function buildServiceInvokedGuidance(response, capabilities = []) {
110
110
  return buildServiceGuidance({
111
111
  execution: response.execution,
112
+ capabilities,
112
113
  resultItems: response.result_items,
113
114
  ...(response.next_actions ? { backendNextActions: response.next_actions } : {}),
114
115
  ...(response.effective_quota ? { effectiveQuota: response.effective_quota } : {}),
@@ -155,9 +156,9 @@ export function buildServiceHandleGuidance(serviceExecutionID, checkoutCapabilit
155
156
  actions.push({
156
157
  id: "checkout_service",
157
158
  label: "Create checkout after human confirmation",
158
- command: `itpay services checkout ${serviceExecutionID} --capability ${checkoutCapabilityID} --email <email> --json`,
159
+ command: `itpay services checkout ${serviceExecutionID} --capability ${checkoutCapabilityID} --json`,
159
160
  requires_human: true,
160
- reason: "Only use after the service contract has the required human confirmation or quote lock.",
161
+ reason: "Inspect the Service Execution first; the CLI will request delivery contact only when the selected capability requires it.",
161
162
  });
162
163
  }
163
164
  return {
@@ -306,12 +307,16 @@ function buildServiceGuidance(input) {
306
307
  else if (execution.checkout_required || execution.next_action === "create_checkout") {
307
308
  const capabilityID = backendCheckout?.capability_id ?? paid?.capability_id ?? input.checkoutCapabilityID ?? execution.current_capability_id;
308
309
  if (capabilityID) {
310
+ const checkoutCapability = capabilities.find((capability) => capability.capability_id === capabilityID);
311
+ const emailRequired = checkoutCapability?.delivery_email_required === true;
309
312
  nextActions.push({
310
313
  id: "checkout_service",
311
314
  label: "Create ItPay checkout for the paid service capability",
312
- command: `itpay services checkout ${execution.service_execution_id} --capability ${capabilityID} --email <email> --json`,
315
+ command: `itpay services checkout ${execution.service_execution_id} --capability ${capabilityID}${emailRequired ? " --email <email>" : ""} --json`,
313
316
  requires_human: true,
314
- reason: "The human must provide delivery contact and pay on the ItPay checkout page.",
317
+ reason: emailRequired
318
+ ? "Ask the human for their email. It is used to send the protected result claim link; never invent or substitute an address."
319
+ : "This capability returns an agent-visible result after payment and does not require a delivery email.",
315
320
  });
316
321
  }
317
322
  else {
@@ -384,6 +389,10 @@ function buildServiceGuidance(input) {
384
389
  capability_id: capability.capability_id,
385
390
  agent_visible: capability.agent_visible,
386
391
  requires_payment: capability.requires_payment,
392
+ vault_required: capability.vault_required,
393
+ delivery_email_required: capability.delivery_email_required,
394
+ price_amount_minor: capability.price_amount_minor,
395
+ price_currency: capability.price_currency,
387
396
  free_quota_limit: capability.free_quota_limit,
388
397
  })),
389
398
  result_items: (input.resultItems ?? []).map((item) => ({
@@ -27,7 +27,17 @@ export async function runServicesInvoke(backend, config, serviceExecutionID, cap
27
27
  idempotency_key: idempotencyKey,
28
28
  redacted_summary: input,
29
29
  });
30
- const guidance = buildServiceInvokedGuidance(response);
30
+ let capabilities = [];
31
+ if (response.next_actions?.some((action) => action.kind === "create_checkout")) {
32
+ try {
33
+ capabilities = (await backend.getServiceExecution(serviceExecutionID)).capabilities;
34
+ }
35
+ catch {
36
+ // Preserve the successful invocation response. Checkout performs the same
37
+ // capability-aware email validation before creating a handoff.
38
+ }
39
+ }
40
+ const guidance = buildServiceInvokedGuidance(response, capabilities);
31
41
  if (options.jsonOutput) {
32
42
  writeJSON(options.output, attachAgentGuidance(response, guidance));
33
43
  return;
package/dist/src/main.js CHANGED
@@ -24,7 +24,7 @@ program
24
24
  .name("itpay")
25
25
  .description("V3 ItPay CLI — checkout, payment, order, and refund commands")
26
26
  .option("--agent-type <type>", "agent runtime type used for device enrollment and client-specific guidance")
27
- .version("2.0.0");
27
+ .version("2.0.2");
28
28
  function withHost(value) {
29
29
  const host = normalizeHost(value);
30
30
  if (!host) {
@@ -8,8 +8,8 @@ import { HttpClient } from "../client/http.js";
8
8
  import { BackendClient } from "../client/backend.js";
9
9
  import { DeviceAuthority } from "./device_authority.js";
10
10
  import { OperationJournal } from "./operation_journal.js";
11
- export const DEFAULT_BASE_URL = "https://test.itpay.ai";
12
- export const CLI_VERSION = "2.0.0";
11
+ export const DEFAULT_BASE_URL = "https://api.itpay.ai";
12
+ export const CLI_VERSION = "2.0.2";
13
13
  export const API_CONTRACT_REVISION = "sha256:2c2829f4618c47bc505efc0ded853cf639d775585ba13aa23012197e39efa31f";
14
14
  const CART_SESSION_DEFAULT_DIR = ".itpay-v3";
15
15
  const CART_SESSION_FILENAME = "cart.json";
@@ -58,7 +58,7 @@
58
58
  },
59
59
  {
60
60
  "intent": "create quote lock and checkout for a service-backed cart item",
61
- "command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> --email <email> --json",
61
+ "command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> [--email <email>] --json",
62
62
  "success_signal": "the quote lock is bound to the original server cart item when present; JSON includes checkout_id and display_token"
63
63
  },
64
64
  {
@@ -76,6 +76,7 @@
76
76
  "Do not remove quote-locked or checkout-bound cart lines. Continue checkout/payment or use refund/cancel owner flow after payment.",
77
77
  "If required contact data is missing, prefer --require-contact so the CLI can emit a structured interaction request.",
78
78
  "Do not invent buyer email or phone values; let the human provide them when required.",
79
+ "Only request --email when the selected capability declares delivery_email_required. Tell the buyer it sends the protected result claim link.",
79
80
  "The happy-path buy flow creates cart and checkout, then renders checkout_qr. It should not create a payment intent first."
80
81
  ],
81
82
  "forbidden": [
@@ -17,14 +17,16 @@
17
17
  }
18
18
  ],
19
19
  "output_interpretation": {
20
- "item_format": "Each item shows catalog_item_id, title, provider, service_type, category, and a list of variants with catalog_variant_id, offer_id, title, amount, currency.",
20
+ "item_format": "Each item includes product description, a structured service_flow, valid IDs, and purchasable offers.",
21
+ "service_flow": "Explain discovery as an auxiliary identity-confirmation step, including free quota and paid continuation. Present primary_service as the actual paid outcome. Read all values from the manifest.",
21
22
  "variant_selection": "To buy, the buyer needs catalog_item_id, catalog_variant_id, and offer_id from the output.",
22
23
  "price_note": "amount_minor is in minor units (e.g., 10000 = 100.00 CNY). The CLI formats prices as XX.YY currency automatically."
23
24
  },
24
25
  "agent_rules": [
25
26
  "Use `itpay catalog list` before suggesting purchase options.",
26
27
  "Read the variant IDs and prices from the output; do not invent them.",
27
- "Present options to the buyer in a readable table or list format.",
28
+ "Explain the customer journey from service_flow instead of presenting every variant as an unrelated service.",
29
+ "State free quota, paid continuation price, email requirement, and claim purpose exactly as published; do not exaggerate or omit conditions.",
28
30
  "If the buyer wants to search by keyword, filter the catalog output client-side (no backend search yet)."
29
31
  ],
30
32
  "next_docs": [
@@ -29,7 +29,7 @@
29
29
  "env_vars": {
30
30
  "ITPAY_BACKEND_URL": {
31
31
  "required": false,
32
- "description": "Optional V3 backend override. This test release defaults to https://test.itpay.ai.",
32
+ "description": "Optional V3 backend override. The CLI defaults to https://api.itpay.ai.",
33
33
  "examples": ["http://localhost:18080", "https://test.itpay.ai"]
34
34
  },
35
35
  "ITPAY_BEARER_TOKEN": {
@@ -63,7 +63,7 @@
63
63
  "lark": "Use --host lark --target <open_id>. Same as feishu format."
64
64
  },
65
65
  "agent_rules": [
66
- "Use the built-in https://test.itpay.ai test-release default; override ITPAY_BACKEND_URL only for another deliberate environment.",
66
+ "Use the built-in https://api.itpay.ai production default; override ITPAY_BACKEND_URL only for another deliberate environment.",
67
67
  "Install globally with npm install -g @itpay/cli for all hosts.",
68
68
  "Identify the real runtime with --agent-type or ITPAY_AGENT_TYPE; do not invent a new type to obtain quota.",
69
69
  "Run `itpay install` without arguments to see all supported targets.",
@@ -17,12 +17,12 @@
17
17
  },
18
18
  {
19
19
  "intent": "create service-execution quote lock and render ItPay checkout page handoff",
20
- "command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> --email <email>",
20
+ "command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> [--email <email>]",
21
21
  "success_signal": "The quote lock is bound to the original server cart item when present; ItPay checkout QR/URL is rendered for the human; the checkout page handles authorization and provider payment."
22
22
  },
23
23
  {
24
24
  "intent": "create service-execution checkout with machine-readable handoff",
25
- "command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> --email <email> --json",
25
+ "command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> [--email <email>] --json",
26
26
  "success_signal": "JSON with kind='checkout_handoff_required', next_action='open_human_checkout', checkout_url, display_token, qr_png_url, and brand_qr_local_path."
27
27
  },
28
28
  {
@@ -12,7 +12,7 @@
12
12
  "required_state": {
13
13
  "needs": [
14
14
  "itpay CLI installed",
15
- "test-release API at https://test.itpay.ai, or an intentional ITPAY_BACKEND_URL override",
15
+ "production API at https://api.itpay.ai, or an intentional ITPAY_BACKEND_URL override",
16
16
  "catalog item id, variant id, and offer id from `itpay catalog list`",
17
17
  "real agent runtime type supplied through --agent-type or ITPAY_AGENT_TYPE"
18
18
  ],
@@ -80,7 +80,7 @@
80
80
  },
81
81
  {
82
82
  "intent": "create checkout from a confirmed service execution and render human handoff",
83
- "command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> --email <email> --json",
83
+ "command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> [--email <email>] --json",
84
84
  "success_signal": "quote lock is bound to the server cart item when present; JSON includes checkout_id, display_token, checkout_url, qr_png_url, and brand_qr_local_path"
85
85
  },
86
86
  {
@@ -134,6 +134,7 @@
134
134
  "For service-backed catalog items, read service_execution_id from `itpay cart add --json` before invoking service capabilities.",
135
135
  "Do not use --pay or itpay pay for the normal buyer flow; first show the ItPay checkout QR/URL so the human enters the checkout page.",
136
136
  "If buy emits an interaction request for missing contact fields, collect values and rerun with --contact-email/--contact-phone.",
137
+ "For services checkout, include --email only when next_actions includes it. Explain that protected delivery uses it to send the claim link; agent-visible paid results do not require email.",
137
138
  "Do not assume checkout implies payment succeeded; it only creates a handoff.",
138
139
  "Payment success is confirmed by backend checkout/order state, not by QR display or buyer claim.",
139
140
  "A human grant applies only to its service execution and expires after 15 minutes; do not claim access to other orders or executions.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itpay/cli",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "ItPay CLI for V3 checkout, payment, order, refund, and agent-facing render flows.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,7 +20,7 @@ itpay readyz
20
20
  itpay docs show quickstart
21
21
  ```
22
22
 
23
- This test release defaults to `https://test.itpay.ai`. Set `ITPAY_BACKEND_URL`
23
+ The CLI defaults to `https://api.itpay.ai`. Set `ITPAY_BACKEND_URL`
24
24
  only for an intentional override.
25
25
 
26
26
  Every commerce flow must identify the real runtime. Pass the global option
@@ -59,9 +59,13 @@ the checkout with the exact server-selected capability:
59
59
 
60
60
  ```bash
61
61
  itpay --agent-type <agent_type> services checkout <service_execution_id> \
62
- --capability <capability_id> --email <human_email> --host <host> --json
62
+ --capability <capability_id> [--email <human_email>] --host <host> --json
63
63
  ```
64
64
 
65
+ Include `--email` only when the CLI's `next_actions` command includes it. For a
66
+ protected delivery, explain that the address receives the order claim link;
67
+ never invent an address. Agent-visible paid results do not require email.
68
+
65
69
  5. Show both handoff forms to the human:
66
70
 
67
71
  - Attach `brand_qr_local_path` when `brand_qr_status` is `downloaded`.