@itpay/cli 0.2.6 → 0.2.7
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
|
@@ -239,7 +239,8 @@ Payment QR rules:
|
|
|
239
239
|
- Otherwise render the ItPay-hosted `qr_png_url` / `preferred_qr_url`.
|
|
240
240
|
- Use `mobile_wallet_url` only as a human mobile fallback.
|
|
241
241
|
- Do not generate your own QR from payment URLs.
|
|
242
|
-
- In agent app clients,
|
|
242
|
+
- In agent app clients, execute `render_plan.selected` first. Send its media, text/markdown, real links, and native buttons when the adapter supports them.
|
|
243
|
+
- Do not rewrite `render_plan.selected` into a custom table or omit the real URL.
|
|
243
244
|
- If status is `payment_handoff_required`, `next` is the human reply step, not payment wait.
|
|
244
245
|
- Treat only `payment_intent.verified` as payment success.
|
|
245
246
|
|
|
@@ -11,8 +11,16 @@
|
|
|
11
11
|
"The human needs to scan with the payment provider."
|
|
12
12
|
],
|
|
13
13
|
"required_state": {
|
|
14
|
-
"needs": [
|
|
15
|
-
|
|
14
|
+
"needs": [
|
|
15
|
+
"payment_intent_id",
|
|
16
|
+
"human_action",
|
|
17
|
+
"qr_png_url/preferred_qr_url or local_qr_path"
|
|
18
|
+
],
|
|
19
|
+
"must_not_need": [
|
|
20
|
+
"raw provider QR",
|
|
21
|
+
"provider sign",
|
|
22
|
+
"ops token"
|
|
23
|
+
]
|
|
16
24
|
},
|
|
17
25
|
"commands": [
|
|
18
26
|
{
|
|
@@ -33,6 +41,10 @@
|
|
|
33
41
|
"Payment QR display requires both a valid/saved buyer session and payment_intent_id. If payment_intent_id appears before buyer_session is saved, run buyer checkout resume/status instead of showing payment QR.",
|
|
34
42
|
"Do not stop after showing auth_qr unless the human explicitly asks you to pause. Keep waiting/resuming the same checkout so the post-auth payment handoff can continue.",
|
|
35
43
|
"Do not describe auth_qr as payment success or payment proof. Only payment_intent.verified proves payment.",
|
|
44
|
+
"If response.render_plan.selected exists, treat it as the final UI render plan for the current host. Execute selected before reading other platform branches.",
|
|
45
|
+
"Do not rewrite response.render_plan.selected into a custom table. Use selected.text/markdown, selected.media, selected.links, and selected.buttons as provided.",
|
|
46
|
+
"If selected.links exists, include the real URL. Do not only show the link label.",
|
|
47
|
+
"If selected.buttons exists but the current adapter cannot render native buttons, degrade to selected.links plus short text; do not fake payment success or skip the status check.",
|
|
36
48
|
"In Codex or Claude Code app clients, send response.human_visible_markdown or response.render_plan.platforms.codex_app.markdown to the human first. Do not start a hidden long wait before the human-visible message is sent.",
|
|
37
49
|
"For Telegram-style message clients, use response.render_plan.platforms.telegram: send photo media first, include links, and expose native buttons for refresh/status when the adapter supports them.",
|
|
38
50
|
"For plain chat clients, show response.human_visible_markdown and stop unless the human asks you to check status or returns with a payment question.",
|
|
@@ -68,5 +80,14 @@
|
|
|
68
80
|
"command": "itp docs show qr-refresh --role buyer --json"
|
|
69
81
|
}
|
|
70
82
|
],
|
|
71
|
-
"search_terms": [
|
|
83
|
+
"search_terms": [
|
|
84
|
+
"qr",
|
|
85
|
+
"payment qr",
|
|
86
|
+
"alipay",
|
|
87
|
+
"scan",
|
|
88
|
+
"order not found",
|
|
89
|
+
"二维码",
|
|
90
|
+
"扫码",
|
|
91
|
+
"付款码"
|
|
92
|
+
]
|
|
72
93
|
}
|
|
@@ -10,9 +10,17 @@
|
|
|
10
10
|
"The CLI returned agent_wait metadata."
|
|
11
11
|
],
|
|
12
12
|
"required_state": {
|
|
13
|
-
"needs": [
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
"needs": [
|
|
14
|
+
"payment_intent_id"
|
|
15
|
+
],
|
|
16
|
+
"optional": [
|
|
17
|
+
"cursor"
|
|
18
|
+
],
|
|
19
|
+
"must_not_need": [
|
|
20
|
+
"ops token",
|
|
21
|
+
"provider query permission",
|
|
22
|
+
"human text proof"
|
|
23
|
+
]
|
|
16
24
|
},
|
|
17
25
|
"commands": [
|
|
18
26
|
{
|
|
@@ -27,6 +35,7 @@
|
|
|
27
35
|
}
|
|
28
36
|
],
|
|
29
37
|
"agent_rules": [
|
|
38
|
+
"If payment wait returns payment_handoff_required, render response.render_plan.selected to the human before running any later status check.",
|
|
30
39
|
"Start payment status checks only after the QR image/link has already been sent to the human or the human asks to check status.",
|
|
31
40
|
"If you run payment wait without a short timeout while payment is still pending, CLI returns payment_handoff_required and human_visible_markdown instead of long-polling.",
|
|
32
41
|
"Payment wait/status check is a recovery loop around the same payment_intent_id, not a one-shot command.",
|
|
@@ -57,5 +66,18 @@
|
|
|
57
66
|
"command": "itp docs show recovery --role buyer --json"
|
|
58
67
|
}
|
|
59
68
|
],
|
|
60
|
-
"search_terms": [
|
|
69
|
+
"search_terms": [
|
|
70
|
+
"wait",
|
|
71
|
+
"long poll",
|
|
72
|
+
"timeout",
|
|
73
|
+
"still waiting",
|
|
74
|
+
"paid",
|
|
75
|
+
"payment",
|
|
76
|
+
"等待",
|
|
77
|
+
"付款",
|
|
78
|
+
"付款成功",
|
|
79
|
+
"没返回",
|
|
80
|
+
"一直等",
|
|
81
|
+
"超时"
|
|
82
|
+
]
|
|
61
83
|
}
|
|
@@ -10,8 +10,16 @@
|
|
|
10
10
|
"The agent is unsure which ItPay buyer command should come first."
|
|
11
11
|
],
|
|
12
12
|
"required_state": {
|
|
13
|
-
"needs": [
|
|
14
|
-
|
|
13
|
+
"needs": [
|
|
14
|
+
"itp CLI available",
|
|
15
|
+
"buyer delivery email before checkout"
|
|
16
|
+
],
|
|
17
|
+
"must_not_need": [
|
|
18
|
+
"ops token",
|
|
19
|
+
"claim token",
|
|
20
|
+
"raw key",
|
|
21
|
+
"provider raw payload"
|
|
22
|
+
]
|
|
15
23
|
},
|
|
16
24
|
"commands": [
|
|
17
25
|
{
|
|
@@ -59,7 +67,8 @@
|
|
|
59
67
|
"If response.status is payment_handoff_required, do not run payment wait from next.command; next is the human-visible reply. Only after the human asks to check payment should you run after_human_response.check_payment_command.",
|
|
60
68
|
"Show the returned payment QR exactly as provided before starting payment wait.",
|
|
61
69
|
"Payment truth comes only from payment_intent.verified.",
|
|
62
|
-
"Secure delivery goes to the human first; report redacted delivery status only."
|
|
70
|
+
"Secure delivery goes to the human first; report redacted delivery status only.",
|
|
71
|
+
"When a response includes render_plan.selected, execute that selected plan first; do not make the model choose a different platform branch or rewrite the payment/auth UI."
|
|
63
72
|
],
|
|
64
73
|
"forbidden": [
|
|
65
74
|
"Do not call ops commands from the buyer path.",
|
|
@@ -95,5 +104,14 @@
|
|
|
95
104
|
"command": "itp docs show account-portal --role buyer --json"
|
|
96
105
|
}
|
|
97
106
|
],
|
|
98
|
-
"search_terms": [
|
|
107
|
+
"search_terms": [
|
|
108
|
+
"start",
|
|
109
|
+
"quickstart",
|
|
110
|
+
"first time",
|
|
111
|
+
"buyer flow",
|
|
112
|
+
"how to use itpay",
|
|
113
|
+
"开始",
|
|
114
|
+
"第一次",
|
|
115
|
+
"怎么用"
|
|
116
|
+
]
|
|
99
117
|
}
|
package/lib/render-human.js
CHANGED
|
@@ -306,29 +306,38 @@ function buildHumanActionRenderPlan(action = {}, intent = {}, flags = {}) {
|
|
|
306
306
|
if (mobileWalletURL) requiredOutputs.push({ type: "link", label: "手机钱包打开", url: mobileWalletURL });
|
|
307
307
|
const markdown = humanActionMarkdown(planAction, { localQRPath, qrPNGURL, preferredQRURL, entryURL, mobileWalletURL });
|
|
308
308
|
const telegram = telegramRenderPlan(planAction, { localQRPath, preferredQRURL, entryURL, mobileWalletURL });
|
|
309
|
+
const host = agentHost(flags);
|
|
310
|
+
const platforms = compactObject({
|
|
311
|
+
codex_app: { format: "markdown_image_and_links", markdown },
|
|
312
|
+
claude_code: { format: "markdown_image_and_links", markdown },
|
|
313
|
+
telegram,
|
|
314
|
+
plain_chat: {
|
|
315
|
+
format: "image_or_link_then_human_reply",
|
|
316
|
+
text: kind === "payment_qr"
|
|
317
|
+
? "请扫码或点击链接完成支付。付完后回复“我已付款”,我再查询真实状态。"
|
|
318
|
+
: "请打开上面的授权入口。完成后告诉我,我再继续查询状态。",
|
|
319
|
+
links: requiredOutputs.filter((item) => item.type === "link")
|
|
320
|
+
},
|
|
321
|
+
terminal: {
|
|
322
|
+
format: "cli_prints_qr_then_wait",
|
|
323
|
+
print_terminal_qr: true,
|
|
324
|
+
print_links: true
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
const selectedPlatform = selectedRenderPlatform(host);
|
|
328
|
+
const selected = {
|
|
329
|
+
platform: selectedPlatform,
|
|
330
|
+
...platforms[selectedPlatform]
|
|
331
|
+
};
|
|
309
332
|
return compactObject({
|
|
310
333
|
kind,
|
|
311
334
|
proof_rule: kind === "payment_qr"
|
|
312
335
|
? "Only payment_intent.verified proves payment."
|
|
313
336
|
: "This human action is not payment proof.",
|
|
314
|
-
host:
|
|
337
|
+
host: host || undefined,
|
|
315
338
|
required_outputs: requiredOutputs,
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
claude_code: { format: "markdown_image_and_links", markdown },
|
|
319
|
-
telegram,
|
|
320
|
-
plain_chat: {
|
|
321
|
-
format: "image_or_link_then_human_reply",
|
|
322
|
-
text: kind === "payment_qr"
|
|
323
|
-
? "请扫码或点击链接完成支付。付完后回复“我已付款”,我再查询真实状态。"
|
|
324
|
-
: "请打开上面的授权入口。完成后告诉我,我再继续查询状态。"
|
|
325
|
-
},
|
|
326
|
-
terminal: {
|
|
327
|
-
format: "cli_prints_qr_then_wait",
|
|
328
|
-
print_terminal_qr: true,
|
|
329
|
-
print_links: true
|
|
330
|
-
}
|
|
331
|
-
}),
|
|
339
|
+
selected,
|
|
340
|
+
platforms,
|
|
332
341
|
forbidden: [
|
|
333
342
|
"Do not say 'scan the QR above' unless an image or scannable URL is actually attached.",
|
|
334
343
|
"Do not read a local image file as model input and treat that as sent to the human.",
|
|
@@ -372,6 +381,15 @@ function telegramRenderPlan(action = {}, { localQRPath = "", preferredQRURL = ""
|
|
|
372
381
|
};
|
|
373
382
|
}
|
|
374
383
|
|
|
384
|
+
function selectedRenderPlatform(host = "") {
|
|
385
|
+
const normalized = String(host || "").toLowerCase().replaceAll("-", "_");
|
|
386
|
+
if (["codex", "codex_app", "codex_cli"].includes(normalized)) return "codex_app";
|
|
387
|
+
if (["claude", "claude_code", "claudecode"].includes(normalized)) return "claude_code";
|
|
388
|
+
if (["telegram", "tg"].includes(normalized)) return "telegram";
|
|
389
|
+
if (terminalQRHostAliases().has(normalized)) return "terminal";
|
|
390
|
+
return "plain_chat";
|
|
391
|
+
}
|
|
392
|
+
|
|
375
393
|
function compactObject(value = {}) {
|
|
376
394
|
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined && item !== null && item !== ""));
|
|
377
395
|
}
|
package/package.json
CHANGED
|
@@ -211,10 +211,13 @@ itp buy <variant_id> --email <buyer_email> --phone <buyer_phone> --display agent
|
|
|
211
211
|
|
|
212
212
|
This keeps JSON output machine-readable while allowing the CLI to prepare a
|
|
213
213
|
local QR image path for clients that cannot render remote SVG reliably. In
|
|
214
|
-
Codex or Claude Code app clients, prefer `--no-wait-payment`:
|
|
215
|
-
`
|
|
216
|
-
human
|
|
217
|
-
|
|
214
|
+
Codex or Claude Code app clients, prefer `--no-wait-payment`: execute
|
|
215
|
+
`render_plan.selected` first. If `selected.markdown` exists, send it exactly to
|
|
216
|
+
the human. If `selected.media` exists, attach the listed image before saying the
|
|
217
|
+
human can scan it. If `selected.links` exists, include the real URL, not just
|
|
218
|
+
the label. If `selected.buttons` exists and the current adapter supports native
|
|
219
|
+
buttons, render them; otherwise fall back to the real URL plus short text. Do
|
|
220
|
+
not invent a table or rewrite the UI plan.
|
|
218
221
|
|
|
219
222
|
If a response has `status=payment_handoff_required`, `next` is the user-visible
|
|
220
223
|
reply step, not payment wait. Do not run `buyer payment wait` until the human
|