@itpay/cli 0.2.11 → 0.2.13

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.
@@ -3,6 +3,7 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { execFileSync } from "node:child_process";
5
5
  import QRCode from "qrcode";
6
+ import { clientCommandArgs, clientHost, clientTarget } from "./client-context.js";
6
7
  import { apiTimeoutMs, cliCommand, commandExists, mergeRun, readRun, readState, safeErrorMessage, writeRun } from "./env.js";
7
8
 
8
9
  async function renderItPayPaymentAction(intent, flags = {}) {
@@ -423,6 +424,8 @@ function openclawTelegramMessage({ action = {}, media = [], links = [], buttons
423
424
  media: mediaURL || undefined,
424
425
  presentation,
425
426
  command_args: compactObject({
427
+ channel: "telegram",
428
+ target: clientTarget() || undefined,
426
429
  message: text,
427
430
  media: mediaURL || undefined,
428
431
  presentation
@@ -431,55 +434,6 @@ function openclawTelegramMessage({ action = {}, media = [], links = [], buttons
431
434
  });
432
435
  }
433
436
 
434
- function humanOutputFromRenderPlan(plan = {}) {
435
- if (!plan || typeof plan !== "object") return null;
436
- const selected = plan.selected || {};
437
- const platforms = plan.platforms || {};
438
- const base = {
439
- required: true,
440
- kind: plan.kind,
441
- proof_rule: plan.proof_rule,
442
- instruction: "Send this human_output to the human before running the next ItPay command."
443
- };
444
- if (selected.platform === "telegram") return { ...base, ...openclawHumanOutput(selected.openclaw_message) };
445
- if (selected.platform === "codex_app" || selected.platform === "claude_code") return { ...base, method: "markdown_reply", markdown: selected.markdown };
446
- if (selected.platform === "terminal") return { ...base, method: "terminal_display", print_terminal_qr: true, print_links: true };
447
- if (selected.platform && selected.platform !== "current_channel_required") return { ...base, ...plainChatHumanOutput(selected) };
448
- return {
449
- ...base,
450
- method: "current_channel_required",
451
- instruction: "Choose the branch matching the current chat platform, send it to the human, then stop until the human responds or clicks a platform button.",
452
- channels: compactObject({
453
- openclaw_telegram: openclawHumanOutput(platforms.telegram?.openclaw_message),
454
- codex_app: { method: "markdown_reply", markdown: platforms.codex_app?.markdown },
455
- claude_code: { method: "markdown_reply", markdown: platforms.claude_code?.markdown },
456
- plain_chat: plainChatHumanOutput(platforms.plain_chat),
457
- terminal: { method: "terminal_display", print_terminal_qr: true, print_links: true }
458
- })
459
- };
460
- }
461
-
462
- function openclawHumanOutput(message = {}) {
463
- if (!message) return null;
464
- return compactObject({
465
- method: "openclaw_message_send",
466
- channel: "telegram",
467
- message: message.command_args?.message || message.message,
468
- media: message.command_args?.media || message.media,
469
- presentation: message.command_args?.presentation || message.presentation,
470
- callbacks: message.callbacks
471
- });
472
- }
473
-
474
- function plainChatHumanOutput(plan = {}) {
475
- if (!plan) return null;
476
- return compactObject({
477
- method: "plain_chat_reply",
478
- text: plan.text,
479
- links: plan.links
480
- });
481
- }
482
-
483
437
  function openclawURLButton(text, url) {
484
438
  return compactObject({ text, url });
485
439
  }
@@ -490,15 +444,16 @@ function openclawCallbackButton(text, intent, action = {}) {
490
444
  }
491
445
 
492
446
  function openclawCallbackCommands(action = {}) {
447
+ const contextArgs = clientCommandArgs();
493
448
  if (action.kind === "payment_qr") {
494
449
  const id = action.payment_intent_id || action.id || "";
495
450
  return compactObject({
496
- refresh_payment_qr: id ? `itp buyer payment refresh-qr ${id} --json` : undefined,
497
- check_payment_status: id ? `itp buyer payment wait ${id} --timeout 1 --json` : undefined
451
+ refresh_payment_qr: id ? cliCommand("buyer", "payment", "refresh-qr", id, ...contextArgs, "--json") : undefined,
452
+ check_payment_status: id ? cliCommand("buyer", "payment", "wait", id, "--timeout", "1", ...contextArgs, "--json") : undefined
498
453
  });
499
454
  }
500
455
  if (action.checkout_id) {
501
- return { check_checkout_status: `itp buyer checkout resume ${action.checkout_id} --json` };
456
+ return { check_checkout_status: cliCommand("buyer", "checkout", "resume", action.checkout_id, ...contextArgs, "--json") };
502
457
  }
503
458
  return undefined;
504
459
  }
@@ -526,14 +481,7 @@ function selectedRenderPlan(host = "", platforms = {}) {
526
481
  if (selectedPlatform && platforms[selectedPlatform]) {
527
482
  return { platform: selectedPlatform, ...platforms[selectedPlatform] };
528
483
  }
529
- return compactObject({
530
- platform: "current_channel_required",
531
- rule: "Use render_plan.platforms.<current channel> when available; fallback is only for unsupported plain chat clients.",
532
- telegram: platforms.telegram,
533
- codex_app: platforms.codex_app,
534
- claude_code: platforms.claude_code,
535
- fallback: platforms.plain_chat
536
- });
484
+ return { platform: "plain_chat", ...platforms.plain_chat };
537
485
  }
538
486
 
539
487
  function compactObject(value = {}) {
@@ -641,20 +589,7 @@ function shouldReturnAfterAgentTextQR(flags = {}) {
641
589
  }
642
590
 
643
591
  function agentHost(flags = {}) {
644
- const explicit = String(
645
- process.env.ITP_HOST ||
646
- flags.host ||
647
- flags.channel ||
648
- process.env.OPENCLAW_CURRENT_CHANNEL_PROVIDER ||
649
- process.env.OPENCLAW_CHANNEL ||
650
- process.env.CURRENT_CHANNEL_PROVIDER ||
651
- process.env.AGENT_CHANNEL ||
652
- ""
653
- ).toLowerCase();
654
- if (explicit) return explicit;
655
- if (process.env.CODEX_THREAD_ID || process.env.CODEX_SHELL || process.env.CODEX_CI) return "codex";
656
- if (process.env.CLAUDECODE || process.env.CLAUDE_CODE || process.env.CLAUDECODE_SESSION_ID) return "claude-code";
657
- return "";
592
+ return clientHost(flags);
658
593
  }
659
594
 
660
595
  function agentTextQRHosts() {
@@ -780,4 +715,4 @@ function openBrowser(targetURL) {
780
715
  return false;
781
716
  }
782
717
 
783
- export { renderItPayPaymentAction, humanActionSummaryLines, writeHumanActionSummary, waitHeartbeatMs, writeWaitHeartbeat, renderHumanAction, buildHumanActionRenderPlan, humanOutputFromRenderPlan, preferredHumanActionQRURL, humanActionPresentationURL, annotateHumanActionPresentation, shouldPrepareLocalQRForJSON, shouldGenerateLocalQRFromActionURL, prepareLocalQRFile, prepareLocalQRFromActionURL, defaultQRFilePath, defaultGeneratedQRFilePath, qrFileExtension, qrMimeType, sanitizeFilename, formatActionTime, shouldUseAgentTextQR, shouldReturnAfterAgentTextQR, attachAgentQRImage, attachAgentLocalQR, downloadQRImage, persistHumanAction, shouldRenderTerminalQR, terminalQRType, shouldOpenBrowser, openBrowser };
718
+ export { renderItPayPaymentAction, humanActionSummaryLines, writeHumanActionSummary, waitHeartbeatMs, writeWaitHeartbeat, renderHumanAction, buildHumanActionRenderPlan, preferredHumanActionQRURL, humanActionPresentationURL, annotateHumanActionPresentation, shouldPrepareLocalQRForJSON, shouldGenerateLocalQRFromActionURL, prepareLocalQRFile, prepareLocalQRFromActionURL, defaultQRFilePath, defaultGeneratedQRFilePath, qrFileExtension, qrMimeType, sanitizeFilename, formatActionTime, shouldUseAgentTextQR, shouldReturnAfterAgentTextQR, attachAgentQRImage, attachAgentLocalQR, downloadQRImage, persistHumanAction, shouldRenderTerminalQR, terminalQRType, shouldOpenBrowser, openBrowser };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itpay/cli",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "description": "ItPay CLI, buyer skill, and agent-readable docs for agent-native commerce.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,10 +20,27 @@ protocol from this file. Use the CLI docs graph whenever you need details.
20
20
 
21
21
  ## Start Here
22
22
 
23
+ Every non-doc ItPay command must include the current client context. The CLI
24
+ will stop with `client_context_required` or `client_target_required` rather
25
+ than guess.
26
+
27
+ ```text
28
+ Codex app: --host codex
29
+ Claude Code app: --host claude-code
30
+ Terminal: --host terminal
31
+ Plain chat: --host plain-chat
32
+ OpenClaw Telegram private/group chat: --host telegram --target <inbound_meta.chat_id>
33
+ ```
34
+
35
+ For Telegram groups or @mention flows, use the same OpenClaw inbound
36
+ `chat_id` as the target, for example `--target telegram:-1001234567890`.
37
+ OpenClaw owns group allowlists and mention policy; ItPay only echoes the target
38
+ into `openclaw message send`.
39
+
23
40
  Run these commands before buying:
24
41
 
25
42
  ```bash
26
- itp status --refresh --json
43
+ itp status --refresh --host <client> --json
27
44
  itp docs show quickstart --role buyer --json
28
45
  itp docs list --role buyer --json
29
46
  ```
@@ -59,41 +76,41 @@ read this skill
59
76
  The high-level command can wrap this flow:
60
77
 
61
78
  ```bash
62
- itp buy <variant_id> --email <buyer_email> --phone <buyer_phone> --display agent --no-wait-payment --json
79
+ itp buy <variant_id> --email <buyer_email> --phone <buyer_phone> --display agent --no-wait-payment --host <client> --json
63
80
  ```
64
81
 
65
82
  For step-by-step testing:
66
83
 
67
84
  ```bash
68
- itp buyer catalog search --query "<user request>" --json
69
- itp buyer catalog search --query "企业工商信息 查询" --category business_data_api --provider itpay_enterprise_data --service-type ai_api --json
70
- itp buyer catalog get --variant <variant_id> --json
71
- itp buyer cart create --variant <variant_id> --json
72
- itp buyer cart create --variants <variant_id_1>,<variant_id_2> --quantities 1,1 --json
73
- itp buyer cart show <cart_id> --json
74
- itp buyer cart add <cart_id> --variant <variant_id> --input key=value --quantity 1 --json
75
- itp buyer cart remove <cart_id> --line <cart_line_item_id> --json
76
- itp buyer checkout create --cart <cart_id> --email <buyer_email> --phone <buyer_phone> --json
77
- itp buyer checkout resume <checkout_id> --json
78
- itp buyer payment wait <payment_intent_id> --timeout 1 --json
79
- itp buyer checkout status <checkout_id> --json
80
- itp buyer refund create --order <order_id> --amount-minor <minor_units> --currency CNY --reason buyer_requested --json
81
- itp buyer refund list --order <order_id> --json
82
- itp buyer refund show <refund_id> --json
83
- itp buyer refund cancel <refund_id> --reason buyer_changed_mind --json
84
- itp buyer vault grants list --checkout <checkout_id> --json
85
- itp buyer vault read --order <order_id> --artifact <vault_artifact_id> --json
85
+ itp buyer catalog search --query "<user request>" --host <client> --json
86
+ itp buyer catalog search --query "企业工商信息 查询" --category business_data_api --provider itpay_enterprise_data --service-type ai_api --host <client> --json
87
+ itp buyer catalog get --variant <variant_id> --host <client> --json
88
+ itp buyer cart create --variant <variant_id> --host <client> --json
89
+ itp buyer cart create --variants <variant_id_1>,<variant_id_2> --quantities 1,1 --host <client> --json
90
+ itp buyer cart show <cart_id> --host <client> --json
91
+ itp buyer cart add <cart_id> --variant <variant_id> --input key=value --quantity 1 --host <client> --json
92
+ itp buyer cart remove <cart_id> --line <cart_line_item_id> --host <client> --json
93
+ itp buyer checkout create --cart <cart_id> --email <buyer_email> --phone <buyer_phone> --host <client> --json
94
+ itp buyer checkout resume <checkout_id> --host <client> --json
95
+ itp buyer payment wait <payment_intent_id> --timeout 1 --host <client> --json
96
+ itp buyer checkout status <checkout_id> --host <client> --json
97
+ itp buyer refund create --order <order_id> --amount-minor <minor_units> --currency CNY --reason buyer_requested --host <client> --json
98
+ itp buyer refund list --order <order_id> --host <client> --json
99
+ itp buyer refund show <refund_id> --host <client> --json
100
+ itp buyer refund cancel <refund_id> --reason buyer_changed_mind --host <client> --json
101
+ itp buyer vault grants list --checkout <checkout_id> --host <client> --json
102
+ itp buyer vault read --order <order_id> --artifact <vault_artifact_id> --host <client> --json
86
103
  ```
87
104
 
88
105
  For API products, read the product metadata input schema before cart creation.
89
106
  Enterprise data products require query input at cart time:
90
107
 
91
108
  ```bash
92
- itp buyer cart create --variant var_itpay_enterprise_fuzzy_search_cny01 --input company_name=京东 --json
93
- itp buyer cart show <cart_id> --json
94
- itp buyer cart add <cart_id> --variant var_itpay_enterprise_fuzzy_search_cny01 --input company_name=美团 --json
95
- itp buyer cart create --variant var_itpay_enterprise_precise_lookup_cny05 --input company_name_or_credit_no=北京京东世纪贸易有限公司 --json
96
- itp buy var_itpay_enterprise_fuzzy_search_cny01 --email <buyer_email> --input company_name=京东 --display agent --no-wait-payment --json
109
+ itp buyer cart create --variant var_itpay_enterprise_fuzzy_search_cny01 --input company_name=京东 --host <client> --json
110
+ itp buyer cart show <cart_id> --host <client> --json
111
+ itp buyer cart add <cart_id> --variant var_itpay_enterprise_fuzzy_search_cny01 --input company_name=美团 --host <client> --json
112
+ itp buyer cart create --variant var_itpay_enterprise_precise_lookup_cny05 --input company_name_or_credit_no=北京京东世纪贸易有限公司 --host <client> --json
113
+ itp buy var_itpay_enterprise_fuzzy_search_cny01 --email <buyer_email> --input company_name=京东 --display agent --no-wait-payment --host <client> --json
97
114
  ```
98
115
 
99
116
  For cart edits, always read the server cart first with `buyer cart show`.
@@ -112,19 +129,19 @@ Refund commands use ItPay shared order state. If `itp buyer refund create`
112
129
  returns `policy_risk_confirmation_required`, explain the returned
113
130
  `refund_eligibility.policy` and `agent_guidance` to the human first. Only retry
114
131
  with `--confirm-policy-risk true` after explicit human confirmation.
115
- Do not guess `order_id`; if missing, run `buyer checkout status <checkout_id> --json`.
132
+ Do not guess `order_id`; if missing, run `buyer checkout status <checkout_id> --host <client> --json`.
116
133
  Refund amounts use minor units: CNY 1000 means CNY 10.00.
117
134
  Refund commands require a server-verified buyer session, not a vault grant. If
118
135
  the CLI says the buyer session is required or expired, run
119
- `itp status --refresh --json` and follow the returned `next.command`.
136
+ `itp status --refresh --host <client> --json` and follow the returned `next.command`.
120
137
  Current buyer refunds are whole-order only; do not use line-item refund scope.
121
138
  If the human cancels a refund before provider or money movement starts, use
122
- `buyer refund cancel <refund_id> --json`; after cancel, the delivery claim can
139
+ `buyer refund cancel <refund_id> --host <client> --json`; after cancel, the delivery claim can
123
140
  be unlocked again by the ItPay backend.
124
141
 
125
142
  ## Non-Negotiable Rules
126
143
 
127
- 1. Use `--json` for every ItPay command.
144
+ 1. Use `--json` and current client context for every non-doc ItPay command. Use `--host codex`, `--host claude-code`, `--host terminal`, `--host plain-chat`, or for OpenClaw Telegram use `--host telegram --target <inbound_meta.chat_id>`.
128
145
  2. Do not invent service IDs, variant IDs, checkout IDs, payment URLs, QR URLs,
129
146
  payment intent IDs, delivery IDs, or claim links.
130
147
  3. When the user asks for several compatible services, use one cart and one
@@ -206,18 +223,19 @@ Each docs page includes `next_docs`. Follow those links as the state changes.
206
223
  For payment creation in an agent/chat client, prefer:
207
224
 
208
225
  ```bash
209
- itp buy <variant_id> --email <buyer_email> --phone <buyer_phone> --display agent --no-wait-payment --json
226
+ itp buy <variant_id> --email <buyer_email> --phone <buyer_phone> --display agent --no-wait-payment --host <client> --json
210
227
  ```
211
228
 
212
229
  This keeps JSON output machine-readable while allowing the CLI to prepare a
213
230
  local QR image path for clients that cannot render remote SVG reliably. In
214
- agent/chat clients, prefer `--no-wait-payment`: if `human_output_required=true`,
215
- send root `human_output` before any next ItPay command. In Codex or Claude Code
216
- app clients, send `human_output.markdown` exactly. In OpenClaw Telegram, pass
217
- `human_output.message/media/presentation` to `openclaw message send` so media
218
- and native `text/url/callback_data` buttons are sent through the adapter.
219
- `render_plan` is diagnostic/compatibility detail. Do not invent a table or
220
- rewrite the UI plan.
231
+ agent/chat clients, prefer `--no-wait-payment`. In OpenClaw Telegram, if
232
+ `agent_instruction` is present, call `openclaw message send` with
233
+ `agent_instruction.openclaw_message.command_args`. The `target` field is the
234
+ OpenClaw chat target, `media` is the QR image, `message` is the exact human text, and
235
+ `presentation.blocks[].type="buttons"` creates Telegram native inline buttons.
236
+ Do not rewrite it as a table or normal prose. In Codex or Claude Code app
237
+ clients, send `agent_instruction.markdown` exactly before any next ItPay
238
+ command.
221
239
 
222
240
  If a response has `status=payment_handoff_required`, `next` is the user-visible
223
241
  reply step, not payment wait. Do not run `buyer payment wait` until the human