@itpay/cli 2.0.36 → 2.0.37
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/state/config.js
CHANGED
|
@@ -12,8 +12,8 @@ import { DeviceAuthority } from "./device_authority.js";
|
|
|
12
12
|
import { OperationJournal } from "./operation_journal.js";
|
|
13
13
|
export const DEFAULT_BASE_URL = "https://app.itpay.ai";
|
|
14
14
|
export const DEV_BASE_URL = "https://dev.itpay.ai";
|
|
15
|
-
export const CLI_VERSION = "2.0.
|
|
16
|
-
export const API_CONTRACT_REVISION = "sha256:
|
|
15
|
+
export const CLI_VERSION = "2.0.37";
|
|
16
|
+
export const API_CONTRACT_REVISION = "sha256:b97025ee4e6f7539757d6aedbe193dd65b3a0f84f1111f678abb5e757065f888";
|
|
17
17
|
const CART_SESSION_DEFAULT_DIR = ".itpay-v3";
|
|
18
18
|
const CART_SESSION_FILENAME = "cart.json";
|
|
19
19
|
const OPERATION_JOURNAL_FILENAME = "operations.json";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash, createPrivateKey, createPublicKey, generateKeyPairSync, randomUUID, sign, } from "node:crypto";
|
|
2
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync,
|
|
2
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
const PROTECTED_PATHS = ["/v1/carts", "/v1/service-executions", "/v1/agent-instances", "/v1/orders", "/v1/refunds", "/v1/me", "/v1/vault"];
|
|
@@ -292,10 +292,12 @@ async function withFileLock(path, run) {
|
|
|
292
292
|
catch (error) {
|
|
293
293
|
throw asDeviceStatePathError(error, "prepare_lock") ?? error;
|
|
294
294
|
}
|
|
295
|
+
const ownerToken = randomUUID();
|
|
295
296
|
let acquired = false;
|
|
296
297
|
for (let attempt = 0; attempt < 200; attempt += 1) {
|
|
297
298
|
try {
|
|
298
|
-
|
|
299
|
+
writeFileSync(path, ownerToken, { encoding: "utf8", flag: "wx", mode: 0o600 });
|
|
300
|
+
chmodSync(path, 0o600);
|
|
299
301
|
acquired = true;
|
|
300
302
|
break;
|
|
301
303
|
}
|
|
@@ -305,7 +307,7 @@ async function withFileLock(path, run) {
|
|
|
305
307
|
throw asDeviceStateError(error, "acquire_lock") ?? error;
|
|
306
308
|
try {
|
|
307
309
|
if (Date.now() - statSync(path).mtimeMs > 30_000)
|
|
308
|
-
|
|
310
|
+
moveLockAside(path, "stale", "remove_stale_lock");
|
|
309
311
|
}
|
|
310
312
|
catch (statError) {
|
|
311
313
|
if (statError.code !== "ENOENT") {
|
|
@@ -321,19 +323,33 @@ async function withFileLock(path, run) {
|
|
|
321
323
|
return await run();
|
|
322
324
|
}
|
|
323
325
|
finally {
|
|
324
|
-
|
|
326
|
+
releaseLock(path, ownerToken);
|
|
325
327
|
}
|
|
326
328
|
}
|
|
327
|
-
function
|
|
329
|
+
function releaseLock(path, ownerToken) {
|
|
328
330
|
try {
|
|
329
|
-
if (
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
unlinkSync(path);
|
|
331
|
+
if (readFileSync(path, "utf8") !== ownerToken)
|
|
332
|
+
return;
|
|
333
|
+
moveLockAside(path, "released", "release_lock");
|
|
333
334
|
}
|
|
334
335
|
catch (error) {
|
|
335
336
|
if (error.code !== "ENOENT")
|
|
336
|
-
throw asDeviceStateError(error,
|
|
337
|
+
throw asDeviceStateError(error, "release_lock") ?? error;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
function moveLockAside(path, suffix, operation) {
|
|
341
|
+
try {
|
|
342
|
+
renameSync(path, `${path}.${suffix}`);
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
const code = error.code;
|
|
346
|
+
if (code === "ENOENT")
|
|
347
|
+
return;
|
|
348
|
+
if (code === "EEXIST" || code === "ENOTEMPTY") {
|
|
349
|
+
renameSync(path, `${path}.${suffix}.${randomUUID()}`);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
throw asDeviceStateError(error, operation) ?? error;
|
|
337
353
|
}
|
|
338
354
|
}
|
|
339
355
|
function asDeviceStateError(error, operation) {
|
|
@@ -14,6 +14,14 @@ itpay --agent-type <agent_type> device recover --confirm-backend-reset --json
|
|
|
14
14
|
|
|
15
15
|
命令只作用于当前官方 Backend 的 Device registration,并保留本地 Ed25519 私钥、Cart 和业务资源。默认是 `https://app.itpay.ai`;显式测试可使用准确的 `ITPAY_BACKEND_URL=https://dev.itpay.ai`。该命令不访问 Backend、不自动创建新身份;返回的只读 `services list` 会保留同一 Backend,是重新登记入口。
|
|
16
16
|
|
|
17
|
+
同一台电脑上的多个 Local Agent Type 共享本地 Device key,但各自使用独立 Agent
|
|
18
|
+
Instance。CLI 只在原子更新 Device state 时使用短期本地锁;释放和 stale recovery
|
|
19
|
+
通过 rename 完成,不依赖 Host 删除文件,因此 WorkBuddy 等 sandbox 的
|
|
20
|
+
safe-delete/trash shim 不应阻断正常命令。该锁不在 Backend,不会让另一台电脑或
|
|
21
|
+
另一个 Buyer 等待。遇到本地锁错误时不得删除 `~/.itpay-v3/device`、切换 Agent
|
|
22
|
+
Type 或执行 `device recover`;应保留身份并重试原命令一次,持续失败时报告
|
|
23
|
+
`device_state_unwritable` 或 lock timeout。
|
|
24
|
+
|
|
17
25
|
缺少确认参数返回 `backend_reset_confirmation_required`。普通 session 失效由 CLI 自动续期;revoked、quota、权限或未知 Backend 故障不得使用本命令。所有 Agent Type 使用相同输入和输出合同。
|
|
18
26
|
|
|
19
27
|
## 参数
|
|
@@ -73,6 +73,9 @@ Markdown:
|
|
|
73
73
|
|
|
74
74
|
没有用户评论时省略 Summary,但仍保存 Context。只写用户明确内容和已知安全上下文;禁止 Token、Session、联系方式、内部身份、
|
|
75
75
|
Provider 响应、Vault payload、完整命令输出、stack trace 或环境变量。
|
|
76
|
+
CLI 不读取或上传 Host 对话、WorkBuddy/ZCode sandbox 日志或其他本地 Agent
|
|
77
|
+
记录。用户自愿提供本地证据时,Agent 也只能提炼与本单有关的安全摘要,不能把原始
|
|
78
|
+
日志作为 Feedback note 上传。
|
|
76
79
|
|
|
77
80
|
## 成功 JSON
|
|
78
81
|
|