@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.
- package/README.md +27 -21
- package/bin/itp +38 -32
- package/docs/agent/buyer/account-portal.json +22 -6
- package/docs/agent/buyer/cart-checkout.json +9 -9
- package/docs/agent/buyer/catalog-search.json +35 -8
- package/docs/agent/buyer/human-claim-ui.json +20 -6
- package/docs/agent/buyer/payment-qr.json +11 -9
- package/docs/agent/buyer/payment-wait.json +5 -4
- package/docs/agent/buyer/product-recommendation.json +1 -1
- package/docs/agent/buyer/qr-refresh.json +18 -5
- package/docs/agent/buyer/quickstart.json +13 -9
- package/docs/agent/buyer/recovery.json +25 -6
- package/docs/agent/buyer/safety-policy.json +17 -3
- package/docs/agent/buyer/secure-delivery.json +24 -6
- package/docs/agent/buyer/vault-agent-read.json +29 -10
- package/lib/buyer.js +322 -63
- package/lib/client-context.js +126 -0
- package/lib/render-human.js +10 -75
- package/package.json +1 -1
- package/skills/itpay-buyer/SKILL.md +55 -37
package/lib/render-human.js
CHANGED
|
@@ -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 ?
|
|
497
|
-
check_payment_status: id ?
|
|
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:
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
@@ -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
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
`
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|