@itpay/cli 2.1.29 → 2.1.34
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/dist/src/client/backend.js +4 -1
- package/dist/src/client/http.js +2 -0
- package/dist/src/commands/buy.js +3 -1
- package/dist/src/commands/checkout.js +1 -0
- package/dist/src/commands/checkout_handoff.js +7 -4
- package/dist/src/commands/guidance.js +3 -1
- package/dist/src/commands/install.js +2 -1
- package/dist/src/commands/services.js +244 -106
- package/dist/src/commands/skill.js +3 -0
- package/dist/src/main.js +4 -4
- package/dist/src/render/qr.js +1 -1
- package/dist/src/state/account_auth.js +6 -3
- package/dist/src/state/config.js +4 -4
- package/dist/src/state/device_authority.js +7 -5
- package/docs/agent/buyer/cart-checkout.json +1 -1
- package/docs/agent/buyer/orders-refunds.json +1 -0
- package/docs/agent/buyer/payment-flow.json +1 -0
- package/docs/agent/buyer/quickstart.json +1 -1
- package/docs/agent/buyer/rail-booking.json +25 -21
- package/docs/agent/buyer/rail-fast-checkout.json +6 -3
- package/docs/agent/buyer/render-hosts.json +1 -1
- package/package.json +5 -1
- package/skills/itpay/SKILL.md +40 -16
|
@@ -5,6 +5,7 @@ export class BackendClient {
|
|
|
5
5
|
constructor(http) {
|
|
6
6
|
this.http = http;
|
|
7
7
|
}
|
|
8
|
+
get localSimulation() { return this.http.localSimulation; }
|
|
8
9
|
// Called only through the fixed Sell operation contract, never arbitrary Agent URLs.
|
|
9
10
|
sellRequest(request) {
|
|
10
11
|
if (!request.path.startsWith("/v1/seller/organizations") && !request.path.startsWith("/v1/library/"))
|
|
@@ -123,8 +124,10 @@ export class BackendClient {
|
|
|
123
124
|
advanceServiceExecution(id, input, idempotencyKey) {
|
|
124
125
|
return this.http.post(`/v1/service-executions/${encodeURIComponent(id)}/advance`, { input, idempotency_key: idempotencyKey });
|
|
125
126
|
}
|
|
126
|
-
getServiceExecutionResultItemPage(serviceExecutionID, resultItemID, offset, limit) {
|
|
127
|
+
getServiceExecutionResultItemPage(serviceExecutionID, resultItemID, offset, limit, view) {
|
|
127
128
|
const qs = new URLSearchParams({ offset: String(offset), limit: String(limit) });
|
|
129
|
+
if (view)
|
|
130
|
+
qs.set("view", view);
|
|
128
131
|
return this.http.get(`/v1/service-executions/${encodeURIComponent(serviceExecutionID)}/result-items/${encodeURIComponent(resultItemID)}?${qs}`);
|
|
129
132
|
}
|
|
130
133
|
invokeServiceCapability(serviceExecutionID, capabilityID, input) {
|
package/dist/src/client/http.js
CHANGED
|
@@ -14,6 +14,7 @@ export class HttpError extends Error {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
export class HttpClient {
|
|
17
|
+
localSimulation = false;
|
|
17
18
|
static MAX_TRANSPORT_RETRIES = 2;
|
|
18
19
|
baseURL;
|
|
19
20
|
fetchImpl;
|
|
@@ -70,6 +71,7 @@ export class HttpClient {
|
|
|
70
71
|
...(options.signal ? { signal: options.signal } : {}),
|
|
71
72
|
});
|
|
72
73
|
text = await response.text();
|
|
74
|
+
this.localSimulation = response.headers.get("X-ItPay-Environment") === "local_simulation";
|
|
73
75
|
}
|
|
74
76
|
catch (error) {
|
|
75
77
|
if (options.signal?.aborted)
|
package/dist/src/commands/buy.js
CHANGED
|
@@ -106,6 +106,7 @@ export async function runBuy(backend, config, options) {
|
|
|
106
106
|
}
|
|
107
107
|
// --- Build render plan (after payment if --pay) ---
|
|
108
108
|
const planInput = {
|
|
109
|
+
localSimulation: backend.localSimulation,
|
|
109
110
|
host: options.host,
|
|
110
111
|
checkoutID,
|
|
111
112
|
checkoutURL,
|
|
@@ -246,7 +247,7 @@ async function waitForPaymentSSE(backend, checkoutID, displayToken, timeoutSec)
|
|
|
246
247
|
}
|
|
247
248
|
// --- checkout QR plan ---
|
|
248
249
|
export function buildCheckoutQRPlan(input) {
|
|
249
|
-
const summary = `Scan the QR or open ${input.checkoutURL} to start the human checkout flow.`;
|
|
250
|
+
const summary = input.localSimulation ? "在本机打开模拟付款入口;铁路与地图查询真实,授权、通知和交易模拟,不会扣款。" : `Scan the QR or open ${input.checkoutURL} to start the human checkout flow.`;
|
|
250
251
|
const isPayment = input.paymentIntentID != null;
|
|
251
252
|
const afterCommand = qualifyItPayCommand(`itpay checkout --id ${input.checkoutID} --token ${input.displayToken}${input.locale === "en" ? " --locale en" : ""} --json`, input.agentType);
|
|
252
253
|
const platform = {
|
|
@@ -265,6 +266,7 @@ export function buildCheckoutQRPlan(input) {
|
|
|
265
266
|
};
|
|
266
267
|
const plan = {
|
|
267
268
|
kind: isPayment ? "payment_qr" : "checkout_qr",
|
|
269
|
+
...(input.localSimulation ? { localSimulation: true } : {}),
|
|
268
270
|
host: input.host,
|
|
269
271
|
summary,
|
|
270
272
|
url: input.qrPayload,
|
|
@@ -57,6 +57,7 @@ export async function runCheckoutPresentation(backend, options) {
|
|
|
57
57
|
const localizedPNGURL = localizeCardURL(qrPNGURL, locale);
|
|
58
58
|
const nextCommand = `itpay checkout --id ${options.checkoutID} --token ${options.displayToken}${locale === "en" ? " --locale en" : ""} --json`;
|
|
59
59
|
const plan = buildCheckoutQRPlan({
|
|
60
|
+
localSimulation: backend.localSimulation,
|
|
60
61
|
host,
|
|
61
62
|
checkoutID: options.checkoutID,
|
|
62
63
|
checkoutURL,
|
|
@@ -30,16 +30,17 @@ function hasCompleteCheckoutTokens(url) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
export function buildCheckoutHandoff(input) {
|
|
33
|
-
const
|
|
33
|
+
const url = input.plan?.localSimulation && input.mobileUrl && hasCompleteCheckoutTokens(input.mobileUrl) ? input.mobileUrl : input.url;
|
|
34
|
+
const handoff = { url, ...(input.plan?.localSimulation ? { environment: "local_simulation", query: "live", transactions: "simulated" } : {}) };
|
|
34
35
|
// mobile_url is only emitted when the link carries the complete token pair;
|
|
35
36
|
// a display-token-only link cannot finish the same-device exchange after payment.
|
|
36
|
-
const mobileUrl = hasCompleteCheckoutTokens(input.mobileUrl) ? input.mobileUrl : undefined;
|
|
37
|
+
const mobileUrl = !input.plan?.localSimulation && hasCompleteCheckoutTokens(input.mobileUrl) ? input.mobileUrl : undefined;
|
|
37
38
|
if (mobileUrl) {
|
|
38
39
|
handoff.mobile_url = mobileUrl;
|
|
39
40
|
}
|
|
40
41
|
const workBuddyAction = isWorkBuddyPlainChat(input.agentType, input.platform);
|
|
41
42
|
if (workBuddyAction) {
|
|
42
|
-
handoff.agent_action = buildWorkBuddyPresentFilesAction(
|
|
43
|
+
handoff.agent_action = buildWorkBuddyPresentFilesAction(url);
|
|
43
44
|
}
|
|
44
45
|
if (input.platform === "markdown") {
|
|
45
46
|
if (input.localPath)
|
|
@@ -58,7 +59,9 @@ export function buildCheckoutHandoff(input) {
|
|
|
58
59
|
}
|
|
59
60
|
return {
|
|
60
61
|
handoff,
|
|
61
|
-
instruction:
|
|
62
|
+
instruction: input.plan?.localSimulation
|
|
63
|
+
? `本地实验:铁路与地图查询真实,授权、通知和交易模拟,不会扣款。在本机打开 handoff.url 模拟付款入口,金额 ${input.amount};仅本机桌面可达。${workBuddyAction ? "按 handoff.agent_action 原样打开一次。" : "展示原入口。"}等待用户操作后读取同一 Checkout;不创建替代订单,用户声明不证明模拟付款已确认。`
|
|
64
|
+
: `先展示官方入口,再做非必要记忆或日志;保留必需安全检查和宿主权限。${checkoutHandoffInstruction(input.agentType, input.platform, input.amount, Boolean(mobileUrl))}`,
|
|
62
65
|
};
|
|
63
66
|
}
|
|
64
67
|
function checkoutHandoffInstruction(agentType, platform, amount, hasMobileLink) {
|
|
@@ -16,12 +16,14 @@ export class CommandContractError extends Error {
|
|
|
16
16
|
instruction;
|
|
17
17
|
recovery;
|
|
18
18
|
interaction;
|
|
19
|
-
|
|
19
|
+
result;
|
|
20
|
+
constructor(code, message, instruction, recovery, interaction, result) {
|
|
20
21
|
super(message);
|
|
21
22
|
this.code = code;
|
|
22
23
|
this.instruction = instruction;
|
|
23
24
|
this.recovery = recovery;
|
|
24
25
|
this.interaction = interaction;
|
|
26
|
+
this.result = result;
|
|
25
27
|
this.name = "CommandContractError";
|
|
26
28
|
}
|
|
27
29
|
}
|
|
@@ -12,6 +12,7 @@ export const INSTALL_AGENT_TYPES = [
|
|
|
12
12
|
"kimi-code",
|
|
13
13
|
"openclaw",
|
|
14
14
|
];
|
|
15
|
+
export const CODEX_WAIT_GUIDANCE = "Codex 宿主等待:保留完整工具返回,按实际返回的会话句柄及当前宿主续读工具收取最终输出,不要只取 stdout。若使用 functions.exec 包装,可用 text(await tools.exec_command(...));内层有 session_id 时用 write_stdin,外层返回运行 cell 时才用 wait。没有该包装时按宿主实际工具操作。先收取最终输出,再执行 CLI 业务 next;不要重复提交。";
|
|
15
16
|
const INSTRUCTIONS = {
|
|
16
17
|
"codex-desktop": "在 Codex Desktop 中始终传这个 Agent Type;付款时把返回的二维码和链接实际展示到当前对话。",
|
|
17
18
|
"codex-cli": "在 Codex CLI 中始终传这个 Agent Type;付款交接只应显示在用户可见终端。",
|
|
@@ -48,7 +49,7 @@ export function runInstall(target, options = {}) {
|
|
|
48
49
|
...installDefinition(normalized),
|
|
49
50
|
default_api: DEFAULT_BASE_URL,
|
|
50
51
|
},
|
|
51
|
-
instruction: INSTRUCTIONS[normalized],
|
|
52
|
+
instruction: INSTRUCTIONS[normalized] + (normalized.startsWith("codex-") ? ` ${CODEX_WAIT_GUIDANCE}` : ""),
|
|
52
53
|
next: {
|
|
53
54
|
command: `itpay --agent-type ${normalized} readyz --json`,
|
|
54
55
|
reason: "验证当前官方 ItPay API 的可用性",
|