@itpay/cli 2.0.7 → 2.0.9

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 CHANGED
@@ -11,7 +11,7 @@ itpay --agent-type codex-desktop readyz --json
11
11
  # follow next.command: typed skill show, then catalog list
12
12
  ```
13
13
 
14
- The default API is `https://app.itpay.ai`. Set `ITPAY_BACKEND_URL` only for an intentional test or local environment.
14
+ The default API is temporarily `https://dev.itpay.ai` during the 2.0.9 beta. Set `ITPAY_BACKEND_URL` only for an intentional override.
15
15
 
16
16
  ## Output Contract
17
17
 
@@ -0,0 +1,32 @@
1
+ import { HttpError } from "../client/http.js";
2
+ import { API_CONTRACT_REVISION, CLI_VERSION } from "../state/config.js";
3
+ export async function requirePlatformCompatibility(backend) {
4
+ const platform = await backend.compatibility();
5
+ const compatible = platform.api_contract_revision === API_CONTRACT_REVISION
6
+ && compareVersions(CLI_VERSION, platform.minimum_cli_version) >= 0
7
+ && versionMajor(CLI_VERSION) <= platform.maximum_cli_major;
8
+ if (compatible)
9
+ return;
10
+ throw new HttpError(426, {
11
+ code: "client_upgrade_required",
12
+ message: `CLI ${CLI_VERSION} contract ${API_CONTRACT_REVISION} is incompatible with platform ${platform.platform_revision} contract ${platform.api_contract_revision} (minimum CLI ${platform.minimum_cli_version}, maximum major ${platform.maximum_cli_major})`,
13
+ }, "CLI is incompatible with the active ItPay platform release");
14
+ }
15
+ function compareVersions(left, right) {
16
+ const a = versionParts(left);
17
+ const b = versionParts(right);
18
+ if (!a || !b)
19
+ return -1;
20
+ for (let index = 0; index < 3; index += 1) {
21
+ if (a[index] !== b[index])
22
+ return a[index] - b[index];
23
+ }
24
+ return 0;
25
+ }
26
+ function versionMajor(version) {
27
+ return versionParts(version)?.[0] ?? Number.MAX_SAFE_INTEGER;
28
+ }
29
+ function versionParts(version) {
30
+ const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version.trim());
31
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : undefined;
32
+ }
package/dist/src/main.js CHANGED
@@ -10,6 +10,7 @@ import { HttpError } from "./client/http.js";
10
10
  import { runReadyz } from "./commands/readyz.js";
11
11
  import { runBuy } from "./commands/buy.js";
12
12
  import { runCatalogList } from "./commands/catalog.js";
13
+ import { requirePlatformCompatibility } from "./commands/compatibility.js";
13
14
  import { runCheckoutPresentation } from "./commands/checkout.js";
14
15
  import { runPay } from "./commands/pay.js";
15
16
  import { runOrder } from "./commands/order.js";
@@ -94,6 +95,7 @@ function reportCLIError(error, contract) {
94
95
  error.code === "client_compatibility_headers_required" ||
95
96
  error.code === "platform_release_unavailable" ||
96
97
  (error.status === 404 && error.code === "unknown_error"));
