@itpay/cli 0.1.0

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.
@@ -0,0 +1,86 @@
1
+ {
2
+ "schema_version": "itp.agent_doc.v1",
3
+ "role": "buyer",
4
+ "topic": "quickstart",
5
+ "title": "ItPay Buyer Agent Quickstart",
6
+ "purpose": "Teach a new external agent the minimal safe flow for buying through ItPay.",
7
+ "when_to_use": [
8
+ "The agent has just installed the ItPay CLI or loaded the buyer skill.",
9
+ "The user wants the agent to search for a service, recommend an option, or buy through ItPay.",
10
+ "The agent is unsure which ItPay buyer command should come first."
11
+ ],
12
+ "required_state": {
13
+ "needs": ["itp CLI available", "buyer delivery email before checkout"],
14
+ "must_not_need": ["ops token", "claim token", "raw key", "provider raw payload"]
15
+ },
16
+ "commands": [
17
+ {
18
+ "intent": "list the available agent docs topics",
19
+ "command": "itp docs list --role buyer --json",
20
+ "success_signal": "response.topics contains catalog-search, cart-checkout, payment-wait, secure-delivery"
21
+ },
22
+ {
23
+ "intent": "search the public catalog for the current user request",
24
+ "command": "itp buyer catalog search --query \"<user request>\" --json",
25
+ "success_signal": "response.products contains public products and variants"
26
+ },
27
+ {
28
+ "intent": "search standardized API services with category/facet filters when intent is clear",
29
+ "command": "itp buyer catalog search --query \"企业工商信息 查询\" --category business_data_api --provider itpay_enterprise_data --service-type ai_api --json",
30
+ "success_signal": "response.products are narrowed by category/facet before recommendation"
31
+ },
32
+ {
33
+ "intent": "buy a selected variant with the high-level cart-first flow",
34
+ "command": "itp buy <variant_id> --sandbox --email <buyer_email> --phone <buyer_phone> --json",
35
+ "success_signal": "response.status becomes waiting_human_auth, waiting_user_payment, payment_verified, or delivery_claimable"
36
+ }
37
+ ],
38
+ "agent_rules": [
39
+ "Use --json for every ItPay command.",
40
+ "Search and explain options before buying unless the user already named a variant.",
41
+ "Add the selected UCP Variant.id to cart; do not bypass cart for CORE-028 flows.",
42
+ "Before checkout, make sure a buyer delivery email is available. If no email is known from the current buyer context, ask the human for it before creating checkout.",
43
+ "Do not invent, guess, or use a placeholder email. Secure delivery and account/order access depend on the buyer email.",
44
+ "For first purchase, show auth_qr as the ItPay first-purchase entry: the human first approves provider login/registration/profile sharing, then ItPay should continue the same checkout to payment.",
45
+ "After showing auth_qr, keep running/resuming the same checkout unless the human explicitly asks you to pause. Do not stop merely because a QR was displayed.",
46
+ "Use high-level itp buy when possible; it is designed to show the first-purchase entry, wait/resume, continue to payment, wait for verification, and poll delivery.",
47
+ "Show the returned payment QR exactly as provided.",
48
+ "Payment truth comes only from payment_intent.verified.",
49
+ "Secure delivery goes to the human first; report redacted delivery status only."
50
+ ],
51
+ "forbidden": [
52
+ "Do not call ops commands from the buyer path.",
53
+ "Do not call worker run-once, provider query recovery, or fixture evidence routes.",
54
+ "Do not ask the user to paste raw keys, claim links, claim tokens, provider payloads, or secrets.",
55
+ "Do not rewrite, shorten, re-encode, or invent QR URLs.",
56
+ "Do not treat user text like 'I paid' as payment proof."
57
+ ],
58
+ "next_docs": [
59
+ {
60
+ "condition": "Need to discover or compare services",
61
+ "topic": "catalog-search",
62
+ "command": "itp docs show catalog-search --role buyer --json"
63
+ },
64
+ {
65
+ "condition": "User asks which option to choose",
66
+ "topic": "product-recommendation",
67
+ "command": "itp docs show product-recommendation --role buyer --json"
68
+ },
69
+ {
70
+ "condition": "A variant is selected and the agent needs to create cart/checkout",
71
+ "topic": "cart-checkout",
72
+ "command": "itp docs show cart-checkout --role buyer --json"
73
+ },
74
+ {
75
+ "condition": "The agent is unsure what is forbidden",
76
+ "topic": "safety-policy",
77
+ "command": "itp docs show safety-policy --role buyer --json"
78
+ },
79
+ {
80
+ "condition": "The user asks to view their ItPay account or previous orders",
81
+ "topic": "account-portal",
82
+ "command": "itp docs show account-portal --role buyer --json"
83
+ }
84
+ ],
85
+ "search_terms": ["start", "quickstart", "first time", "buyer flow", "how to use itpay", "开始", "第一次", "怎么用"]
86
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "schema_version": "itp.agent_doc.v1",
3
+ "role": "buyer",
4
+ "topic": "recovery",
5
+ "title": "Safe Recovery",
6
+ "purpose": "Teach the agent how to recover without duplicating orders or crossing into ops authority.",
7
+ "when_to_use": [
8
+ "A command timed out.",
9
+ "The agent lost local context.",
10
+ "The human reports QR scan trouble.",
11
+ "Checkout or delivery is pending."
12
+ ],
13
+ "required_state": {
14
+ "needs": ["last known checkout_id, payment_intent_id, or variant_id"],
15
+ "must_not_need": ["ops token", "provider raw payload", "claim token"]
16
+ },
17
+ "commands": [
18
+ {
19
+ "intent": "resume checkout state",
20
+ "command": "itp buyer checkout resume <checkout_id> --json",
21
+ "success_signal": "response.status and agent_next_actions describe the safe next action"
22
+ },
23
+ {
24
+ "intent": "wait again on the same payment intent",
25
+ "command": "itp buyer payment wait <payment_intent_id> --json",
26
+ "success_signal": "response.payment_event.event_type is payment_intent.verified or still waiting"
27
+ },
28
+ {
29
+ "intent": "refresh display QR only",
30
+ "command": "itp buyer payment refresh-qr <payment_intent_id> --reason order-not-found --json",
31
+ "success_signal": "response.payment_intent.qr_image_url is present"
32
+ }
33
+ ],
34
+ "agent_rules": [
35
+ "Prefer resume over creating a new checkout.",
36
+ "A timeout does not prove failure.",
37
+ "Use the same checkout_id/cart_id/payment_intent_id whenever possible.",
38
+ "Report safe error messages only."
39
+ ],
40
+ "forbidden": [
41
+ "Do not call ops sandbox worker or provider query from buyer flow.",
42
+ "Do not create duplicate checkout after transient wait timeout.",
43
+ "Do not ask the user to paste secrets, claim links, or raw provider data."
44
+ ],
45
+ "next_docs": [
46
+ {
47
+ "condition": "QR needs display refresh",
48
+ "topic": "qr-refresh",
49
+ "command": "itp docs show qr-refresh --role buyer --json"
50
+ },
51
+ {
52
+ "condition": "Payment still waiting",
53
+ "topic": "payment-wait",
54
+ "command": "itp docs show payment-wait --role buyer --json"
55
+ },
56
+ {
57
+ "condition": "Delivery is claimable",
58
+ "topic": "secure-delivery",
59
+ "command": "itp docs show secure-delivery --role buyer --json"
60
+ }
61
+ ],
62
+ "search_terms": ["recover", "resume", "timeout", "lost", "retry", "stuck", "恢复", "重试", "卡住", "没返回", "断了", "找不到"]
63
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "schema_version": "itp.agent_doc.v1",
3
+ "role": "buyer",
4
+ "topic": "safety-policy",
5
+ "title": "Buyer Agent Safety Policy",
6
+ "purpose": "Define the non-negotiable safety rules for ItPay buyer agents.",
7
+ "when_to_use": [
8
+ "The agent is unsure whether a command or data access is allowed.",
9
+ "The user asks the agent to reveal, fetch, or paste protected content.",
10
+ "The agent is deciding between buyer and ops commands."
11
+ ],
12
+ "required_state": {
13
+ "needs": ["role=buyer"],
14
+ "must_not_need": ["ops token", "raw secret access"]
15
+ },
16
+ "commands": [
17
+ {
18
+ "intent": "read this safety policy",
19
+ "command": "itp docs show safety-policy --role buyer --json",
20
+ "success_signal": "forbidden list is present"
21
+ },
22
+ {
23
+ "intent": "return to quickstart after safety check",
24
+ "command": "itp docs show quickstart --role buyer --json",
25
+ "success_signal": "quickstart topic is returned"
26
+ }
27
+ ],
28
+ "agent_rules": [
29
+ "Buyer agent authority is public discovery, cart/checkout creation, QR presentation, payment wait, and redacted delivery status.",
30
+ "Payment success must be verified by ItPay, not by user text or local inference.",
31
+ "Secure delivery is human-first.",
32
+ "If a request requires raw secret access, explain that ItPay blocks agent access by design."
33
+ ],
34
+ "forbidden": [
35
+ "No ops token in buyer flow.",
36
+ "No worker run-once in buyer flow.",
37
+ "No provider query recovery in buyer flow.",
38
+ "No fixture evidence route.",
39
+ "No raw key, redeem code, claim token, claim URL, storage ref, provider raw payload, buyer profile value, or session token in chat.",
40
+ "No QR URL rewriting.",
41
+ "No fake/mock/offline payment unless the user explicitly asks for offline simulation."
42
+ ],
43
+ "next_docs": [
44
+ {
45
+ "condition": "Need the normal flow",
46
+ "topic": "quickstart",
47
+ "command": "itp docs show quickstart --role buyer --json"
48
+ },
49
+ {
50
+ "condition": "Need delivery boundary details",
51
+ "topic": "secure-delivery",
52
+ "command": "itp docs show secure-delivery --role buyer --json"
53
+ }
54
+ ],
55
+ "search_terms": ["policy", "forbidden", "security", "secret", "ops", "安全", "禁止", "权限"]
56
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "schema_version": "itp.agent_doc.v1",
3
+ "role": "buyer",
4
+ "topic": "secure-delivery",
5
+ "title": "Secure Delivery Status",
6
+ "purpose": "Teach the agent how to handle ItPay secure delivery without seeing protected content.",
7
+ "when_to_use": [
8
+ "Payment was verified.",
9
+ "Checkout status mentions delivery_claimable, check_email, or claim_link_sent.",
10
+ "The user asks where the purchased key/content is."
11
+ ],
12
+ "required_state": {
13
+ "needs": ["checkout_id"],
14
+ "must_not_need": ["claim token", "claim link", "raw key", "storage ref"]
15
+ },
16
+ "commands": [
17
+ {
18
+ "intent": "check redacted delivery status",
19
+ "command": "itp buyer checkout status <checkout_id> --json",
20
+ "success_signal": "delivery.sensitive_content_redacted == true"
21
+ },
22
+ {
23
+ "intent": "list agent-safe delivery state",
24
+ "command": "itp buyer deliveries list --checkout <checkout_id> --json",
25
+ "success_signal": "response.deliveries contains no raw content or claim token"
26
+ },
27
+ {
28
+ "intent": "after the human says they granted agent access, discover the current agent's grants",
29
+ "command": "itp buyer vault grants list --checkout <checkout_id> --json",
30
+ "success_signal": "response.agent_readable_grants contains only grants for this exact agent device"
31
+ }
32
+ ],
33
+ "agent_rules": [
34
+ "Tell the human to check email or the ItPay human claim UI.",
35
+ "Agent-visible status may say delivery_claimable/check_email/claim_link_sent.",
36
+ "Raw protected content is human-first unless the human later shares it outside ItPay.",
37
+ "If the user wants analysis, comparison, installation help, or structured use of the delivered result, you may ask the human to use the ItPay page's 'Give to Agent / 一键给 Agent' Passkey flow.",
38
+ "If the human uses the portal's one-key agent authorization, discover the resulting grant with buyer vault commands; do not ask the human to paste content or grant IDs.",
39
+ "Do not ask the human to paste the key into chat."
40
+ ],
41
+ "forbidden": [
42
+ "Do not call the secure claim URL as an agent API.",
43
+ "Do not request or print claim token, claim URL, raw key, redeem code, or storage ref.",
44
+ "Do not scrape the human claim UI.",
45
+ "Do not claim installation is complete unless a later human-granted install flow says so."
46
+ ],
47
+ "next_docs": [
48
+ {
49
+ "condition": "Human asks what the claim page is",
50
+ "topic": "human-claim-ui",
51
+ "command": "itp docs show human-claim-ui --role buyer --json"
52
+ },
53
+ {
54
+ "condition": "Human asks to view account or order history",
55
+ "topic": "account-portal",
56
+ "command": "itp docs show account-portal --role buyer --json"
57
+ },
58
+ {
59
+ "condition": "Human says they approved agent access with Passkey",
60
+ "topic": "vault-agent-read",
61
+ "command": "itp docs show vault-agent-read --role buyer --json"
62
+ },
63
+ {
64
+ "condition": "Delivery is not ready yet",
65
+ "topic": "recovery",
66
+ "command": "itp docs show recovery --role buyer --json"
67
+ }
68
+ ],
69
+ "search_terms": ["delivery", "claim", "email", "key", "redeem", "secure delivery", "交付", "邮件", "领取", "密钥"]
70
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "schema_version": "itp.agent_doc.v1",
3
+ "role": "buyer",
4
+ "topic": "vault-agent-read",
5
+ "title": "Human-Approved Vault Agent Read",
6
+ "purpose": "Teach the agent how to read only the artifact fields that the human explicitly approved with Passkey.",
7
+ "when_to_use": [
8
+ "The human opened the ItPay account portal and selected one-key agent authorization.",
9
+ "The user asks whether the agent can now see a purchased report or selected fields.",
10
+ "A checkout/order has delivered a vault artifact and the human granted agent-readable access."
11
+ ],
12
+ "required_state": {
13
+ "needs": ["authenticated buyer account session", "current agent device binding", "order_id or checkout_id or vault_artifact_id"],
14
+ "must_not_need": ["human portal token", "claim token", "passkey credential", "raw protected payload", "grant id copied by the human"]
15
+ },
16
+ "commands": [
17
+ {
18
+ "intent": "check whether this agent has active human-approved grants for a checkout",
19
+ "command": "itp buyer vault grants list --checkout <checkout_id> --json",
20
+ "success_signal": "response.agent_readable_grants is an array; count > 0 means the human has granted this exact agent access"
21
+ },
22
+ {
23
+ "intent": "check whether this agent has active human-approved grants for one order or artifact",
24
+ "command": "itp buyer vault grants list --order <order_id> --artifact <vault_artifact_id> --json",
25
+ "success_signal": "only grants scoped to this logged-in agent device are returned"
26
+ },
27
+ {
28
+ "intent": "read a discovered grant view",
29
+ "command": "itp buyer vault grants read <agent_read_grant_id> --json",
30
+ "success_signal": "response.grant contains selected_fields, structured_view, or summary according to the human-approved scope"
31
+ },
32
+ {
33
+ "intent": "convenience read by order/artifact without asking the human for grant id",
34
+ "command": "itp buyer vault read --order <order_id> --artifact <vault_artifact_id> --json",
35
+ "success_signal": "the CLI discovers the active grant and reads its scoped view"
36
+ }
37
+ ],
38
+ "agent_rules": [
39
+ "Only read through `buyer vault` commands after the human has explicitly approved the agent grant in the ItPay portal.",
40
+ "Do not ask the human to copy or paste `agent_read_grant_id`; discover it with `buyer vault grants list`.",
41
+ "If no grant is returned, tell the human to open their ItPay account portal, reveal with Passkey, choose fields, and confirm one-key agent authorization.",
42
+ "Use only fields returned in the grant view. Do not infer that unreturned fields are accessible.",
43
+ "If the command returns 401 or buyer_session_invalid, run `itp buyer auth status --json` and ask the human to reauthorize through a normal checkout/account flow."
44
+ ],
45
+ "forbidden": [
46
+ "Do not open, scrape, or screenshot the human portal to obtain protected content.",
47
+ "Do not request passkey credentials, portal tokens, claim links, claim tokens, storage refs, provider AppCode, provider keys, or raw payloads.",
48
+ "Do not use another agent's grant id. Grants are scoped to the exact buyer account session and agent device.",
49
+ "Do not cache selected fields beyond the task context unless the user explicitly asks you to create a local artifact."
50
+ ],
51
+ "next_docs": [
52
+ {
53
+ "condition": "The human needs a portal link to grant access",
54
+ "topic": "account-portal",
55
+ "command": "itp docs show account-portal --role buyer --json"
56
+ },
57
+ {
58
+ "condition": "The order was delivered but no grant exists",
59
+ "topic": "secure-delivery",
60
+ "command": "itp docs show secure-delivery --role buyer --json"
61
+ },
62
+ {
63
+ "condition": "The agent is unsure what it may read",
64
+ "topic": "safety-policy",
65
+ "command": "itp docs show safety-policy --role buyer --json"
66
+ }
67
+ ],
68
+ "search_terms": ["vault", "agent read", "passkey grant", "one key agent", "授权给 agent", "可读授权", "字段授权", "查看报告"]
69
+ }
package/e2e-local.sh ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env sh
2
+ set -eu
3
+
4
+ ROOT=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
+ API_BASE=${VOLTAGENT_API_BASE:-http://localhost:3000}
6
+ NODE=${NODE:-$(command -v node)}
7
+
8
+ TMP_HOME=$(mktemp -d "${TMPDIR:-/tmp}/voltagent-itp-e2e-home.XXXXXX")
9
+ TMP_SETUP_HOME=$(mktemp -d "${TMPDIR:-/tmp}/voltagent-itp-setup-home.XXXXXX")
10
+ TMP_SETUP_NOWAIT_HOME=$(mktemp -d "${TMPDIR:-/tmp}/voltagent-itp-setup-nowait-home.XXXXXX")
11
+
12
+ cleanup() {
13
+ rm -rf "$TMP_HOME" "$TMP_SETUP_HOME" "$TMP_SETUP_NOWAIT_HOME"
14
+ }
15
+ trap cleanup EXIT INT TERM
16
+
17
+ itp_home() {
18
+ itp_home_dir="$1"
19
+ shift
20
+ attempt=0
21
+ while :; do
22
+ err_file="$itp_home_dir/itp-error.log"
23
+ if out=$(HOME="$itp_home_dir" PATH=/nonexistent VOLTAGENT_API_BASE="$API_BASE" "$NODE" "$ROOT/bin/itp" "$@" 2>"$err_file"); then
24
+ printf '%s' "$out"
25
+ return 0
26
+ fi
27
+ status=$?
28
+ error_text=$(cat "$err_file" 2>/dev/null || true)
29
+ attempt=$((attempt + 1))
30
+ if [ "$attempt" -lt 6 ] && printf '%s' "$error_text" | grep -q 'request failed: 429'; then
31
+ sleep "$attempt"
32
+ continue
33
+ fi
34
+ printf '%s\n' "$error_text" >&2
35
+ return "$status"
36
+ done
37
+ }
38
+
39
+ itp() {
40
+ itp_home "$TMP_HOME" "$@"
41
+ }
42
+
43
+ json_get() {
44
+ "$NODE" -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const v=JSON.parse(d); const path=process.argv[1].split('.'); let cur=v; for (const p of path) cur=cur?.[p]; if (cur === undefined || cur === null) process.exit(2); process.stdout.write(String(cur));})" "$1"
45
+ }
46
+
47
+ json_assert() {
48
+ "$NODE" -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const v=JSON.parse(d); const fn = new Function('v', process.argv[1]); if (!fn(v)) process.exit(1);})" "$1"
49
+ }
50
+
51
+ printf 'checking server %s\n' "$API_BASE" >&2
52
+ curl -fsS "$API_BASE/api/status" >/dev/null
53
+ curl -fsS "$API_BASE/api/itp/plans" | json_assert "return v.success === true && v.data.plans.some(p => p.plan_id === 'credit-100') && v.data.unit_rule === '1 credit = 1 CNY'" >/dev/null
54
+
55
+ printf 'running one-command setup flow\n' >&2
56
+ SETUP=$(itp_home "$TMP_SETUP_HOME" setup --credits 100 --method fake --mock-approve --allow-fake --offline --json)
57
+ printf '%s' "$SETUP" | json_assert "return v.status === 'grant_ready' && v.target === 'generic' && v.grant_id && v.base_url && v.openai_base_url && v.credential && v.credential.stored === true && v.auth && v.auth.session_stored === true && v.runtime_install.status === 'skipped'"
58
+ test ! -f "$TMP_SETUP_HOME/.codex/config.toml"
59
+ TOKEN_FROM_SETUP=$(HOME="$TMP_SETUP_HOME" PATH=/nonexistent VOLTAGENT_API_BASE="$API_BASE" "$NODE" "$ROOT/bin/itp" token issue --grant "$(printf '%s' "$SETUP" | json_get grant_id)" --stdout)
60
+ case "$TOKEN_FROM_SETUP" in
61
+ sk-*) ;;
62
+ *) echo "setup token issue did not return sk-* token" >&2; exit 1 ;;
63
+ esac
64
+
65
+ printf 'checking setup no-wait auth handoff\n' >&2
66
+ SETUP_NOWAIT=$(itp_home "$TMP_SETUP_NOWAIT_HOME" setup --credits 100 --method fake --allow-fake --no-wait --json)
67
+ printf '%s' "$SETUP_NOWAIT" | json_assert "return v.status === 'waiting_human_auth' && v.action === 'scan_alipay_auth' && v.run_id && v.auth_id && v.user_code && v.verification_uri_complete && v.human_action && v.human_action.display.length > 0"
68
+ SETUP_NOWAIT_STATUS=$(itp_home "$TMP_SETUP_NOWAIT_HOME" status --json)
69
+ printf '%s' "$SETUP_NOWAIT_STATUS" | json_assert "return v.status === 'waiting_human_auth' && v.run_id && v.auth_id && v.next && v.next.command.includes('resume')"
70
+ SETUP_RESUMED=$(itp_home "$TMP_SETUP_NOWAIT_HOME" resume --mock-approve --allow-fake --offline --json)
71
+ printf '%s' "$SETUP_RESUMED" | json_assert "return v.status === 'grant_ready' && v.run_id && v.grant_id && v.credential && v.credential.stored === true"
72
+
73
+ USERNAME="e2e-$(date +%Y%m%d%H%M%S)-$$"
74
+ printf 'registering %s\n' "$USERNAME" >&2
75
+ AUTH=$(itp auth register --runtime codex --mock-approve --allow-fake --alipay-user-id "2088$RANDOM$RANDOM" --json)
76
+ printf '%s' "$AUTH" | json_assert "return v.account_id && v.device_id && v.session_stored === true"
77
+
78
+ ACCOUNT=$(itp account show --json)
79
+ printf '%s' "$ACCOUNT" | json_assert "return v.password_set === false && v.account && v.account.account_id"
80
+
81
+ printf 'setting first password\n' >&2
82
+ printf 'secret123\n' | itp account set-password --password-stdin --json | json_assert "return v.password_set === true"
83
+ ACCOUNT=$(itp account show --json)
84
+ printf '%s' "$ACCOUNT" | json_assert "return v.password_set === true"
85
+
86
+ printf 'creating fake checkout\n' >&2
87
+ CHECKOUT=$(itp checkout create --credits 100 --method fake --allow-fake --idempotency-key "e2e-$USERNAME" --json)
88
+ CHECKOUT_ID=$(printf '%s' "$CHECKOUT" | json_get checkout_id)
89
+ GRANT_ID=$(printf '%s' "$CHECKOUT" | json_get grant_id)
90
+ printf '%s' "$CHECKOUT" | json_assert "return v.status === 'grant_issued' && v.grant_id && !v.payment.cashier_url"
91
+
92
+ printf 'waiting payment %s\n' "$CHECKOUT_ID" >&2
93
+ PAYMENT=$(itp payment wait "$CHECKOUT_ID" --timeout 10 --json)
94
+ printf '%s' "$PAYMENT" | json_assert "return v.status === 'grant_issued' && v.grant_id"
95
+
96
+ printf 'installing grant %s\n' "$GRANT_ID" >&2
97
+ INSTALL=$(itp grants install "$GRANT_ID" --target codex --json)
98
+ printf '%s' "$INSTALL" | json_assert "return v.grant_id && v.credential && v.credential.credential_store"
99
+
100
+ printf 'installing codex profile in temp HOME\n' >&2
101
+ itp install codex --grant "$GRANT_ID" --offline --no-test --json | json_assert "return v.target === 'codex' && v.grant_id"
102
+ test -f "$TMP_HOME/.codex/config.toml"
103
+ test -f "$TMP_HOME/.itp/voltagent.env"
104
+
105
+ BALANCE=$(itp balance --json)
106
+ printf '%s' "$BALANCE" | json_assert "return v.active_grants === 1 && v.credits_remaining === '100.000000'"
107
+
108
+ ORDERS=$(itp checkout list --limit 5 --json)
109
+ printf '%s' "$ORDERS" | json_assert "return Array.isArray(v.orders) && v.orders.some(o => o.checkout_id === '$CHECKOUT_ID')"
110
+
111
+ USAGE=$(itp usage --grant "$GRANT_ID" --json)
112
+ printf '%s' "$USAGE" | json_assert "return v.grant_id === '$GRANT_ID' && v.total && v.total.requests === 0"
113
+
114
+ printf 'rotating grant key\n' >&2
115
+ ROTATE=$(itp keys rotate --grant "$GRANT_ID" --json)
116
+ printf '%s' "$ROTATE" | json_assert "return v.grant_id === '$GRANT_ID' && v.credential && v.credential.credential_store"
117
+ TOKEN=$(itp token issue --grant "$GRANT_ID" --stdout)
118
+ case "$TOKEN" in
119
+ sk-*) ;;
120
+ *) echo "token issue did not return sk-* token" >&2; exit 1 ;;
121
+ esac
122
+
123
+ printf 'revoking grant\n' >&2
124
+ REVOKE=$(itp grants revoke "$GRANT_ID" --json)
125
+ printf '%s' "$REVOKE" | json_assert "return v.status === 'revoked'"
126
+ BALANCE=$(itp balance --json)
127
+ printf '%s' "$BALANCE" | json_assert "return v.active_grants === 0"
128
+
129
+ printf 'voltagent local e2e ok\n'
130
+ printf 'server: %s\n' "$API_BASE"
131
+ printf 'account: %s\n' "$(printf '%s' "$AUTH" | json_get account_id)"
132
+ printf 'checkout: %s\n' "$CHECKOUT_ID"
133
+ printf 'grant: %s\n' "$GRANT_ID"
134
+ printf 'temp_home_cleaned_on_exit: %s\n' "$TMP_HOME"
package/install.ps1 ADDED
@@ -0,0 +1,53 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $SourceDir = Split-Path -Parent $MyInvocation.MyCommand.Path
4
+ $ItpBin = Join-Path $SourceDir "bin\itp"
5
+ $SkillsDir = Join-Path $SourceDir "skills"
6
+ $DocsDir = Join-Path $SourceDir "docs"
7
+ $NodeModules = Join-Path $SourceDir "node_modules"
8
+ $Prefix = if ($env:ITP_PREFIX) { $env:ITP_PREFIX } else { Join-Path $HOME ".local" }
9
+ $TargetDir = Join-Path $Prefix "bin"
10
+ $TargetScript = Join-Path $TargetDir "itp.js"
11
+ $TargetCmd = Join-Path $TargetDir "itp.cmd"
12
+ $ModuleTarget = Join-Path $TargetDir "node_modules"
13
+ $ShareTargetDir = Join-Path $Prefix "share\itpay_cli"
14
+ $SkillsTarget = Join-Path $ShareTargetDir "skills"
15
+ $DocsTarget = Join-Path $ShareTargetDir "docs"
16
+
17
+ if (!(Test-Path $ItpBin)) {
18
+ throw "itp binary not found at $ItpBin"
19
+ }
20
+
21
+ New-Item -ItemType Directory -Force -Path $TargetDir | Out-Null
22
+ Copy-Item -Force $ItpBin $TargetScript
23
+ if (Test-Path $NodeModules) {
24
+ if (Test-Path $ModuleTarget) {
25
+ Remove-Item -Recurse -Force $ModuleTarget
26
+ }
27
+ Copy-Item -Recurse -Force $NodeModules $ModuleTarget
28
+ }
29
+ if (Test-Path $SkillsDir) {
30
+ if (Test-Path $SkillsTarget) {
31
+ Remove-Item -Recurse -Force $SkillsTarget
32
+ }
33
+ New-Item -ItemType Directory -Force -Path $ShareTargetDir | Out-Null
34
+ Copy-Item -Recurse -Force $SkillsDir $SkillsTarget
35
+ }
36
+ if (Test-Path $DocsDir) {
37
+ if (Test-Path $DocsTarget) {
38
+ Remove-Item -Recurse -Force $DocsTarget
39
+ }
40
+ New-Item -ItemType Directory -Force -Path $ShareTargetDir | Out-Null
41
+ Copy-Item -Recurse -Force $DocsDir $DocsTarget
42
+ }
43
+ Set-Content -Path $TargetCmd -Encoding ASCII -Value @"
44
+ @echo off
45
+ node "%~dp0itp.js" %*
46
+ "@
47
+
48
+ Write-Output "Installed itp to $TargetCmd"
49
+ if (($env:Path -split ';') -notcontains $TargetDir) {
50
+ Write-Output "Add $TargetDir to PATH before running itp."
51
+ } else {
52
+ & $TargetCmd --version
53
+ }
package/install.sh ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env sh
2
+ set -eu
3
+
4
+ SOURCE_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
+ ITP_BIN="$SOURCE_DIR/bin/itp"
6
+ SKILLS_DIR="$SOURCE_DIR/skills"
7
+ DOCS_DIR="$SOURCE_DIR/docs"
8
+ NODE_MODULES="$SOURCE_DIR/node_modules"
9
+ PREFIX="${ITP_PREFIX:-$HOME/.local}"
10
+ TARGET_DIR="$PREFIX/bin"
11
+ TARGET="$TARGET_DIR/itp"
12
+ SHARE_TARGET_DIR="$PREFIX/share/itpay_cli"
13
+ MODULE_TARGET="$TARGET_DIR/node_modules"
14
+
15
+ if [ ! -f "$ITP_BIN" ]; then
16
+ echo "itp binary not found at $ITP_BIN" >&2
17
+ exit 1
18
+ fi
19
+
20
+ mkdir -p "$TARGET_DIR"
21
+ chmod +x "$ITP_BIN"
22
+ cp "$ITP_BIN" "$TARGET"
23
+ chmod +x "$TARGET"
24
+
25
+ if [ -d "$NODE_MODULES" ]; then
26
+ rm -rf "$MODULE_TARGET"
27
+ cp -R "$NODE_MODULES" "$MODULE_TARGET"
28
+ fi
29
+
30
+ if [ -d "$SKILLS_DIR" ]; then
31
+ rm -rf "$SHARE_TARGET_DIR/skills"
32
+ mkdir -p "$SHARE_TARGET_DIR"
33
+ cp -R "$SKILLS_DIR" "$SHARE_TARGET_DIR/skills"
34
+ find "$SHARE_TARGET_DIR/skills" -type f -exec chmod 0644 {} \;
35
+ fi
36
+
37
+ if [ -d "$DOCS_DIR" ]; then
38
+ rm -rf "$SHARE_TARGET_DIR/docs"
39
+ mkdir -p "$SHARE_TARGET_DIR"
40
+ cp -R "$DOCS_DIR" "$SHARE_TARGET_DIR/docs"
41
+ find "$SHARE_TARGET_DIR/docs" -type f -exec chmod 0644 {} \;
42
+ fi
43
+
44
+ case ":$PATH:" in
45
+ *":$TARGET_DIR:"*) ;;
46
+ *)
47
+ echo "Installed itp to $TARGET"
48
+ echo "Add $TARGET_DIR to PATH before running itp."
49
+ exit 0
50
+ ;;
51
+ esac
52
+
53
+ "$TARGET" --version
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@itpay/cli",
3
+ "version": "0.1.0",
4
+ "description": "ItPay CLI, buyer skill, and agent-readable docs for agent-native commerce.",
5
+ "type": "module",
6
+ "bin": {
7
+ "itp": "bin/itp",
8
+ "itpay": "bin/itp",
9
+ "itpay_cli": "bin/itp"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "skills/",
14
+ "docs/",
15
+ "install.sh",
16
+ "install.ps1",
17
+ "smoke.sh",
18
+ "e2e-local.sh",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "scripts": {
26
+ "smoke": "sh ./smoke.sh",
27
+ "check": "node --check ./bin/itp && sh ./smoke.sh"
28
+ },
29
+ "keywords": [
30
+ "itpay",
31
+ "voltagent",
32
+ "agent",
33
+ "cli",
34
+ "claude-code",
35
+ "codex",
36
+ "openclaw"
37
+ ],
38
+ "license": "MIT",
39
+ "engines": {
40
+ "node": ">=18"
41
+ },
42
+ "dependencies": {
43
+ "qrcode": "^1.5.4"
44
+ }
45
+ }