@itpay/cli 2.0.0 → 2.0.2
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 +3 -3
- package/dist/src/commands/catalog.js +34 -8
- package/dist/src/commands/guidance.js +14 -5
- package/dist/src/commands/services.js +11 -1
- package/dist/src/main.js +1 -1
- package/dist/src/state/config.js +2 -2
- package/docs/agent/buyer/cart-checkout.json +2 -1
- package/docs/agent/buyer/catalog-list.json +4 -2
- package/docs/agent/buyer/install-and-setup.json +2 -2
- package/docs/agent/buyer/payment-flow.json +2 -2
- package/docs/agent/buyer/quickstart.json +3 -2
- package/package.json +1 -1
- package/skills/itpay-buyer/SKILL.md +6 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ itpay readyz
|
|
|
8
8
|
itpay docs show quickstart
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The CLI defaults to the production API at `https://api.itpay.ai`. Set
|
|
12
12
|
`ITPAY_BACKEND_URL` only when intentionally using another backend.
|
|
13
13
|
|
|
14
14
|
## Commands
|
|
@@ -28,7 +28,7 @@ This test release defaults to `https://test.itpay.ai`. Set
|
|
|
28
28
|
- `itpay services start <service_id>` — start a generic Service Execution run
|
|
29
29
|
- `itpay services invoke <service_execution_id> --capability <capability_id> --input key=value` — invoke an agent-visible capability
|
|
30
30
|
- `itpay services action <service_execution_id> --action <action_type> [--result-item <id>]` — record a human/agent service action
|
|
31
|
-
- `itpay services checkout <service_execution_id> --capability <capability_id> --email <email> [--host <host>] [--json]` — create quote lock from Service Execution state,
|
|
31
|
+
- `itpay services checkout <service_execution_id> --capability <capability_id> [--email <email>] [--host <host>] [--json]` — create quote lock from Service Execution state, require email only for capabilities that deliver a claim link, persist the handoff, and render the branded ItPay checkout
|
|
32
32
|
- `itpay services checkout <service_execution_id> --resume --json` — reissue a lost or expired handoff for the same unpaid checkout without asking for contact information again
|
|
33
33
|
- `itpay services next <service_execution_id> [--json]` — show the next recommended action from the Service Execution read model
|
|
34
34
|
- `itpay services get <service_execution_id>` / `itpay services events <service_execution_id>` — read the redacted Service Execution timeline
|
|
@@ -54,7 +54,7 @@ Aliases: `tg` and `openclaw-telegram` map to `telegram`; `feishu_im` and `fs` ma
|
|
|
54
54
|
|
|
55
55
|
## Environment
|
|
56
56
|
|
|
57
|
-
- `ITPAY_BACKEND_URL` — optional backend override (
|
|
57
|
+
- `ITPAY_BACKEND_URL` — optional backend override (default `https://api.itpay.ai`)
|
|
58
58
|
- `ITPAY_BEARER_TOKEN` — account-scoped session token (only needed for `orders`)
|
|
59
59
|
- `ITPAY_AGENT_DEVICE_ID` — agent device id, used for cart/service execution quota identity and `client_context`
|
|
60
60
|
- `ITPAY_CURRENCY` — checkout currency (default `CNY`)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { formatMoney } from "../render/output.js";
|
|
2
1
|
import { resolveOutput } from "../render/sink.js";
|
|
3
2
|
export async function runCatalogList(backend, options = {}) {
|
|
4
3
|
const manifest = await backend.getCatalogManifest();
|
|
@@ -8,19 +7,46 @@ export async function runCatalogList(backend, options = {}) {
|
|
|
8
7
|
out(JSON.stringify(manifest, null, 2) + "\n");
|
|
9
8
|
return;
|
|
10
9
|
}
|
|
11
|
-
out(`
|
|
10
|
+
out(`ItPay 当前上线 ${items.length} 个服务(目录版本 ${manifest.version})\n\n`);
|
|
12
11
|
for (const item of items) {
|
|
13
|
-
out(` ${item.
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
out(` ${item.title}\n`);
|
|
13
|
+
if (item.description)
|
|
14
|
+
out(` ${item.description}\n`);
|
|
15
|
+
if (item.service_flow) {
|
|
16
|
+
const discovery = item.service_flow.discovery;
|
|
17
|
+
const primary = item.service_flow.primary_service;
|
|
18
|
+
out(`\n 先做什么:${discovery.title}\n`);
|
|
19
|
+
out(` ${discovery.description}\n`);
|
|
20
|
+
if (discovery.free_quota_limit !== undefined) {
|
|
21
|
+
out(` 每台已登记设备可免费使用 ${discovery.free_quota_limit} 次。\n`);
|
|
22
|
+
}
|
|
23
|
+
if (discovery.paid_continuation) {
|
|
24
|
+
const continuation = discovery.paid_continuation;
|
|
25
|
+
out(` 免费次数用完后:${formatProductMoney(continuation.amount_minor, continuation.currency)}/次,继续使用该辅助步骤;结果直接返回给 agent${continuation.delivery_email_required ? ",需要用户提供收件邮箱" : ",不需要邮箱"}。\n`);
|
|
26
|
+
}
|
|
27
|
+
out(`\n 确认主体后:${primary.title},${formatProductMoney(primary.amount_minor, primary.currency)}/次\n`);
|
|
28
|
+
out(` ${primary.description}\n`);
|
|
29
|
+
if (primary.delivery_description)
|
|
30
|
+
out(` ${primary.delivery_description}\n`);
|
|
31
|
+
}
|
|
32
|
+
out(`\n 服务 ID:${item.service_id ?? "未发布"}`);
|
|
16
33
|
if (item.service_id)
|
|
17
|
-
out(
|
|
34
|
+
out(`(启动:itpay services start ${item.service_id})`);
|
|
35
|
+
out("\n");
|
|
18
36
|
if (item.variants.length > 0) {
|
|
19
|
-
out(`
|
|
37
|
+
out(` 可购买项目:\n`);
|
|
20
38
|
for (const variant of item.variants) {
|
|
21
|
-
out(` - ${variant.catalog_variant_id} ${variant.title} ${variant.offer_id} ${
|
|
39
|
+
out(` - ${variant.catalog_variant_id} ${variant.title} ${variant.offer_id} ${formatProductMoney(variant.amount_minor, variant.currency)}\n`);
|
|
22
40
|
}
|
|
23
41
|
}
|
|
24
42
|
out("\n");
|
|
25
43
|
}
|
|
26
44
|
}
|
|
45
|
+
function formatProductMoney(amountMinor, currency) {
|
|
46
|
+
return new Intl.NumberFormat("zh-CN", {
|
|
47
|
+
style: "currency",
|
|
48
|
+
currency,
|
|
49
|
+
minimumFractionDigits: 2,
|
|
50
|
+
maximumFractionDigits: 2,
|
|
51
|
+
}).format(amountMinor / 100);
|
|
52
|
+
}
|
|
@@ -106,9 +106,10 @@ export function buildServiceReadModelGuidance(model) {
|
|
|
106
106
|
deliveryBindings: model.delivery_bindings,
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
|
-
export function buildServiceInvokedGuidance(response) {
|
|
109
|
+
export function buildServiceInvokedGuidance(response, capabilities = []) {
|
|
110
110
|
return buildServiceGuidance({
|
|
111
111
|
execution: response.execution,
|
|
112
|
+
capabilities,
|
|
112
113
|
resultItems: response.result_items,
|
|
113
114
|
...(response.next_actions ? { backendNextActions: response.next_actions } : {}),
|
|
114
115
|
...(response.effective_quota ? { effectiveQuota: response.effective_quota } : {}),
|
|
@@ -155,9 +156,9 @@ export function buildServiceHandleGuidance(serviceExecutionID, checkoutCapabilit
|
|
|
155
156
|
actions.push({
|
|
156
157
|
id: "checkout_service",
|
|
157
158
|
label: "Create checkout after human confirmation",
|
|
158
|
-
command: `itpay services checkout ${serviceExecutionID} --capability ${checkoutCapabilityID} --
|
|
159
|
+
command: `itpay services checkout ${serviceExecutionID} --capability ${checkoutCapabilityID} --json`,
|
|
159
160
|
requires_human: true,
|
|
160
|
-
reason: "
|
|
161
|
+
reason: "Inspect the Service Execution first; the CLI will request delivery contact only when the selected capability requires it.",
|
|
161
162
|
});
|
|
162
163
|
}
|
|
163
164
|
return {
|
|
@@ -306,12 +307,16 @@ function buildServiceGuidance(input) {
|
|
|
306
307
|
else if (execution.checkout_required || execution.next_action === "create_checkout") {
|
|
307
308
|
const capabilityID = backendCheckout?.capability_id ?? paid?.capability_id ?? input.checkoutCapabilityID ?? execution.current_capability_id;
|
|
308
309
|
if (capabilityID) {
|
|
310
|
+
const checkoutCapability = capabilities.find((capability) => capability.capability_id === capabilityID);
|
|
311
|
+
const emailRequired = checkoutCapability?.delivery_email_required === true;
|
|
309
312
|
nextActions.push({
|
|
310
313
|
id: "checkout_service",
|
|
311
314
|
label: "Create ItPay checkout for the paid service capability",
|
|
312
|
-
command: `itpay services checkout ${execution.service_execution_id} --capability ${capabilityID} --email <email> --json`,
|
|
315
|
+
command: `itpay services checkout ${execution.service_execution_id} --capability ${capabilityID}${emailRequired ? " --email <email>" : ""} --json`,
|
|
313
316
|
requires_human: true,
|
|
314
|
-
reason:
|
|
317
|
+
reason: emailRequired
|
|
318
|
+
? "Ask the human for their email. It is used to send the protected result claim link; never invent or substitute an address."
|
|
319
|
+
: "This capability returns an agent-visible result after payment and does not require a delivery email.",
|
|
315
320
|
});
|
|
316
321
|
}
|
|
317
322
|
else {
|
|
@@ -384,6 +389,10 @@ function buildServiceGuidance(input) {
|
|
|
384
389
|
capability_id: capability.capability_id,
|
|
385
390
|
agent_visible: capability.agent_visible,
|
|
386
391
|
requires_payment: capability.requires_payment,
|
|
392
|
+
vault_required: capability.vault_required,
|
|
393
|
+
delivery_email_required: capability.delivery_email_required,
|
|
394
|
+
price_amount_minor: capability.price_amount_minor,
|
|
395
|
+
price_currency: capability.price_currency,
|
|
387
396
|
free_quota_limit: capability.free_quota_limit,
|
|
388
397
|
})),
|
|
389
398
|
result_items: (input.resultItems ?? []).map((item) => ({
|
|
@@ -27,7 +27,17 @@ export async function runServicesInvoke(backend, config, serviceExecutionID, cap
|
|
|
27
27
|
idempotency_key: idempotencyKey,
|
|
28
28
|
redacted_summary: input,
|
|
29
29
|
});
|
|
30
|
-
|
|
30
|
+
let capabilities = [];
|
|
31
|
+
if (response.next_actions?.some((action) => action.kind === "create_checkout")) {
|
|
32
|
+
try {
|
|
33
|
+
capabilities = (await backend.getServiceExecution(serviceExecutionID)).capabilities;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Preserve the successful invocation response. Checkout performs the same
|
|
37
|
+
// capability-aware email validation before creating a handoff.
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const guidance = buildServiceInvokedGuidance(response, capabilities);
|
|
31
41
|
if (options.jsonOutput) {
|
|
32
42
|
writeJSON(options.output, attachAgentGuidance(response, guidance));
|
|
33
43
|
return;
|
package/dist/src/main.js
CHANGED
|
@@ -24,7 +24,7 @@ program
|
|
|
24
24
|
.name("itpay")
|
|
25
25
|
.description("V3 ItPay CLI — checkout, payment, order, and refund commands")
|
|
26
26
|
.option("--agent-type <type>", "agent runtime type used for device enrollment and client-specific guidance")
|
|
27
|
-
.version("2.0.
|
|
27
|
+
.version("2.0.2");
|
|
28
28
|
function withHost(value) {
|
|
29
29
|
const host = normalizeHost(value);
|
|
30
30
|
if (!host) {
|
package/dist/src/state/config.js
CHANGED
|
@@ -8,8 +8,8 @@ import { HttpClient } from "../client/http.js";
|
|
|
8
8
|
import { BackendClient } from "../client/backend.js";
|
|
9
9
|
import { DeviceAuthority } from "./device_authority.js";
|
|
10
10
|
import { OperationJournal } from "./operation_journal.js";
|
|
11
|
-
export const DEFAULT_BASE_URL = "https://
|
|
12
|
-
export const CLI_VERSION = "2.0.
|
|
11
|
+
export const DEFAULT_BASE_URL = "https://api.itpay.ai";
|
|
12
|
+
export const CLI_VERSION = "2.0.2";
|
|
13
13
|
export const API_CONTRACT_REVISION = "sha256:2c2829f4618c47bc505efc0ded853cf639d775585ba13aa23012197e39efa31f";
|
|
14
14
|
const CART_SESSION_DEFAULT_DIR = ".itpay-v3";
|
|
15
15
|
const CART_SESSION_FILENAME = "cart.json";
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
60
|
"intent": "create quote lock and checkout for a service-backed cart item",
|
|
61
|
-
"command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> --email <email> --json",
|
|
61
|
+
"command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> [--email <email>] --json",
|
|
62
62
|
"success_signal": "the quote lock is bound to the original server cart item when present; JSON includes checkout_id and display_token"
|
|
63
63
|
},
|
|
64
64
|
{
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
"Do not remove quote-locked or checkout-bound cart lines. Continue checkout/payment or use refund/cancel owner flow after payment.",
|
|
77
77
|
"If required contact data is missing, prefer --require-contact so the CLI can emit a structured interaction request.",
|
|
78
78
|
"Do not invent buyer email or phone values; let the human provide them when required.",
|
|
79
|
+
"Only request --email when the selected capability declares delivery_email_required. Tell the buyer it sends the protected result claim link.",
|
|
79
80
|
"The happy-path buy flow creates cart and checkout, then renders checkout_qr. It should not create a payment intent first."
|
|
80
81
|
],
|
|
81
82
|
"forbidden": [
|
|
@@ -17,14 +17,16 @@
|
|
|
17
17
|
}
|
|
18
18
|
],
|
|
19
19
|
"output_interpretation": {
|
|
20
|
-
"item_format": "Each item
|
|
20
|
+
"item_format": "Each item includes product description, a structured service_flow, valid IDs, and purchasable offers.",
|
|
21
|
+
"service_flow": "Explain discovery as an auxiliary identity-confirmation step, including free quota and paid continuation. Present primary_service as the actual paid outcome. Read all values from the manifest.",
|
|
21
22
|
"variant_selection": "To buy, the buyer needs catalog_item_id, catalog_variant_id, and offer_id from the output.",
|
|
22
23
|
"price_note": "amount_minor is in minor units (e.g., 10000 = 100.00 CNY). The CLI formats prices as XX.YY currency automatically."
|
|
23
24
|
},
|
|
24
25
|
"agent_rules": [
|
|
25
26
|
"Use `itpay catalog list` before suggesting purchase options.",
|
|
26
27
|
"Read the variant IDs and prices from the output; do not invent them.",
|
|
27
|
-
"
|
|
28
|
+
"Explain the customer journey from service_flow instead of presenting every variant as an unrelated service.",
|
|
29
|
+
"State free quota, paid continuation price, email requirement, and claim purpose exactly as published; do not exaggerate or omit conditions.",
|
|
28
30
|
"If the buyer wants to search by keyword, filter the catalog output client-side (no backend search yet)."
|
|
29
31
|
],
|
|
30
32
|
"next_docs": [
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"env_vars": {
|
|
30
30
|
"ITPAY_BACKEND_URL": {
|
|
31
31
|
"required": false,
|
|
32
|
-
"description": "Optional V3 backend override.
|
|
32
|
+
"description": "Optional V3 backend override. The CLI defaults to https://api.itpay.ai.",
|
|
33
33
|
"examples": ["http://localhost:18080", "https://test.itpay.ai"]
|
|
34
34
|
},
|
|
35
35
|
"ITPAY_BEARER_TOKEN": {
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"lark": "Use --host lark --target <open_id>. Same as feishu format."
|
|
64
64
|
},
|
|
65
65
|
"agent_rules": [
|
|
66
|
-
"Use the built-in https://
|
|
66
|
+
"Use the built-in https://api.itpay.ai production default; override ITPAY_BACKEND_URL only for another deliberate environment.",
|
|
67
67
|
"Install globally with npm install -g @itpay/cli for all hosts.",
|
|
68
68
|
"Identify the real runtime with --agent-type or ITPAY_AGENT_TYPE; do not invent a new type to obtain quota.",
|
|
69
69
|
"Run `itpay install` without arguments to see all supported targets.",
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"intent": "create service-execution quote lock and render ItPay checkout page handoff",
|
|
20
|
-
"command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> --email <email>",
|
|
20
|
+
"command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> [--email <email>]",
|
|
21
21
|
"success_signal": "The quote lock is bound to the original server cart item when present; ItPay checkout QR/URL is rendered for the human; the checkout page handles authorization and provider payment."
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"intent": "create service-execution checkout with machine-readable handoff",
|
|
25
|
-
"command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> --email <email> --json",
|
|
25
|
+
"command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> [--email <email>] --json",
|
|
26
26
|
"success_signal": "JSON with kind='checkout_handoff_required', next_action='open_human_checkout', checkout_url, display_token, qr_png_url, and brand_qr_local_path."
|
|
27
27
|
},
|
|
28
28
|
{
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"required_state": {
|
|
13
13
|
"needs": [
|
|
14
14
|
"itpay CLI installed",
|
|
15
|
-
"
|
|
15
|
+
"production API at https://api.itpay.ai, or an intentional ITPAY_BACKEND_URL override",
|
|
16
16
|
"catalog item id, variant id, and offer id from `itpay catalog list`",
|
|
17
17
|
"real agent runtime type supplied through --agent-type or ITPAY_AGENT_TYPE"
|
|
18
18
|
],
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
"intent": "create checkout from a confirmed service execution and render human handoff",
|
|
83
|
-
"command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> --email <email> --json",
|
|
83
|
+
"command": "itpay services checkout <service_execution_id> --capability <paid_capability_id> [--email <email>] --json",
|
|
84
84
|
"success_signal": "quote lock is bound to the server cart item when present; JSON includes checkout_id, display_token, checkout_url, qr_png_url, and brand_qr_local_path"
|
|
85
85
|
},
|
|
86
86
|
{
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
"For service-backed catalog items, read service_execution_id from `itpay cart add --json` before invoking service capabilities.",
|
|
135
135
|
"Do not use --pay or itpay pay for the normal buyer flow; first show the ItPay checkout QR/URL so the human enters the checkout page.",
|
|
136
136
|
"If buy emits an interaction request for missing contact fields, collect values and rerun with --contact-email/--contact-phone.",
|
|
137
|
+
"For services checkout, include --email only when next_actions includes it. Explain that protected delivery uses it to send the claim link; agent-visible paid results do not require email.",
|
|
137
138
|
"Do not assume checkout implies payment succeeded; it only creates a handoff.",
|
|
138
139
|
"Payment success is confirmed by backend checkout/order state, not by QR display or buyer claim.",
|
|
139
140
|
"A human grant applies only to its service execution and expires after 15 minutes; do not claim access to other orders or executions.",
|
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@ itpay readyz
|
|
|
20
20
|
itpay docs show quickstart
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
The CLI defaults to `https://api.itpay.ai`. Set `ITPAY_BACKEND_URL`
|
|
24
24
|
only for an intentional override.
|
|
25
25
|
|
|
26
26
|
Every commerce flow must identify the real runtime. Pass the global option
|
|
@@ -59,9 +59,13 @@ the checkout with the exact server-selected capability:
|
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
61
|
itpay --agent-type <agent_type> services checkout <service_execution_id> \
|
|
62
|
-
--capability <capability_id> --email <human_email> --host <host> --json
|
|
62
|
+
--capability <capability_id> [--email <human_email>] --host <host> --json
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
Include `--email` only when the CLI's `next_actions` command includes it. For a
|
|
66
|
+
protected delivery, explain that the address receives the order claim link;
|
|
67
|
+
never invent an address. Agent-visible paid results do not require email.
|
|
68
|
+
|
|
65
69
|
5. Show both handoff forms to the human:
|
|
66
70
|
|
|
67
71
|
- Attach `brand_qr_local_path` when `brand_qr_status` is `downloaded`.
|