@itpay/cli 0.2.13 → 0.2.15
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 +9 -5
- package/docs/agent/buyer/payment-qr.json +8 -6
- package/docs/agent/buyer/payment-wait.json +2 -2
- package/docs/agent/buyer/quickstart.json +9 -7
- package/lib/buyer.js +106 -18
- package/lib/client-context.js +2 -2
- package/package.json +1 -1
- package/skills/itpay-buyer/SKILL.md +24 -15
package/README.md
CHANGED
|
@@ -158,9 +158,12 @@ Before starting a new purchase, agents should inspect recoverable local state:
|
|
|
158
158
|
itp status --refresh --host <client> --json
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
-
Every non-doc command needs a client context.
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
Every non-doc command needs a client context. `--host` means the
|
|
162
|
+
human-visible client/surface, not where the shell command runs. Use
|
|
163
|
+
`--host codex` in Codex desktop chat even when you call `itp` through shell;
|
|
164
|
+
use `--host terminal` only when the human is directly reading a terminal. For
|
|
165
|
+
OpenClaw Telegram private/group chat, use
|
|
166
|
+
`--host telegram --target <inbound_meta.chat_id>`.
|
|
164
167
|
If the CLI returns `client_context_required` or `client_target_required`, rerun
|
|
165
168
|
the same command with the requested fields.
|
|
166
169
|
|
|
@@ -245,9 +248,10 @@ Payment QR rules:
|
|
|
245
248
|
- Otherwise render the ItPay-hosted `qr_png_url` / `preferred_qr_url`.
|
|
246
249
|
- Use `mobile_wallet_url` only as a human mobile fallback.
|
|
247
250
|
- Do not generate your own QR from payment URLs.
|
|
248
|
-
- In OpenClaw Telegram,
|
|
251
|
+
- In OpenClaw Telegram, run root `agent_action.command` or `agent_action.argv` before replying; do not simulate buttons in normal prose.
|
|
249
252
|
- Telegram native buttons require `presentation.blocks[].type="buttons"` with `text/url/callback_data`.
|
|
250
|
-
- For Codex/Claude Code, send root `
|
|
253
|
+
- For Codex/Claude Code app clients, send root `agent_action.markdown` before any next ItPay command. If you can confirm it is visible to the human, you may then run `after_visible_action.command`; if unsure, stop.
|
|
254
|
+
- For terminal clients, run root `agent_action.command` only when the human is directly watching that terminal. Do not use `--host terminal` merely because you invoke `itp` through shell.
|
|
251
255
|
- If status is `payment_handoff_required`, `next` is the human reply step, not payment wait.
|
|
252
256
|
- Treat only `payment_intent.verified` as payment success.
|
|
253
257
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
{
|
|
27
27
|
"intent": "create payment intent through the high-level buy flow",
|
|
28
28
|
"command": "itp buy <variant_id> --email <buyer_email> --phone <buyer_phone> --display agent --no-wait-payment --host <client> --json",
|
|
29
|
-
"success_signal": "response.status is payment_handoff_required; for OpenClaw Telegram,
|
|
29
|
+
"success_signal": "response.status is payment_handoff_required; for OpenClaw Telegram, execute response.agent_action.command or response.agent_action.argv before any normal reply or status check"
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"intent": "recover a scanner order-not-found display problem",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
}
|
|
36
36
|
],
|
|
37
37
|
"agent_rules": [
|
|
38
|
-
"Every non-doc ItPay command must include current client context. Use --host codex/claude-code/terminal/plain-chat, or for OpenClaw Telegram use --host telegram --target <inbound_meta.chat_id>.",
|
|
38
|
+
"Every non-doc ItPay command must include current client context. Use --host codex/claude-code/terminal/plain-chat, or for OpenClaw Telegram use --host telegram --target <inbound_meta.chat_id>. --host is the human-visible client/surface, not where the shell command runs; in Codex desktop chat use --host codex even when calling itp through shell.",
|
|
39
39
|
"If ItPay returns client_context_required or client_target_required, rerun the same command with the requested --host/--target before doing anything else.",
|
|
40
40
|
"If human_action.kind is auth_qr, present the ItPay first-purchase entry URL/QR and explain it starts account login/registration/profile authorization and should continue to payment for the same checkout after approval.",
|
|
41
41
|
"For auth_qr, the ItPay auth entry is the primary handoff. oauth_start_url is fallback/debug and should not replace the ItPay orchestration page.",
|
|
@@ -43,11 +43,13 @@
|
|
|
43
43
|
"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.",
|
|
44
44
|
"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.",
|
|
45
45
|
"Do not describe auth_qr as payment success or payment proof. Only payment_intent.verified proves payment.",
|
|
46
|
-
"If response.
|
|
47
|
-
"In OpenClaw Telegram,
|
|
46
|
+
"If response.agent_action is present, it is the mandatory execution path. Execute it before any normal prose reply or next ItPay command: command/argv for Telegram or terminal, markdown for Codex/Claude Code app clients.",
|
|
47
|
+
"In OpenClaw Telegram, response.agent_action is already the exact openclaw message send command. Do not rebuild it, do not summarize it, and do not rewrite it into a custom table.",
|
|
48
|
+
"If response.agent_action cannot be executed or made visible to the human, stop and tell the human what capability is missing. Do not fall back to handmade prose.",
|
|
49
|
+
"response.agent_instruction is natural-language reinforcement for the agent; it does not replace response.agent_action.",
|
|
48
50
|
"Telegram native buttons require openclaw message send --presentation; presentation.blocks[].type=\"buttons\" uses native text/url/callback_data. Do not simulate buttons in normal prose.",
|
|
49
51
|
"If agent_instruction links/buttons include URLs, include the real URL. Do not only show the link label.",
|
|
50
|
-
"In Codex or Claude Code app clients, send response.
|
|
52
|
+
"In Codex or Claude Code app clients, send response.agent_action.markdown first. Do not start a hidden long wait before the human-visible message is sent.",
|
|
51
53
|
"For Telegram-style message clients, send photo media first, include links, and expose native buttons for refresh/status when the adapter supports them.",
|
|
52
54
|
"For plain chat clients, show response.agent_instruction.message/links and stop unless the human asks you to check status or returns with a payment question.",
|
|
53
55
|
"When response.status is payment_handoff_required, response.next is the human reply step, not payment wait.",
|
|
@@ -58,7 +60,7 @@
|
|
|
58
60
|
"payment_entry_url is the stable ItPay status/payment page. qr_png_url/local_qr_path is usually the better desktop scanner artifact.",
|
|
59
61
|
"The provider can briefly show order not found even after precreate succeeded. Tell the human to wait 30-60 seconds and retry the same QR/page. Do not create a new checkout, do not create a new payment intent, and do not repeatedly refresh unless the ItPay page or CLI explicitly asks for recovery.",
|
|
60
62
|
"Opening the payment page must not be treated as paid.",
|
|
61
|
-
"Do not run payment wait before the QR/link has been sent to the human.
|
|
63
|
+
"Do not run payment wait before the QR/link has been sent to the human. If after_visible_action.command exists and you can confirm the handoff is visible, you may run it once; if unsure, stop and wait for the human.",
|
|
62
64
|
"After the human says they paid or clicks a platform status button, run response.after_human_response.check_payment_command for the same payment_intent_id."
|
|
63
65
|
],
|
|
64
66
|
"forbidden": [
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
],
|
|
37
37
|
"agent_rules": [
|
|
38
38
|
"Every payment wait/status command must include the same client context as the handoff command. For OpenClaw Telegram, keep --host telegram --target <same chat_id>.",
|
|
39
|
-
"If payment wait returns payment_handoff_required with response.
|
|
39
|
+
"If payment wait returns payment_handoff_required with response.agent_action, execute it before any later status check: command/argv for Telegram or terminal, markdown for Codex/Claude Code app clients. If only response.agent_instruction is present, follow it exactly before any later status check.",
|
|
40
40
|
"Start payment status checks only after the QR image/link has already been sent to the human or the human asks to check status.",
|
|
41
41
|
"If you run payment wait without a short timeout while payment is still pending, CLI returns payment_handoff_required and the human handoff instruction instead of long-polling.",
|
|
42
42
|
"Payment wait/status check is a recovery loop around the same payment_intent_id, not a one-shot command.",
|
|
43
43
|
"wait.timeout is a heartbeat, not a payment failure.",
|
|
44
|
-
"In Codex or Claude Code app clients, after showing QR, use
|
|
44
|
+
"In Codex or Claude Code app clients, after showing QR, use after_visible_action.command only if you can confirm the QR/link is visible. If the human still has not paid, explain that the same QR/link remains valid and pause for their reply.",
|
|
45
45
|
"Continue checking the same payment_intent_id unless the user explicitly cancels or asks you to pause.",
|
|
46
46
|
"If the network drops, the process is interrupted, or there is no response, rerun payment wait with the same payment_intent_id or run checkout status/resume with the same checkout_id.",
|
|
47
47
|
"If status is unclear, tell the human it is unclear and continue querying the same payment_intent_id/checkout_id. Do not create a new checkout.",
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
{
|
|
46
46
|
"intent": "buy a selected variant with the high-level cart-first flow",
|
|
47
47
|
"command": "itp buy <variant_id> --email <buyer_email> --phone <buyer_phone> --display agent --no-wait-payment --host <client> --json",
|
|
48
|
-
"success_signal": "response.status becomes waiting_human_auth or payment_handoff_required;
|
|
48
|
+
"success_signal": "response.status becomes waiting_human_auth or payment_handoff_required; if agent_action is present, execute it before any normal reply or payment status check"
|
|
49
49
|
}
|
|
50
50
|
],
|
|
51
51
|
"agent_rules": [
|
|
52
52
|
"Use --json for every ItPay command.",
|
|
53
|
-
"Every non-doc ItPay command must include the current client context: --host codex, --host claude-code, --host terminal, --host plain-chat, or for OpenClaw/Telegram use --host telegram --target <inbound_meta.chat_id>.",
|
|
53
|
+
"Every non-doc ItPay command must include the current client context: --host codex, --host claude-code, --host terminal, --host plain-chat, or for OpenClaw/Telegram use --host telegram --target <inbound_meta.chat_id>. --host is the human-visible client/surface, not where the shell command runs; in Codex desktop chat use --host codex even when calling itp through shell.",
|
|
54
54
|
"Do not rely on the CLI to guess Telegram, Discord, WhatsApp, Codex, or Claude Code. If ItPay returns client_context_required or client_target_required, rerun the same command with the required --host/--target fields before continuing.",
|
|
55
|
-
"For Telegram group chat or @mention flows, pass the group/private chat target from OpenClaw inbound metadata, for example --target telegram:-1001234567890. ItPay only echoes the target into
|
|
55
|
+
"For Telegram group chat or @mention flows, pass the group/private chat target from OpenClaw inbound metadata, for example --target telegram:-1001234567890. ItPay only echoes the target into agent_action; OpenClaw owns group allowlist/mention policy.",
|
|
56
56
|
"Use `itp status --refresh --host <client> --json` before account, order, refund, or repeat-purchase decisions. Plain local memory is not identity.",
|
|
57
57
|
"If `status --refresh` returns `recoverable_context.found=true`, do not blindly resume or blindly ignore it. Decide whether the old task is related to the current user intent; continue related tasks, ignore clearly unrelated tasks, and ask the human when unsure.",
|
|
58
58
|
"If the catalog is unclear, read catalog-search docs and use buyer shelf manifest/snapshot as the shopping-list view before guessing keywords.",
|
|
@@ -66,13 +66,15 @@
|
|
|
66
66
|
"When a buyer command returns buyer_session.status=buyer_session_saved, the CLI has stored the buyer account session for this agent device. You may continue with checkout/payment or `buyer vault` commands without asking the human for a token.",
|
|
67
67
|
"Vault grants are only for reading approved delivered artifacts. They are not buyer session credentials and do not authorize refunds or account/order management.",
|
|
68
68
|
"Use high-level itp buy when possible, but in agent app clients split payment into two visible steps: first return and send the human handoff instruction, then only check status after the human responds or uses a platform button.",
|
|
69
|
-
"If response.
|
|
70
|
-
"In OpenClaw Telegram,
|
|
71
|
-
"If response.
|
|
69
|
+
"If response.agent_action is present, it is the mandatory execution path for the current client. Execute it before any normal prose reply: command/argv for Telegram or terminal, markdown for Codex/Claude Code app clients.",
|
|
70
|
+
"In OpenClaw Telegram, response.agent_action is already the exact openclaw message send command. It includes target, QR media, exact message, and native button presentation.",
|
|
71
|
+
"If response.agent_action cannot be executed or made visible to the human, stop and tell the human what capability is missing. Do not fall back to handwritten prose.",
|
|
72
|
+
"response.agent_instruction is natural-language reinforcement for the agent; it does not replace response.agent_action.",
|
|
73
|
+
"If response.status is payment_handoff_required, do not run payment wait from next.command; next is the human-visible reply. If after_visible_action.command exists and you can confirm the handoff is visible, you may run it once; if unsure, stop and wait for the human.",
|
|
72
74
|
"Show the returned payment QR exactly as provided before starting payment wait.",
|
|
73
75
|
"Payment truth comes only from payment_intent.verified.",
|
|
74
76
|
"Secure delivery goes to the human first; report redacted delivery status only.",
|
|
75
|
-
"For OpenClaw Telegram, root
|
|
77
|
+
"For OpenClaw Telegram, root agent_action is the execution path. Do not use handwritten prose when agent_action is present."
|
|
76
78
|
],
|
|
77
79
|
"forbidden": [
|
|
78
80
|
"Do not call ops commands from the buyer path.",
|
package/lib/buyer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
appendURLQuery, booleanFlag, cliCommand, cryptoRandom, csvValues, deleteSessionCredential, intFlag, output, positional, readConfig, readCredentials,
|
|
3
3
|
readSessionToken, readState, safeErrorMessage, sleep, splitCSV, stripInternalBuyerFields, updateRun, writeConfig,
|
|
4
|
-
writeCredentials, writeSessionCredentials, writeState
|
|
4
|
+
writeCredentials, writeSessionCredentials, writeState, shellQuote
|
|
5
5
|
} from "./env.js";
|
|
6
6
|
import { clientCommandArgs, clientHost, clientTarget } from "./client-context.js";
|
|
7
7
|
import { coreApi, coreApiBase } from "./http.js";
|
|
@@ -1592,48 +1592,77 @@ function telegramBuyerInstruction(value = {}, flags = {}) {
|
|
|
1592
1592
|
const hasHumanEntry = Boolean(media || presentation.blocks?.some((block) => block.type === "buttons" && block.buttons?.some((button) => button.url)));
|
|
1593
1593
|
const text = telegramBuyerInstructionText(plan.kind, summary, hasHumanEntry);
|
|
1594
1594
|
const callbacks = rawMessage.callbacks || {};
|
|
1595
|
+
const commandArgs = compactObject({
|
|
1596
|
+
channel: "telegram",
|
|
1597
|
+
target: clientTarget(flags) || undefined,
|
|
1598
|
+
message: text,
|
|
1599
|
+
media: media || undefined,
|
|
1600
|
+
presentation
|
|
1601
|
+
});
|
|
1602
|
+
const action = telegramAgentAction(commandArgs);
|
|
1603
|
+
const instruction = "必须先执行顶层 agent_action.command 或 agent_action.argv,把二维码、说明和 Telegram 原生按钮发给用户。不要手写 Markdown 表格,不要只贴链接,不要先运行 wait/status;如果不能执行 openclaw message send,就停止并说明工具缺失。";
|
|
1595
1604
|
return compactObject({
|
|
1596
1605
|
status: value.status,
|
|
1606
|
+
instruction,
|
|
1597
1607
|
must_send_to_human_before_next_command: true,
|
|
1608
|
+
must_execute_agent_action_before_reply: true,
|
|
1598
1609
|
order_summary: summary,
|
|
1610
|
+
agent_action: action,
|
|
1599
1611
|
agent_instruction: {
|
|
1600
1612
|
type: plan.kind === "auth_qr" ? "send_telegram_auth_handoff" : "send_telegram_payment_handoff",
|
|
1601
1613
|
platform: "telegram",
|
|
1602
1614
|
proof_rule: plan.proof_rule,
|
|
1603
|
-
instruction
|
|
1615
|
+
instruction,
|
|
1604
1616
|
openclaw_message: {
|
|
1605
1617
|
command: "openclaw message send",
|
|
1606
|
-
command_args:
|
|
1607
|
-
channel: "telegram",
|
|
1608
|
-
target: clientTarget(flags) || undefined,
|
|
1609
|
-
message: text,
|
|
1610
|
-
media: media || undefined,
|
|
1611
|
-
presentation
|
|
1612
|
-
}),
|
|
1618
|
+
command_args: commandArgs,
|
|
1613
1619
|
telegram_rule: "Telegram 原生按钮必须通过 openclaw message send --presentation 发送;presentation.blocks[].type=\"buttons\" 才会生成 Inline Keyboard。",
|
|
1614
1620
|
callbacks
|
|
1615
1621
|
}
|
|
1616
1622
|
},
|
|
1617
1623
|
after_human_response: telegramAfterHumanResponse(value, callbacks),
|
|
1618
|
-
agent_next_actions: ["
|
|
1624
|
+
agent_next_actions: ["execute_agent_action"],
|
|
1619
1625
|
next: {
|
|
1620
1626
|
type: "reply_to_human",
|
|
1621
1627
|
safe_for_agent: false,
|
|
1622
|
-
instruction: "
|
|
1628
|
+
instruction: "先执行 agent_action.command/argv;用户点击按钮或回复后,再运行 after_human_response 里的命令。"
|
|
1623
1629
|
}
|
|
1624
1630
|
});
|
|
1625
1631
|
}
|
|
1626
1632
|
|
|
1633
|
+
function telegramAgentAction(commandArgs = {}) {
|
|
1634
|
+
const argv = ["openclaw", "message", "send"];
|
|
1635
|
+
if (commandArgs.channel) argv.push("--channel", commandArgs.channel);
|
|
1636
|
+
if (commandArgs.target) argv.push("--target", commandArgs.target);
|
|
1637
|
+
if (commandArgs.message) argv.push("--message", commandArgs.message);
|
|
1638
|
+
if (commandArgs.media) argv.push("--media", commandArgs.media);
|
|
1639
|
+
if (commandArgs.presentation) argv.push("--presentation", JSON.stringify(commandArgs.presentation));
|
|
1640
|
+
return {
|
|
1641
|
+
type: "openclaw_message_send",
|
|
1642
|
+
tool: "shell",
|
|
1643
|
+
instruction: "现在立刻执行这个 shell 命令发送 Telegram 原生消息;不要改写为普通聊天回复。执行成功后再简短告诉用户已发出。",
|
|
1644
|
+
command: argv.map((item) => shellQuote(String(item))).join(" "),
|
|
1645
|
+
argv,
|
|
1646
|
+
if_unavailable: "如果当前 agent 不能执行 openclaw message send,停止并告诉用户:当前 agent 缺少 Telegram 原生按钮发送工具;不要降级成 Markdown 表格或普通链接。"
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1627
1650
|
function markdownBuyerInstruction(value = {}, flags = {}, platform = "codex_app", markdown = "") {
|
|
1628
1651
|
const plan = value.render_plan || {};
|
|
1629
1652
|
const summary = buyerOrderSummary(value, plan.kind);
|
|
1653
|
+
const instruction = markdownBuyerInstructionText(platform);
|
|
1630
1654
|
return handoffInstructionOutput(value, flags, {
|
|
1631
1655
|
type: plan.kind === "auth_qr" ? "send_markdown_auth_handoff" : "send_markdown_payment_handoff",
|
|
1632
1656
|
platform,
|
|
1633
1657
|
proof_rule: plan.proof_rule,
|
|
1634
|
-
instruction
|
|
1658
|
+
instruction,
|
|
1635
1659
|
markdown
|
|
1636
|
-
}, summary
|
|
1660
|
+
}, summary, {
|
|
1661
|
+
instruction,
|
|
1662
|
+
agent_action: markdownAgentAction(platform, markdown),
|
|
1663
|
+
after_visible_action: afterVisibleAction(value, flags, summary),
|
|
1664
|
+
agent_next_actions: ["send_agent_action_to_human"]
|
|
1665
|
+
});
|
|
1637
1666
|
}
|
|
1638
1667
|
|
|
1639
1668
|
function plainChatBuyerInstruction(value = {}, flags = {}, selected = {}) {
|
|
@@ -1652,31 +1681,90 @@ function plainChatBuyerInstruction(value = {}, flags = {}, selected = {}) {
|
|
|
1652
1681
|
function terminalBuyerInstruction(value = {}, flags = {}) {
|
|
1653
1682
|
const plan = value.render_plan || {};
|
|
1654
1683
|
const summary = buyerOrderSummary(value, plan.kind);
|
|
1684
|
+
const instruction = "必须先执行 agent_action.command,让 CLI 在人类正在看的终端里打印二维码、链接和摘要;不要把 terminal 当成 Codex 桌面端。如果人类不是直接看这个终端,改用 --host codex 重跑。";
|
|
1655
1685
|
return handoffInstructionOutput(value, flags, {
|
|
1656
1686
|
type: plan.kind === "auth_qr" ? "terminal_auth_handoff" : "terminal_payment_handoff",
|
|
1657
1687
|
platform: "terminal",
|
|
1658
1688
|
proof_rule: plan.proof_rule,
|
|
1659
|
-
instruction
|
|
1689
|
+
instruction,
|
|
1660
1690
|
print_terminal_qr: true
|
|
1661
|
-
}, summary
|
|
1691
|
+
}, summary, {
|
|
1692
|
+
instruction,
|
|
1693
|
+
agent_action: terminalAgentAction(summary, flags, plan.kind),
|
|
1694
|
+
after_visible_action: afterVisibleAction(value, flags, summary),
|
|
1695
|
+
agent_next_actions: ["execute_agent_action"]
|
|
1696
|
+
});
|
|
1662
1697
|
}
|
|
1663
1698
|
|
|
1664
|
-
function handoffInstructionOutput(value = {}, flags = {}, agentInstruction = {}, summary = {}) {
|
|
1699
|
+
function handoffInstructionOutput(value = {}, flags = {}, agentInstruction = {}, summary = {}, extra = {}) {
|
|
1665
1700
|
return compactObject({
|
|
1666
1701
|
status: value.status,
|
|
1702
|
+
instruction: extra.instruction,
|
|
1667
1703
|
must_send_to_human_before_next_command: true,
|
|
1668
1704
|
order_summary: summary,
|
|
1705
|
+
agent_action: extra.agent_action,
|
|
1669
1706
|
agent_instruction: agentInstruction,
|
|
1670
1707
|
after_human_response: genericAfterHumanResponse(value, flags, summary),
|
|
1671
|
-
|
|
1708
|
+
after_visible_action: extra.after_visible_action,
|
|
1709
|
+
agent_next_actions: extra.agent_next_actions || ["send_agent_instruction_to_human"],
|
|
1672
1710
|
next: {
|
|
1673
1711
|
type: "reply_to_human",
|
|
1674
1712
|
safe_for_agent: false,
|
|
1675
|
-
instruction: "先把 agent_instruction 发送给用户;用户点击按钮或回复后,再运行 after_human_response 里的命令。"
|
|
1713
|
+
instruction: extra.next_instruction || "先把 agent_instruction 发送给用户;用户点击按钮或回复后,再运行 after_human_response 里的命令。"
|
|
1676
1714
|
}
|
|
1677
1715
|
});
|
|
1678
1716
|
}
|
|
1679
1717
|
|
|
1718
|
+
function markdownBuyerInstructionText(platform = "codex_app") {
|
|
1719
|
+
const label = platform === "claude_code" ? "Claude Code app" : "Codex desktop app";
|
|
1720
|
+
return `你在 ${label}。必须先把顶层 agent_action.markdown 原样发到当前聊天,让人类真正看到二维码、订单摘要和链接;不要因为你用 shell 跑 itp 就改用 --host terminal。发出后,如果你能确认消息已经对人类可见,可以继续执行 after_visible_action.command 等 30 秒;如果不能确认,就停止等人类回复。`;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
function markdownAgentAction(platform = "codex_app", markdown = "") {
|
|
1724
|
+
const label = platform === "claude_code" ? "Claude Code app" : "Codex desktop app";
|
|
1725
|
+
return {
|
|
1726
|
+
type: "markdown_reply",
|
|
1727
|
+
platform,
|
|
1728
|
+
instruction: `现在立刻把 markdown 原样发送到当前聊天。${label} 可以用绝对路径 Markdown 图片显示本地二维码。不要只贴文件路径,不要先运行 wait/status。`,
|
|
1729
|
+
markdown,
|
|
1730
|
+
if_unavailable: "如果当前客户端不能让这段 Markdown 对人类可见,停止并说明无法展示二维码;不要先运行 wait/status。"
|
|
1731
|
+
};
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
function terminalAgentAction(summary = {}, flags = {}, kind = "") {
|
|
1735
|
+
const args = kind === "auth_qr" && summary.checkout_id
|
|
1736
|
+
? ["buyer", "checkout", "resume", summary.checkout_id, ...clientCommandArgs(flags), "--no-wait-auth"]
|
|
1737
|
+
: summary.payment_intent_id
|
|
1738
|
+
? ["buyer", "payment", "wait", summary.payment_intent_id, ...clientCommandArgs(flags)]
|
|
1739
|
+
: [];
|
|
1740
|
+
if (!args.length) return undefined;
|
|
1741
|
+
return {
|
|
1742
|
+
type: "terminal_handoff_command",
|
|
1743
|
+
tool: "shell",
|
|
1744
|
+
instruction: "只有当人类直接看这个终端窗口时才执行。它会让 CLI 打印二维码和链接。若你在 Codex 桌面聊天里,请改用 --host codex 重跑原命令。",
|
|
1745
|
+
command: cliCommand(...args),
|
|
1746
|
+
if_unavailable: "如果不能确认人类正在看该终端,停止并用正确的 --host 重跑;不要把终端输出当成 Codex 桌面端回复。"
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
function afterVisibleAction(value = {}, flags = {}, summary = {}) {
|
|
1751
|
+
if (summary.payment_intent_id) {
|
|
1752
|
+
return {
|
|
1753
|
+
optional: true,
|
|
1754
|
+
command: cliCommand("buyer", "payment", "wait", summary.payment_intent_id, "--timeout", "30", ...clientCommandArgs(flags), "--json"),
|
|
1755
|
+
instruction: "只有在二维码、订单摘要和链接已经对人类可见后才能执行。用户说已付款不算证明,只有 payment_intent.verified 算付款成功。"
|
|
1756
|
+
};
|
|
1757
|
+
}
|
|
1758
|
+
if (summary.checkout_id) {
|
|
1759
|
+
return {
|
|
1760
|
+
optional: true,
|
|
1761
|
+
command: cliCommand("buyer", "checkout", "resume", summary.checkout_id, ...clientCommandArgs(flags), "--json"),
|
|
1762
|
+
instruction: "只有在授权入口已经对人类可见后才能执行;继续同一个 checkout,不要新建 checkout。"
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
return undefined;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1680
1768
|
function buyerOrderSummary(value = {}, kind = "") {
|
|
1681
1769
|
const cart = value.cart || {};
|
|
1682
1770
|
const checkout = value.checkout || {};
|
package/lib/client-context.js
CHANGED
|
@@ -52,7 +52,7 @@ function clientContextRequired() {
|
|
|
52
52
|
schema_version: "itp.client_context.v1",
|
|
53
53
|
status: "client_context_required",
|
|
54
54
|
must_rerun: true,
|
|
55
|
-
instruction: "Rerun the same itp command with --host <client>.
|
|
55
|
+
instruction: "Rerun the same itp command with --host <client>. --host means the human-visible client/surface, not where the shell command runs. In Codex desktop chat use --host codex even when calling itp through shell; use --host terminal only when the human is directly reading a terminal.",
|
|
56
56
|
allowed_hosts: Array.from(SUPPORTED_HOSTS),
|
|
57
57
|
examples: {
|
|
58
58
|
codex: "itp ... --host codex --json",
|
|
@@ -84,7 +84,7 @@ function unsupportedClientContext(host) {
|
|
|
84
84
|
status: "unsupported_client_context",
|
|
85
85
|
must_rerun: true,
|
|
86
86
|
host,
|
|
87
|
-
instruction: "Use one supported --host value so ItPay can return a single executable human-output instruction.",
|
|
87
|
+
instruction: "Use one supported --host value so ItPay can return a single executable human-output instruction. --host means the human-visible client/surface, not the shell execution environment.",
|
|
88
88
|
allowed_hosts: Array.from(SUPPORTED_HOSTS)
|
|
89
89
|
};
|
|
90
90
|
}
|
package/package.json
CHANGED
|
@@ -20,9 +20,12 @@ 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.
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
Every non-doc ItPay command must include the current client context. `--host`
|
|
24
|
+
means the human-visible client/surface, not where the shell command runs. In
|
|
25
|
+
Codex desktop chat use `--host codex` even when calling `itp` through shell;
|
|
26
|
+
use `--host terminal` only when the human is directly reading a terminal. The
|
|
27
|
+
CLI will stop with `client_context_required` or `client_target_required`
|
|
28
|
+
rather than guess.
|
|
26
29
|
|
|
27
30
|
```text
|
|
28
31
|
Codex app: --host codex
|
|
@@ -35,7 +38,13 @@ OpenClaw Telegram private/group chat: --host telegram --target <inbound_meta.cha
|
|
|
35
38
|
For Telegram groups or @mention flows, use the same OpenClaw inbound
|
|
36
39
|
`chat_id` as the target, for example `--target telegram:-1001234567890`.
|
|
37
40
|
OpenClaw owns group allowlists and mention policy; ItPay only echoes the target
|
|
38
|
-
into
|
|
41
|
+
into the returned `agent_action`.
|
|
42
|
+
|
|
43
|
+
If a response contains `agent_action`, execute that action before writing any
|
|
44
|
+
normal reply or running wait/status. For Telegram/terminal this may be
|
|
45
|
+
`agent_action.command` or `agent_action.argv`; for Codex/Claude Code this may
|
|
46
|
+
be `agent_action.markdown`, which must be sent exactly to the current chat.
|
|
47
|
+
If the action cannot be made visible to the human, stop and say why.
|
|
39
48
|
|
|
40
49
|
Run these commands before buying:
|
|
41
50
|
|
|
@@ -141,7 +150,7 @@ be unlocked again by the ItPay backend.
|
|
|
141
150
|
|
|
142
151
|
## Non-Negotiable Rules
|
|
143
152
|
|
|
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>`.
|
|
153
|
+
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>`. `--host` is the human-visible client, not the shell execution environment.
|
|
145
154
|
2. Do not invent service IDs, variant IDs, checkout IDs, payment URLs, QR URLs,
|
|
146
155
|
payment intent IDs, delivery IDs, or claim links.
|
|
147
156
|
3. When the user asks for several compatible services, use one cart and one
|
|
@@ -228,19 +237,19 @@ itp buy <variant_id> --email <buyer_email> --phone <buyer_phone> --display agent
|
|
|
228
237
|
|
|
229
238
|
This keeps JSON output machine-readable while allowing the CLI to prepare a
|
|
230
239
|
local QR image path for clients that cannot render remote SVG reliably. In
|
|
231
|
-
agent/chat clients, prefer `--no-wait-payment`.
|
|
232
|
-
|
|
233
|
-
`
|
|
234
|
-
|
|
235
|
-
`
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
command.
|
|
240
|
+
agent/chat clients, prefer `--no-wait-payment`. If `agent_action` is present,
|
|
241
|
+
execute it exactly before normal prose. In OpenClaw Telegram it contains
|
|
242
|
+
`openclaw message send`, the chat target, QR media, exact human text, and
|
|
243
|
+
`presentation.blocks[].type="buttons"` for Telegram native inline buttons. In
|
|
244
|
+
Codex or Claude Code app clients, send `agent_action.markdown` exactly to the
|
|
245
|
+
current chat. In terminal, run `agent_action.command` only when the human is
|
|
246
|
+
directly watching that terminal.
|
|
239
247
|
|
|
240
248
|
If a response has `status=payment_handoff_required`, `next` is the user-visible
|
|
241
249
|
reply step, not payment wait. Do not run `buyer payment wait` until the human
|
|
242
|
-
has seen the QR/link
|
|
243
|
-
|
|
250
|
+
has seen the QR/link. If `after_visible_action.command` exists and you can
|
|
251
|
+
confirm the handoff is visible, you may run it once; if unsure, stop and wait
|
|
252
|
+
for the human.
|
|
244
253
|
|
|
245
254
|
For first-purchase auth, treat the returned ItPay authorization entry as a
|
|
246
255
|
single human orchestration entry. It may open Alipay login/registration first
|