@itpay/cli 0.2.17 → 2.0.0-rc.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.
Files changed (69) hide show
  1. package/README.md +148 -447
  2. package/bin/itp +1 -150
  3. package/dist/src/client/backend.js +154 -0
  4. package/dist/src/client/http.js +76 -0
  5. package/dist/src/client/types.js +4 -0
  6. package/dist/src/commands/buy.js +351 -0
  7. package/dist/src/commands/cart.js +264 -0
  8. package/dist/src/commands/catalog.js +26 -0
  9. package/dist/src/commands/checkout.js +106 -0
  10. package/dist/src/commands/docs.js +61 -0
  11. package/dist/src/commands/guidance.js +422 -0
  12. package/dist/src/commands/install.js +95 -0
  13. package/dist/src/commands/order.js +78 -0
  14. package/dist/src/commands/orders.js +22 -0
  15. package/dist/src/commands/pay.js +26 -0
  16. package/dist/src/commands/readyz.js +8 -0
  17. package/dist/src/commands/refund.js +20 -0
  18. package/dist/src/commands/services.js +317 -0
  19. package/dist/src/main.js +606 -0
  20. package/dist/src/render/feishu.js +201 -0
  21. package/dist/src/render/ide.js +321 -0
  22. package/dist/src/render/index.js +57 -0
  23. package/dist/src/render/interaction.js +49 -0
  24. package/dist/src/render/markdown.js +83 -0
  25. package/dist/src/render/output.js +42 -0
  26. package/dist/src/render/plain_chat.js +60 -0
  27. package/dist/src/render/plan.js +31 -0
  28. package/dist/src/render/qr.js +32 -0
  29. package/dist/src/render/sink.js +6 -0
  30. package/dist/src/render/status.js +37 -0
  31. package/dist/src/render/telegram.js +172 -0
  32. package/dist/src/render/terminal.js +148 -0
  33. package/dist/src/render/terminal_image.js +19 -0
  34. package/dist/src/state/cart_session.js +151 -0
  35. package/dist/src/state/client_context.js +73 -0
  36. package/dist/src/state/config.js +82 -0
  37. package/dist/src/state/device_authority.js +217 -0
  38. package/dist/src/state/operation_journal.js +80 -0
  39. package/docs/agent/buyer/cart-checkout.json +56 -94
  40. package/docs/agent/buyer/catalog-list.json +47 -0
  41. package/docs/agent/buyer/install-and-setup.json +82 -0
  42. package/docs/agent/buyer/orders-refunds.json +76 -0
  43. package/docs/agent/buyer/payment-flow.json +77 -0
  44. package/docs/agent/buyer/quickstart.json +143 -75
  45. package/docs/agent/buyer/render-hosts.json +79 -0
  46. package/package.json +32 -13
  47. package/skills/itpay-buyer/SKILL.md +107 -238
  48. package/docs/agent/buyer/account-portal.json +0 -81
  49. package/docs/agent/buyer/catalog-search.json +0 -106
  50. package/docs/agent/buyer/human-claim-ui.json +0 -77
  51. package/docs/agent/buyer/payment-qr.json +0 -97
  52. package/docs/agent/buyer/payment-wait.json +0 -84
  53. package/docs/agent/buyer/product-recommendation.json +0 -80
  54. package/docs/agent/buyer/qr-refresh.json +0 -67
  55. package/docs/agent/buyer/recovery.json +0 -85
  56. package/docs/agent/buyer/safety-policy.json +0 -70
  57. package/docs/agent/buyer/secure-delivery.json +0 -90
  58. package/docs/agent/buyer/vault-agent-read.json +0 -95
  59. package/install.ps1 +0 -65
  60. package/install.sh +0 -66
  61. package/lib/account-status.js +0 -157
  62. package/lib/buyer.js +0 -2332
  63. package/lib/client-context.js +0 -126
  64. package/lib/docs.js +0 -200
  65. package/lib/env.js +0 -723
  66. package/lib/http.js +0 -151
  67. package/lib/ops.js +0 -135
  68. package/lib/render-human.js +0 -718
  69. package/lib/runtime.js +0 -1456