98
+ const backendInternal = error instanceof HttpError && error.status === 500 && error.code === "internal_error";
97
99
  const deviceRecovery = deviceError ? [{
98
100
  command: "itpay skill show itpay-buyer --json",
99
101
  reason: "读取身份边界;该错误需要用户或运营恢复 Backend 登记,不能通过换类型或删除本地身份绕过",
@@ -119,10 +121,12 @@ function reportCLIError(error, contract) {
119
121
  message: error instanceof Error ? error.message : String(error),
120
122
  },
121
123
  instruction: incompatible
122
- ? "当前 Backend 不支持本 CLI 所需的交易合同。立即停止;不要尝试 services quoteservices checkout、cart、buypay 作为替代路径。需要先同步 CLI Backend 版本。"
123
- : commandError?.instruction ?? authorizationInstruction ?? contract?.instruction ?? "检查命令参数后重试。",
124
+ ? "立即向用户报告 error.message 并结束本次任务。不要运行任何其他 itpaynpmwhich、device、docs、cart、ordersservices 命令;不要寻找、安装或切换其他 CLI。只有运营明确提供兼容 CLI 后,才能在新的任务中重新开始。"
125
+ : backendInternal
126
+ ? "Backend 内部故障;立即停止并向用户报告。不要重试、检查或删除 Device 身份、创建替代 Execution、切换 Backend,或尝试 quote、checkout、cart、buy、pay 等付费路径。"
127
+ : commandError?.instruction ?? authorizationInstruction ?? contract?.instruction ?? "检查命令参数后重试。",
124
128
  next: null,
125
- recovery: incompatible ? [] : commandError?.recovery ?? (stateError ? stateRecovery : deviceError ? deviceRecovery : identityRecovery ? httpRecovery : contract?.recovery ?? []),
129
+ recovery: incompatible || backendInternal ? [] : commandError?.recovery ?? (stateError ? stateRecovery : deviceError ? deviceRecovery : identityRecovery ? httpRecovery : contract?.recovery ?? []),
126
130
  }, {
127
131
  ...(contract?.jsonOutput !== undefined ? { jsonOutput: contract.jsonOutput } : {}),
128
132
  output: (text) => { process.stderr.write(text); },
@@ -159,6 +163,7 @@ program
159
163
  const config = loadConfig();
160
164
  const backend = newBackendClient(config);
161
165
  try {
166
+ await requirePlatformCompatibility(backend);
162
167
  await runReadyz(backend, { jsonOutput: Boolean(options.json), ...(config.agentType ? { agentType: config.agentType } : {}) });
163
168
  }
164
169
  catch (error) {
@@ -254,8 +259,19 @@ program
254
259
  .option("--json", "output JSON instead of terminal text")
255
260
  .action(async (options) => {
256
261
  const config = loadConfig();
257
- const session = CartSession.loadFromFile(cartSessionPath(), config.checkoutCurrency);
258
- runNext(session, { jsonOutput: Boolean(options.json) });
262
+ try {
263
+ await requirePlatformCompatibility(newBackendClient(config));
264
+ const session = CartSession.loadFromFile(cartSessionPath(), config.checkoutCurrency);
265
+ runNext(session, { jsonOutput: Boolean(options.json) });
266
+ }
267
+ catch (error) {
268
+ reportCLIError(error, {
269
+ jsonOutput: Boolean(options.json),
270
+ code: "next_unavailable",
271
+ instruction: "Backend 合同可用后再读取本地恢复句柄;不要根据旧句柄继续交易。",
272
+ recovery: [],
273
+ });
274
+ }
259
275
  });
260
276
  // --- catalog --------------------------------------------------------------
261
277
  const catalogCmd = program.command("catalog").description("Browse V3 service catalog");
@@ -266,6 +282,7 @@ catalogCmd
266
282
  .action(async (options) => {
267
283
  const backend = newBackendClient(loadConfig());
268
284
  try {
285
+ await requirePlatformCompatibility(backend);
269
286
  await runCatalogList(backend, { jsonOutput: Boolean(options.json) });
270
287
  }
271
288
  catch (error) {
@@ -9,9 +9,9 @@ import { BackendClient } from "../client/backend.js";
9
9
  import { declaredAgentType } from "./agent_type.js";
10
10
  import { DeviceAuthority } from "./device_authority.js";
11
11
  import { OperationJournal } from "./operation_journal.js";
12
- export const DEFAULT_BASE_URL = "https://app.itpay.ai";
13
- export const CLI_VERSION = "2.0.7";
14
- export const API_CONTRACT_REVISION = "sha256:47d42ab7bbe74a806b9ec989384b28ad715ffcf05a5eb913449b8bc224ffcf49";
12
+ export const DEFAULT_BASE_URL = "https://dev.itpay.ai";
13
+ export const CLI_VERSION = "2.0.9";
14
+ export const API_CONTRACT_REVISION = "sha256:4ad3ff2565cc265a8c98dec3bb92be1cbfee4d37cb78756d929c78ef134a7bca";
15
15
  const CART_SESSION_DEFAULT_DIR = ".itpay-v3";
16
16
  const CART_SESSION_FILENAME = "cart.json";
17
17
  const OPERATION_JOURNAL_FILENAME = "operations.json";
@@ -32,7 +32,7 @@
32
32
  ],
33
33
  "agent_rules": [
34
34
  "Install with npm install -g @itpay/cli.",
35
- "Use the default https://app.itpay.ai API unless an environment override is deliberate.",
35
+ "Use the default https://dev.itpay.ai beta API unless an environment override is deliberate.",
36
36
  "Use one exact type: codex-desktop, codex-cli, claude-code-desktop, claude-code-cli, or workbuddy.",
37
37
  "One local private key is reused, but each exact Backend API base URL has its own server registration and quota lineage.",
38
38
  "Within one Backend registration, each Agent Type has one Agent Instance; all windows and chats of the same type reuse it.",
@@ -29,7 +29,7 @@ itpay install [target] [--json]
29
29
  "result": {
30
30
  "agent_type": "codex-desktop",
31
31
  "default_host": "codex",
32
- "default_api": "https://app.itpay.ai",
32
+ "default_api": "https://dev.itpay.ai",
33
33
  "install_command": "npm install -g @itpay/cli"
34
34
  },
35
35
  "instruction": "在 Codex Desktop 中始终传这个 Agent Type;付款时把返回的二维码和链接实际展示到当前对话。",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itpay/cli",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "description": "ItPay CLI for V3 checkout, payment, order, refund, and agent-facing render flows.",
5
5
  "type": "module",
6
6
  "bin": {