@@ -1,126 +0,0 @@
1
- const SUPPORTED_HOSTS = new Set(["codex", "claude-code", "telegram", "discord", "whatsapp", "terminal", "plain-chat"]);
2
- const RUNTIME_TARGETS = new Set(["codex", "claude-code", "openclaw", "generic"]);
3
- const EXEMPT_GROUPS = new Set(["", "--help", "-h", "help", "version", "docs", "skill", "doctor", "install"]);
4
-
5
- function clientContextGate(args = []) {
6
- const group = args[0] || "";
7
- if (EXEMPT_GROUPS.has(group)) return null;
8
- const flags = parseArgFlags(args.slice(1));
9
- const host = clientHost(flags);
10
- if (!host) return clientContextRequired();
11
- if (!SUPPORTED_HOSTS.has(host)) return unsupportedClientContext(host);
12
- if (requiresTarget(host) && !clientTarget(flags)) return clientTargetRequired(host);
13
- return null;
14
- }
15
-
16
- function clientHost(flags = {}) {
17
- const raw = firstValue(
18
- flags.host,
19
- flags.client,
20
- flags.channel,
21
- argFlag("host"),
22
- argFlag("client"),
23
- argFlag("channel")
24
- );
25
- const host = normalizeHost(raw);
26
- if (host === "openclaw" && flags.channel) return normalizeHost(flags.channel);
27
- return host;
28
- }
29
-
30
- function clientTarget(flags = {}) {
31
- const target = firstValue(flags.chat_target, flags.reply_target, argFlag("chat-target"), argFlag("reply-target"));
32
- if (target) return target;
33
- const flagTarget = flags.target || argFlag("target");
34
- return flagTarget && !RUNTIME_TARGETS.has(normalizeHost(flagTarget)) ? String(flagTarget) : "";
35
- }
36
-
37
- function clientCommandArgs(flags = {}) {
38
- const host = clientHost(flags);
39
- const target = clientTarget(flags);
40
- return [
41
- ...(host ? ["--host", host] : []),
42
- ...(target ? ["--target", target] : [])
43
- ];
44
- }
45
-
46
- function requiresTarget(host) {
47
- return host === "telegram" || host === "discord" || host === "whatsapp";
48
- }
49
-
50
- function clientContextRequired() {
51
- return {
52
- schema_version: "itp.client_context.v1",
53
- status: "client_context_required",
54
- must_rerun: true,
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
- allowed_hosts: Array.from(SUPPORTED_HOSTS),
57
- examples: {
58
- codex: "itp ... --host codex --json",
59
- claude_code: "itp ... --host claude-code --json",
60
- telegram: "itp ... --host telegram --target telegram:<chat_id> --json",
61
- terminal: "itp ... --host terminal --json"
62
- }
63
- };
64
- }
65
-
66
- function clientTargetRequired(host) {
67
- return {
68
- schema_version: "itp.client_context.v1",
69
- status: "client_target_required",
70
- must_rerun: true,
71
- host,
72
- instruction: "Rerun the same itp command with the current chat target. For OpenClaw Telegram group/private chat, pass inbound_meta.chat_id as --target.",
73
- examples: {
74
- telegram_private: "itp ... --host telegram --target telegram:5559456744 --json",
75
- telegram_group: "itp ... --host telegram --target telegram:-1001234567890 --json",
76
- discord: "itp ... --host discord --target discord:<channel_id> --json"
77
- }
78
- };
79
- }
80
-
81
- function unsupportedClientContext(host) {
82
- return {
83
- schema_version: "itp.client_context.v1",
84
- status: "unsupported_client_context",
85
- must_rerun: true,
86
- host,
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
- allowed_hosts: Array.from(SUPPORTED_HOSTS)
89
- };
90
- }
91
-
92
- function normalizeHost(value = "") {
93
- const normalized = String(value || "").trim().toLowerCase().replaceAll("_", "-");
94
- if (["tg", "openclaw-telegram"].includes(normalized)) return "telegram";
95
- if (["codex-app", "codex-cli"].includes(normalized)) return "codex";
96
- if (["claude", "claudecode", "claude-code-app"].includes(normalized)) return "claude-code";
97
- if (["plain", "plain-chat", "chat"].includes(normalized)) return "plain-chat";
98
- return normalized;
99
- }
100
-
101
- function parseArgFlags(args = []) {
102
- const flags = {};
103
- for (let i = 0; i < args.length; i += 1) {
104
- const arg = args[i];
105
- if (!String(arg).startsWith("--")) continue;
106
- const key = String(arg).slice(2).replaceAll("-", "_");
107
- const next = args[i + 1];
108
- if (!next || String(next).startsWith("--")) {
109
- flags[key] = true;
110
- } else {
111
- flags[key] = next;
112
- i += 1;
113
- }
114
- }
115
- return flags;
116
- }
117
-
118
- function argFlag(name) {
119
- return parseArgFlags(process.argv.slice(2))[String(name).replaceAll("-", "_")] || "";
120
- }
121
-
122
- function firstValue(...values) {
123
- return values.find((value) => value !== undefined && value !== null && value !== false && String(value).trim() !== "") || "";
124
- }
125
-
126
- export { clientCommandArgs, clientContextGate, clientHost, clientTarget };
package/lib/docs.js DELETED
@@ -1,200 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { CLI_DIR, PACKAGE_ROOT, cliCommand, output, positionalArgs, readJSON } from "./env.js";
4
-
5
- async function docs(command, rest = [], flags = {}) {
6
- const role = normalizeDocsRole(flags.role || "buyer");
7
- if (command === "list" || !command) {
8
- const docsList = listAgentDocs(role);
9
- output({
10
- schema_version: "itp.agent_doc_index.v1",
11
- role,
12
- topics: docsList.map((doc) => ({
13
- topic: doc.topic,
14
- title: doc.title,
15
- purpose: doc.purpose,
16
- command: cliCommand("docs", "show", doc.topic, "--role", role, "--json"),
17
- next_docs: Array.isArray(doc.next_docs) ? doc.next_docs.map((next) => next.topic).filter(Boolean) : []
18
- })),
19
- start_here: cliCommand("docs", "show", "quickstart", "--role", role, "--json"),
20
- search_command: cliCommand("docs", "search", "<question>", "--role", role, "--json")
21
- });
22
- return;
23
- }
24
- if (command === "show" || command === "read") {
25
- const topic = flags.topic || positionalArgs(rest)[0] || "quickstart";
26
- output(loadAgentDoc(role, topic));
27
- return;
28
- }
29
- if (command === "search") {
30
- const query = String(flags.query || flags.q || positionalArgs(rest).join(" ")).trim();
31
- if (!query) throw new Error("docs search query is required");
32
- const matches = searchAgentDocs(role, query);
33
- output({
34
- schema_version: "itp.agent_doc_search.v1",
35
- role,
36
- query,
37
- matches,
38
- fallback: matches.length ? null : {
39
- topic: "quickstart",
40
- command: cliCommand("docs", "show", "quickstart", "--role", role, "--json")
41
- }
42
- });
43
- return;
44
- }
45
- throw new Error(`unknown docs command: ${command}`);
46
- }
47
-
48
- function normalizeDocsRole(role) {
49
- const normalized = String(role || "buyer").trim().toLowerCase();
50
- if (normalized === "buyer" || normalized === "itpay-buyer") return "buyer";
51
- throw new Error(`unsupported docs role: ${role}`);
52
- }
53
-
54
- function listAgentDocs(role) {
55
- const docsDir = resolveDocsDir(role);
56
- return fs.readdirSync(docsDir)
57
- .filter((name) => name.endsWith(".json"))
58
- .map((name) => loadAgentDoc(role, name.replace(/\.json$/, "")))
59
- .sort((a, b) => docTopicOrder(a.topic) - docTopicOrder(b.topic) || a.topic.localeCompare(b.topic));
60
- }
61
-
62
- function loadAgentDoc(role, topic) {
63
- const normalizedTopic = normalizeDocTopic(topic);
64
- const file = path.join(resolveDocsDir(role), `${normalizedTopic}.json`);
65
- if (!fs.existsSync(file)) {
66
- throw new Error(`agent docs topic not found: ${normalizedTopic}`);
67
- }
68
- const doc = readJSON(file, null);
69
- if (!doc || doc.role !== role || doc.topic !== normalizedTopic) {
70
- throw new Error(`invalid agent docs topic: ${normalizedTopic}`);
71
- }
72
- return {
73
- ...doc,
74
- source: {
75
- packaged_path: file,
76
- command: cliCommand("docs", "show", normalizedTopic, "--role", role, "--json")
77
- }
78
- };
79
- }
80
-
81
- function searchAgentDocs(role, query) {
82
- const rawQuery = String(query).toLowerCase();
83
- const terms = rawQuery.split(/\s+/).filter(Boolean);
84
- return listAgentDocs(role)
85
- .map((doc) => {
86
- const docTerms = (doc.search_terms || []).map((term) => String(term).toLowerCase()).filter(Boolean);
87
- const haystack = [
88
- doc.topic,
89
- doc.title,
90
- doc.purpose,
91
- ...(doc.when_to_use || []),
92
- ...(doc.agent_rules || []),
93
- ...(doc.forbidden || []),
94
- ...docTerms
95
- ].join(" ").toLowerCase();
96
- const score = terms.reduce((sum, term) => sum + (haystack.includes(term) ? 1 : 0), 0) +
97
- docTerms.reduce((sum, term) => sum + (rawQuery.includes(term) ? 1 : 0), 0);
98
- return { doc, score };
99
- })
100
- .filter((entry) => entry.score > 0)
101
- .sort((a, b) => b.score - a.score || docTopicOrder(a.doc.topic) - docTopicOrder(b.doc.topic))
102
- .slice(0, 5)
103
- .map((entry) => ({
104
- topic: entry.doc.topic,
105
- title: entry.doc.title,
106
- purpose: entry.doc.purpose,
107
- score: entry.score,
108
- command: cliCommand("docs", "show", entry.doc.topic, "--role", role, "--json"),
109
- next_docs: Array.isArray(entry.doc.next_docs) ? entry.doc.next_docs.map((next) => next.topic).filter(Boolean) : []
110
- }));
111
- }
112
-
113
- function resolveDocsDir(role) {
114
- const candidates = [
115
- process.env.ITPAY_CLI_DOCS_DIR,
116
- path.join(PACKAGE_ROOT, "docs", "agent", role),
117
- path.join(path.dirname(CLI_DIR), "share", "itpay_cli", "docs", "agent", role),
118
- path.join(process.cwd(), "docs", "agent", role)
119
- ].filter(Boolean);
120
- const found = candidates.find((candidate) => fs.existsSync(candidate));
121
- if (!found) {
122
- throw new Error(`ItPay agent docs not found for role ${role}. Checked: ${candidates.join(", ")}`);
123
- }
124
- return found;
125
- }
126
-
127
- function normalizeDocTopic(topic) {
128
- return String(topic || "").trim().toLowerCase().replaceAll("_", "-");
129
- }
130
-
131
- function docTopicOrder(topic) {
132
- const order = [
133
- "quickstart",
134
- "catalog-search",
135
- "product-recommendation",
136
- "cart-checkout",
137
- "payment-qr",
138
- "payment-wait",
139
- "qr-refresh",
140
- "secure-delivery",
141
- "human-claim-ui",
142
- "account-portal",
143
- "vault-agent-read",
144
- "recovery",
145
- "safety-policy"
146
- ];
147
- const index = order.indexOf(topic);
148
- return index === -1 ? 999 : index;
149
- }
150
-
151
- async function skill(command, flags) {
152
- const role = normalizeSkillRole(flags.role || flags.skill || "buyer");
153
- const skillPath = resolveSkillPath(role);
154
- if (!command || command === "show" || command === "read") {
155
- const content = fs.readFileSync(skillPath, "utf8");
156
- if (flags.json) {
157
- output({ skill: "itpay-buyer", role, path: skillPath, content });
158
- } else {
159
- process.stdout.write(content.endsWith("\n") ? content : `${content}\n`);
160
- }
161
- return;
162
- }
163
- if (command === "path") {
164
- if (flags.json) {
165
- output({ skill: "itpay-buyer", role, path: skillPath });
166
- } else {
167
- process.stdout.write(`${skillPath}\n`);
168
- }
169
- return;
170
- }
171
- throw new Error(`unknown skill command: ${command}`);
172
- }
173
-
174
- function normalizeSkillRole(role) {
175
- const normalized = String(role || "buyer").trim().toLowerCase();
176
- if (normalized === "buyer" || normalized === "itpay-buyer") return "buyer";
177
- if (normalized === "merchant" || normalized === "itpay-merchant") {
178
- throw new Error("merchant skill is not packaged yet; use --role buyer for current external-agent tests");
179
- }
180
- throw new Error(`unsupported skill role: ${role}`);
181
- }
182
-
183
- function resolveSkillPath(role = "buyer") {
184
- const skillDirName = "itpay-buyer";
185
- const envPath = process.env.ITPAY_BUYER_SKILL_PATH;
186
- const candidates = [
187
- envPath,
188
- process.env.ITPAY_CLI_SKILL_PATH,
189
- path.join(PACKAGE_ROOT, "skills", skillDirName, "SKILL.md"),
190
- path.join(path.dirname(CLI_DIR), "share", "itpay_cli", "skills", skillDirName, "SKILL.md"),
191
- path.join(process.cwd(), "skills", skillDirName, "SKILL.md")
192
- ].filter(Boolean);
193
- const found = candidates.find((candidate) => fs.existsSync(candidate));
194
- if (!found) {
195
- throw new Error(`ItPay skill file not found for role ${role}. Checked: ${candidates.join(", ")}`);
196
- }
197
- return found;
198
- }
199
-
200
- export { docs, skill };