@itpay/cli 2.1.61 → 2.1.63
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/THIRD-PARTY-NOTICES.txt +1 -1
- package/dist/src/main.js +175 -75
- package/dist/src/state/config.js +1 -1
- package/docs/agent/buyer/install-and-setup.json +2 -2
- package/docs/cli-reference/commands/setup.md +3 -1
- package/package.json +3 -3
- package/skills/itpay/SKILL.md +3 -3
- package/skills/itpay-api/SKILL.md +2 -2
package/THIRD-PARTY-NOTICES.txt
CHANGED
package/dist/src/main.js
CHANGED
|
@@ -3134,7 +3134,7 @@ var HubClient = class {
|
|
|
3134
3134
|
const controller = new AbortController();
|
|
3135
3135
|
let timer;
|
|
3136
3136
|
const aborted = new Promise((_, reject) => {
|
|
3137
|
-
controller.signal.addEventListener("abort", () => reject(new HubApiError(0, { error: { code: opts.signal?.aborted ? "request_cancelled" : "request_timeout", message: method === "POST" && path2 !== "/v1/discover" ? "Request outcome is unknown; read the original request/run before exact-key recovery. No automatic write retry." :
|
|
3137
|
+
controller.signal.addEventListener("abort", () => reject(new HubApiError(0, { error: { code: opts.signal?.aborted ? "request_cancelled" : "request_timeout", message: method === "POST" && path2 !== "/v1/discover" ? "Request outcome is unknown; read the original request/run before exact-key recovery. No automatic write retry." : `Hub ${stage} read timed out after ${timeoutMs} ms; no spending-budget conclusion. Keep the original reference and read it later.`, details: { stage, method, path: path2 } } })), { once: true });
|
|
3138
3138
|
timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
3139
3139
|
});
|
|
3140
3140
|
const cancel = /* @__PURE__ */ __name(() => controller.abort(), "cancel");
|
|
@@ -3741,7 +3741,7 @@ __name(safeParseJson, "safeParseJson");
|
|
|
3741
3741
|
|
|
3742
3742
|
// src/state/hub_credentials.ts
|
|
3743
3743
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
3744
|
-
import { chmodSync as chmodSync2, existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3744
|
+
import { chmodSync as chmodSync2, existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3745
3745
|
import { dirname as dirname2, resolve } from "node:path";
|
|
3746
3746
|
|
|
3747
3747
|
// src/state/file_lock.ts
|
|
@@ -3963,12 +3963,7 @@ function importHubKeyUnlocked(apiKey, baseURL, env = process.env) {
|
|
|
3963
3963
|
api_key: apiKey,
|
|
3964
3964
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
3965
3965
|
};
|
|
3966
|
-
|
|
3967
|
-
const tmp = `${path2}.${randomUUID2()}.tmp`;
|
|
3968
|
-
writeFileSync2(tmp, JSON.stringify(file, null, 2), { encoding: "utf8", mode: 384 });
|
|
3969
|
-
chmodSync2(tmp, 384);
|
|
3970
|
-
renameSync(tmp, path2);
|
|
3971
|
-
chmodSync2(path2, 384);
|
|
3966
|
+
saveHubProfileUnlocked(file.profiles["default"], env);
|
|
3972
3967
|
return { key_prefix: apiKey.slice(0, 14) };
|
|
3973
3968
|
}
|
|
3974
3969
|
__name(importHubKeyUnlocked, "importHubKeyUnlocked");
|
|
@@ -4011,21 +4006,61 @@ function storeHubSessionUnlocked(accessToken, refreshToken, expiresIn, subject,
|
|
|
4011
4006
|
token_url: hubOAuthConfig(env).tokenURL,
|
|
4012
4007
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4013
4008
|
};
|
|
4014
|
-
|
|
4015
|
-
const tmp = `${path2}.${randomUUID2()}.tmp`;
|
|
4016
|
-
writeFileSync2(tmp, JSON.stringify(file, null, 2), { encoding: "utf8", mode: 384 });
|
|
4017
|
-
chmodSync2(tmp, 384);
|
|
4018
|
-
renameSync(tmp, path2);
|
|
4019
|
-
chmodSync2(path2, 384);
|
|
4009
|
+
saveHubProfileUnlocked(file.profiles["default"], env);
|
|
4020
4010
|
}
|
|
4021
4011
|
__name(storeHubSessionUnlocked, "storeHubSessionUnlocked");
|
|
4012
|
+
function saveHubProfileUnlocked(profile, env) {
|
|
4013
|
+
const path2 = hubCredentialsPath(env);
|
|
4014
|
+
const tmp = `${path2}.${randomUUID2()}.tmp`;
|
|
4015
|
+
try {
|
|
4016
|
+
const file = existsSync(path2) ? JSON.parse(readFileSync2(path2, "utf8")) : { schema_version: "itpay.hub_credentials.v1", profiles: {} };
|
|
4017
|
+
file.profiles.default = profile;
|
|
4018
|
+
mkdirSync2(dirname2(path2), { recursive: true, mode: 448 });
|
|
4019
|
+
writeFileSync2(tmp, JSON.stringify(file, null, 2), { encoding: "utf8", flag: "wx", mode: 384 });
|
|
4020
|
+
chmodSync2(tmp, 384);
|
|
4021
|
+
renameSync(tmp, path2);
|
|
4022
|
+
} catch {
|
|
4023
|
+
throw new Error("credential_persistence_failed: could not save the original connection; stop and check private storage before retrying");
|
|
4024
|
+
} finally {
|
|
4025
|
+
try {
|
|
4026
|
+
unlinkSync2(tmp);
|
|
4027
|
+
} catch {
|
|
4028
|
+
}
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4031
|
+
__name(saveHubProfileUnlocked, "saveHubProfileUnlocked");
|
|
4032
|
+
async function probeHubIdentity(resource, accessToken) {
|
|
4033
|
+
let response;
|
|
4034
|
+
try {
|
|
4035
|
+
response = await fetch(`${resource}/v1/me`, {
|
|
4036
|
+
headers: { Authorization: `Bearer ${accessToken}`, "X-ItPay-OAuth-Resource": resource },
|
|
4037
|
+
signal: AbortSignal.timeout(1e4)
|
|
4038
|
+
});
|
|
4039
|
+
} catch {
|
|
4040
|
+
throw new Error("connection_verification_pending: identity check unavailable; preserve the original connection and references, do not reconnect");
|
|
4041
|
+
}
|
|
4042
|
+
if (!response.ok) {
|
|
4043
|
+
if (response.status === 401 || response.status === 403) throw new Error("authorization_required: original connection identity rejected");
|
|
4044
|
+
throw new Error("connection_verification_pending: identity check unavailable; preserve the original connection and references, do not reconnect");
|
|
4045
|
+
}
|
|
4046
|
+
try {
|
|
4047
|
+
const identity = await response.json();
|
|
4048
|
+
if (!identity || typeof identity !== "object" || Array.isArray(identity)) throw new Error();
|
|
4049
|
+
const me = identity;
|
|
4050
|
+
if (typeof me.buyer_id !== "string" || !me.buyer_id || typeof me.consumer_id !== "string" || !me.consumer_id) throw new Error();
|
|
4051
|
+
return { buyer_id: me.buyer_id, consumer_id: me.consumer_id };
|
|
4052
|
+
} catch {
|
|
4053
|
+
throw new Error("connection_verification_pending: identity response invalid; preserve the original connection and references, do not reconnect");
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
__name(probeHubIdentity, "probeHubIdentity");
|
|
4022
4057
|
function storedHubToken(env = process.env) {
|
|
4023
4058
|
const path2 = hubCredentialsPath(env);
|
|
4024
4059
|
if (!existsSync(path2)) return void 0;
|
|
4025
4060
|
try {
|
|
4026
4061
|
const file = JSON.parse(readFileSync2(path2, "utf8"));
|
|
4027
4062
|
const p = file.profiles["default"];
|
|
4028
|
-
if (!p?.access_token) return void 0;
|
|
4063
|
+
if (!p?.access_token || p.identity_verification_pending) return void 0;
|
|
4029
4064
|
if (p.expires_at && Date.parse(p.expires_at) <= Date.now()) return void 0;
|
|
4030
4065
|
return p.access_token;
|
|
4031
4066
|
} catch {
|
|
@@ -4043,31 +4078,68 @@ async function connectedHubToken(env = process.env, rejectedToken) {
|
|
|
4043
4078
|
return withAsyncFileLock(`${hubCredentialsPath(env)}.refresh.lock`, async () => {
|
|
4044
4079
|
const p = storedHubProfile(env);
|
|
4045
4080
|
if (!p?.access_token || !p.subject) throw new Error("authorization_required: reconnect ItPay");
|
|
4046
|
-
const refreshAt = p.refresh_after ? Date.parse(p.refresh_after) : Date.parse(p.expires_at ?? "") - 3e4;
|
|
4047
|
-
if (p.access_token !== rejectedToken && refreshAt > Date.now()) return p.access_token;
|
|
4048
4081
|
const cfg = hubOAuthConfig(env);
|
|
4049
|
-
if (
|
|
4082
|
+
if (p.base_url !== cfg.resource || p.token_url !== cfg.tokenURL || p.client_id !== cfg.clientID || !p.consumer_id) {
|
|
4050
4083
|
throw new Error("authorization_required: connection configuration changed");
|
|
4051
4084
|
}
|
|
4052
|
-
const
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4085
|
+
const refreshAt = p.refresh_after ? Date.parse(p.refresh_after) : Date.parse(p.expires_at ?? "") - 3e4;
|
|
4086
|
+
if (!p.identity_verification_pending && p.access_token !== rejectedToken && refreshAt > Date.now()) return p.access_token;
|
|
4087
|
+
let candidate = p;
|
|
4088
|
+
if (!p.identity_verification_pending || !(Date.parse(p.expires_at ?? "") > Date.now())) {
|
|
4089
|
+
if (!p.refresh_token) throw new Error("authorization_required: reconnect the original ItPay connection");
|
|
4090
|
+
let response;
|
|
4091
|
+
try {
|
|
4092
|
+
response = await fetch(p.token_url, {
|
|
4093
|
+
method: "POST",
|
|
4094
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
4095
|
+
body: new URLSearchParams({ grant_type: "refresh_token", refresh_token: p.refresh_token, client_id: p.client_id, resource: cfg.resource }),
|
|
4096
|
+
signal: AbortSignal.timeout(1e4)
|
|
4097
|
+
});
|
|
4098
|
+
} catch {
|
|
4099
|
+
throw new Error("connection_verification_pending: refresh outcome unknown; preserve the original connection and references, do not repeat authorization or business requests");
|
|
4100
|
+
}
|
|
4101
|
+
if (!response.ok) {
|
|
4102
|
+
let rejected = response.status === 401 || response.status === 403;
|
|
4103
|
+
if (response.status === 400) {
|
|
4104
|
+
try {
|
|
4105
|
+
const problem = await response.json();
|
|
4106
|
+
rejected = ["invalid_grant", "invalid_client", "unauthorized_client"].includes(problem?.error ?? "");
|
|
4107
|
+
} catch {
|
|
4108
|
+
}
|
|
4109
|
+
}
|
|
4110
|
+
if (rejected) throw new Error("authorization_required: connection refresh rejected");
|
|
4111
|
+
throw new Error("connection_verification_pending: refresh unavailable; preserve the original connection and references");
|
|
4112
|
+
}
|
|
4113
|
+
let token;
|
|
4114
|
+
try {
|
|
4115
|
+
token = await response.json();
|
|
4116
|
+
} catch {
|
|
4117
|
+
throw new Error("connection_verification_pending: invalid refresh response; preserve the original connection and references");
|
|
4118
|
+
}
|
|
4119
|
+
if (!token || typeof token.access_token !== "string" || !token.access_token || typeof token.token_type !== "string" || token.token_type.toLowerCase() !== "bearer" || typeof token.expires_in !== "number" || !Number.isFinite(token.expires_in) || token.expires_in <= 0 || (!Number.isFinite(Date.now() + token.expires_in * 1e3) || Date.now() + token.expires_in * 1e3 > 864e13) || token.refresh_token !== void 0 && (typeof token.refresh_token !== "string" || !token.refresh_token)) {
|
|
4120
|
+
throw new Error("connection_verification_pending: invalid refresh response; preserve the original connection and references");
|
|
4121
|
+
}
|
|
4122
|
+
const now = Date.now();
|
|
4123
|
+
candidate = {
|
|
4124
|
+
...p,
|
|
4125
|
+
access_token: token.access_token,
|
|
4126
|
+
refresh_token: token.refresh_token ?? p.refresh_token,
|
|
4127
|
+
expires_at: new Date(now + token.expires_in * 1e3).toISOString(),
|
|
4128
|
+
refresh_after: new Date(now + token.expires_in * 1e3 - Math.min(3e4, Math.max(100, token.expires_in * 100))).toISOString(),
|
|
4129
|
+
identity_verification_pending: true
|
|
4130
|
+
};
|
|
4131
|
+
saveHubProfileUnlocked(candidate, env);
|
|
4132
|
+
}
|
|
4133
|
+
const identity = await probeHubIdentity(cfg.resource, candidate.access_token);
|
|
4134
|
+
if (identity.buyer_id !== p.subject || identity.consumer_id !== p.consumer_id) {
|
|
4067
4135
|
throw new Error("authorization_required: refreshed identity changed");
|
|
4068
4136
|
}
|
|
4069
|
-
|
|
4070
|
-
|
|
4137
|
+
if (!(Date.parse(candidate.expires_at ?? "") > Date.now())) {
|
|
4138
|
+
throw new Error("connection_verification_pending: token expired during identity check; preserve the original connection and references");
|
|
4139
|
+
}
|
|
4140
|
+
delete candidate.identity_verification_pending;
|
|
4141
|
+
saveHubProfileUnlocked(candidate, env);
|
|
4142
|
+
return candidate.access_token;
|
|
4071
4143
|
});
|
|
4072
4144
|
}
|
|
4073
4145
|
__name(connectedHubToken, "connectedHubToken");
|
|
@@ -4095,13 +4167,14 @@ function loadHubConfig(env = process.env) {
|
|
|
4095
4167
|
}
|
|
4096
4168
|
__name(loadHubConfig, "loadHubConfig");
|
|
4097
4169
|
function toSdkConfig(cfg) {
|
|
4170
|
+
const base = { baseUrl: cfg.baseURL, resource: cfg.baseURL.replace(/\/+$/, "") };
|
|
4098
4171
|
if (cfg.bearerToken) {
|
|
4099
|
-
return {
|
|
4172
|
+
return { ...base, token: cfg.bearerToken };
|
|
4100
4173
|
}
|
|
4101
4174
|
if (cfg.apiKey) {
|
|
4102
|
-
return {
|
|
4175
|
+
return { ...base, token: cfg.apiKey, apiKeyHeader: "X-ItPay-Key" };
|
|
4103
4176
|
}
|
|
4104
|
-
return
|
|
4177
|
+
return base;
|
|
4105
4178
|
}
|
|
4106
4179
|
__name(toSdkConfig, "toSdkConfig");
|
|
4107
4180
|
var HubClient2 = class {
|
|
@@ -4167,14 +4240,14 @@ var HubClient2 = class {
|
|
|
4167
4240
|
let token;
|
|
4168
4241
|
if (this.cfg.sessionEnv) {
|
|
4169
4242
|
token = await connectedHubToken(this.cfg.sessionEnv);
|
|
4170
|
-
this.sdk = new HubClient({
|
|
4243
|
+
this.sdk = new HubClient(toSdkConfig({ ...this.cfg, bearerToken: token }));
|
|
4171
4244
|
}
|
|
4172
4245
|
try {
|
|
4173
4246
|
return await fn();
|
|
4174
4247
|
} catch (err) {
|
|
4175
4248
|
if (!(err instanceof HubApiError) || err.status !== 401 || err.envelope.error.code !== "unauthenticated" || !this.cfg.sessionEnv || !token) throw err;
|
|
4176
4249
|
const refreshed = await connectedHubToken(this.cfg.sessionEnv, token);
|
|
4177
|
-
this.sdk = new HubClient({
|
|
4250
|
+
this.sdk = new HubClient(toSdkConfig({ ...this.cfg, bearerToken: refreshed }));
|
|
4178
4251
|
return await fn();
|
|
4179
4252
|
}
|
|
4180
4253
|
} catch (err) {
|
|
@@ -5588,7 +5661,7 @@ function writeCommandEnvelope(value, options = {}) {
|
|
|
5588
5661
|
}
|
|
5589
5662
|
return { ...action, command: [...assignments, qualifyItPayCommand(action.command, declaredAgentType())].join(" ") };
|
|
5590
5663
|
}, "qualify");
|
|
5591
|
-
value = { ...value, next: value.next ? qualify(value.next) : null, recovery: value.recovery.map(qualify).filter((action) => action !== null) };
|
|
5664
|
+
value = { ...value, instruction: value.instruction + " " + routingInstruction(value), next: value.next ? qualify(value.next) : null, recovery: value.recovery.map(qualify).filter((action) => action !== null) };
|
|
5592
5665
|
const out = options.output ?? ((text2) => {
|
|
5593
5666
|
process.stdout.write(text2);
|
|
5594
5667
|
});
|
|
@@ -5603,6 +5676,21 @@ function writeCommandEnvelope(value, options = {}) {
|
|
|
5603
5676
|
for (const action of value.recovery) out("recovery: " + action.command + "\n when: " + action.reason + "\n");
|
|
5604
5677
|
}
|
|
5605
5678
|
__name(writeCommandEnvelope, "writeCommandEnvelope");
|
|
5679
|
+
function hubFailureInstruction(error, fallback) {
|
|
5680
|
+
if (!(error instanceof HttpError)) return fallback;
|
|
5681
|
+
if ((error.code === "request_timeout" || error.code === "request_cancelled") && error.message.includes("outcome is unknown")) return "\u63D0\u4EA4\u7ED3\u679C\u672A\u77E5\uFF1B\u4FDD\u7559\u539F\u8EAB\u4EFD\u3001\u5165\u53E3\u3001\u5E42\u7B49\u952E\u53CA\u8BF7\u6C42\u5F15\u7528\uFF0C\u5148\u8BFB\u53D6\u539F\u4EFB\u52A1\uFF0C\u4E0D\u6362\u8DEF\u91CD\u53D1\u6216\u91CD\u65B0\u4ED8\u6B3E\u3002";
|
|
5682
|
+
if (error.code === "request_timeout" || error.code === "request_cancelled") return "Hub \u8BFB\u53D6\u8D85\u65F6\u6216\u5DF2\u53D6\u6D88\uFF0C\u672A\u53D6\u5F97\u5F53\u524D\u4E8B\u5B9E\uFF1B\u8FD9\u4E0D\u8868\u793A\u64CD\u4F5C\u672A\u53D1\u5E03\u6216\u6D88\u8D39\u9884\u7B97\u4E0D\u8DB3\u3002\u4FDD\u7559\u539F\u8EAB\u4EFD\u3001\u6761\u4EF6\u53CA\u5DF2\u6709\u8BF7\u6C42\u5F15\u7528\uFF0C\u7A0D\u540E\u8BFB\u53D6\uFF1B\u4E0D\u6362\u8DEF\u91CD\u53D1\u3002";
|
|
5683
|
+
if (error.status === 404) return "\u8BE5\u64CD\u4F5C\u6216\u539F\u5F15\u7528\u5F53\u524D\u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u89C1\uFF1B\u6838\u5BF9\u539F\u7F16\u53F7\u53CA\u53EF\u89C1\u53D1\u5E03\uFF0C\u4E0D\u731C\u66FF\u4EE3\u64CD\u4F5C\u3002";
|
|
5684
|
+
if (error.status === 403) return "\u5F53\u524D\u51ED\u636E\u6743\u9650\u6216\u6388\u6743\u8303\u56F4\u4E0D\u8DB3\uFF1B\u6838\u5BF9\u5B9E\u9645\u62D2\u7EDD\u539F\u56E0\u53CA\u5B98\u65B9\u6388\u6743\uFF0C\u4FDD\u7559\u539F\u8EAB\u4EFD\u548C\u8BF7\u6C42\uFF0C\u4E0D\u6362\u5165\u53E3\u7ED5\u8FC7\u3002";
|
|
5685
|
+
return fallback;
|
|
5686
|
+
}
|
|
5687
|
+
__name(hubFailureInstruction, "hubFailureInstruction");
|
|
5688
|
+
function routingInstruction(value) {
|
|
5689
|
+
const result = value.result && typeof value.result === "object" ? value.result : {};
|
|
5690
|
+
const original = ["request_id", "run_id", "intent_id", "order_id", "topup_id"].some((key) => typeof result[key] === "string" && result[key] !== "") || ["unknown", "unavailable"].includes(value.status) || ["hub_request_unknown", "request_timeout", "request_cancelled"].includes(value.error?.code ?? "");
|
|
5691
|
+
return original ? "\u7EE7\u7EED\u539F\u8EAB\u4EFD\u3001\u5165\u53E3\u548C\u5DF2\u6709\u8BF7\u6C42\u5F15\u7528\uFF0C\u4E0D\u6362\u8DEF\u91CD\u53D1\u3002" : "\u5F53\u524D\u4E3A API Hub\uFF1B\u529E\u7406\u3001\u4EA4\u4ED8\u4E0E\u552E\u540E\u4F7F\u7528 Services\uFF0C\u7A7A\u7ED3\u679C\u53EA\u9650\u5F53\u524D\u76EE\u5F55\u53CA\u6761\u4EF6\u3002";
|
|
5692
|
+
}
|
|
5693
|
+
__name(routingInstruction, "routingInstruction");
|
|
5606
5694
|
|
|
5607
5695
|
// src/commands/hub.ts
|
|
5608
5696
|
function hub() {
|
|
@@ -5792,7 +5880,7 @@ var HubTaskRequestError = class extends Error {
|
|
|
5792
5880
|
super(error instanceof Error ? error.message : "original Hub request did not return a receipt");
|
|
5793
5881
|
this.requestID = task.request_id;
|
|
5794
5882
|
this.references = { request_id: task.request_id, ...task.run_id ? { run_id: task.run_id } : {}, ...task.intent_id ? { intent_id: task.intent_id } : {} };
|
|
5795
|
-
this.code = error instanceof HttpError ? error.code : ["authorization_required", "idempotency_conflict", "invalid_state"].find((code) => this.message.startsWith(code + ":")) ?? "hub_request_unknown";
|
|
5883
|
+
this.code = error instanceof HttpError ? error.code : ["authorization_required", "connection_verification_pending", "credential_persistence_failed", "idempotency_conflict", "invalid_state"].find((code) => this.message.startsWith(code + ":")) ?? "hub_request_unknown";
|
|
5796
5884
|
}
|
|
5797
5885
|
};
|
|
5798
5886
|
async function dispatchOriginalTask(client, store, task, options) {
|
|
@@ -5832,11 +5920,11 @@ async function dispatchOriginalTask(client, store, task, options) {
|
|
|
5832
5920
|
}
|
|
5833
5921
|
__name(dispatchOriginalTask, "dispatchOriginalTask");
|
|
5834
5922
|
function renderRun(rec, jsonOutput, note) {
|
|
5835
|
-
const charged = rec.actual_charge ? atomsToYuan(rec.actual_charge.amount_atoms) : "\
|
|
5923
|
+
const charged = rec.actual_charge ? atomsToYuan(rec.actual_charge.amount_atoms) : "\u8D39\u7528\u56DE\u6267\u672A\u63D0\u4F9B";
|
|
5836
5924
|
writeCommandEnvelope({
|
|
5837
5925
|
status: rec.execution_state === "succeeded" ? "executed" : rec.execution_state,
|
|
5838
|
-
result: { run_id: rec.run_id, execution_state: rec.execution_state, settlement_state: rec.settlement_state, actual_charge: rec.actual_charge ?? null, result: rec.result ?? null, error: rec.error ?? null, ...note ? { note } : {} },
|
|
5839
|
-
instruction: rec.execution_state === "succeeded" ? `\
|
|
5926
|
+
result: { run_id: rec.run_id, execution_state: rec.execution_state, settlement_state: rec.settlement_state, ...rec.delivery_state ? { delivery_state: rec.delivery_state } : {}, actual_charge: rec.actual_charge ?? null, result: rec.result ?? null, error: rec.error ?? null, ...note ? { note } : {} },
|
|
5927
|
+
instruction: rec.execution_state === "succeeded" ? `\u6267\u884C\u72B6\u6001\u4E3A succeeded\uFF1B\u4EA4\u4ED8\u72B6\u6001 ${rec.delivery_state ?? "\u672A\u63D0\u4F9B"}\uFF0C\u7ED3\u7B97\u72B6\u6001 ${rec.settlement_state ?? "\u672A\u63D0\u4F9B"}\uFF0C\u5B9E\u9645\u8D39\u7528\u56DE\u6267 ${charged}\u3002\u4EC5\u636E\u5B9E\u9645 result \u548C\u4EA4\u4ED8\u4E8B\u5B9E\u56DE\u7B54\uFF0C\u7A7A\u503C\u4E0D\u4EE3\u8868\u67E5\u8BE2\u6210\u529F\u4E14\u96F6\u6761\u3002` : `\u6267\u884C\u72B6\u6001 ${rec.execution_state}\uFF08${rec.error?.code ?? "\u65E0\u9519\u8BEF\u4EE3\u7801"}\uFF09\uFF0C\u7ED3\u7B97\u72B6\u6001 ${rec.settlement_state ?? "\u672A\u63D0\u4F9B"}\uFF0C\u5B9E\u9645\u8D39\u7528\u56DE\u6267 ${charged}\uFF1B\u7528 itpay api run-status ${rec.run_id} \u67E5\u8BE2\u539F\u4EFB\u52A1\uFF0C\u4E0D\u91CD\u590D\u53D1\u8D77\u3002`,
|
|
5840
5928
|
next: ["succeeded", "failed"].includes(rec.execution_state) ? null : { command: `itpay api run-status ${rec.run_id}`, reason: "\u67E5\u8BE2\u539F run \u72B6\u6001\uFF0C\u4E0D\u65B0\u5EFA\u8BF7\u6C42" },
|
|
5841
5929
|
recovery: []
|
|
5842
5930
|
}, {
|
|
@@ -5880,7 +5968,7 @@ async function runHubWallet(options) {
|
|
|
5880
5968
|
writeCommandEnvelope({
|
|
5881
5969
|
status: "ok",
|
|
5882
5970
|
result: { available: bal.available, held: bal.held },
|
|
5883
|
-
instruction: `\u53EF\u7528 ${atomsToYuan(bal.available.amount_atoms)}\uFF0C\u5728\u9014 ${atomsToYuan(bal.held.amount_atoms)}\u3002`,
|
|
5971
|
+
instruction: `\u5F53\u524D\u8D26\u6237\u94B1\u5305\uFF1A\u53EF\u7528 ${atomsToYuan(bal.available.amount_atoms)}\uFF0C\u5728\u9014 ${atomsToYuan(bal.held.amount_atoms)}\uFF1B\u4E0D\u4EE3\u8868\u672C Consumer \u7684\u6388\u6743\u6D88\u8D39\u4E0A\u9650\u3002`,
|
|
5884
5972
|
next: null,
|
|
5885
5973
|
recovery: []
|
|
5886
5974
|
}, {
|
|
@@ -5891,7 +5979,7 @@ async function runHubWallet(options) {
|
|
|
5891
5979
|
__name(runHubWallet, "runHubWallet");
|
|
5892
5980
|
async function runHubUsage(options) {
|
|
5893
5981
|
const usage = await hub().usage();
|
|
5894
|
-
writeCommandEnvelope({ status: "ok", result: usage, instruction: "\u5F53\u524D
|
|
5982
|
+
writeCommandEnvelope({ status: "ok", result: usage, instruction: "\u5F53\u524D\u8FDE\u63A5\u51ED\u636E\uFF08API Key \u6216 Consumer\uFF09\u8303\u56F4\u7684\u7528\u91CF\u4E0E\u8D39\u7528\u56DE\u6267\uFF1Bruns \u5305\u542B\u5931\u8D25\u8C03\u7528\uFF0C\u4E0D\u80FD\u5F53\u4F5C\u6210\u529F\u4EA4\u4ED8\u6B21\u6570\u3002\u94B1\u5305\u4F59\u989D\u5C5E\u4E8E\u8D26\u6237\u53E3\u5F84\uFF1B\u8BFB\u53D6\u4E0D\u4F1A\u518D\u6B21\u6267\u884C\u6216\u6263\u8D39\u3002", next: null, recovery: [] }, {
|
|
5895
5983
|
jsonOutput: Boolean(options.jsonOutput),
|
|
5896
5984
|
plainResult: [`gross ${atomsToYuan(usage.gross_atoms)} refunded ${atomsToYuan(usage.refunded_atoms)} net ${atomsToYuan(usage.net_atoms)} held ${atomsToYuan(usage.held_atoms)}`]
|
|
5897
5985
|
});
|
|
@@ -6162,12 +6250,15 @@ async function runHubConnect(options) {
|
|
|
6162
6250
|
plainResult: ["\u6253\u5F00\u6D4F\u89C8\u5668\u5B8C\u6210\u6388\u6743\uFF1A", ` ${authorizeURL}`]
|
|
6163
6251
|
});
|
|
6164
6252
|
const tokens = await done;
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
})
|
|
6169
|
-
|
|
6170
|
-
|
|
6253
|
+
let me;
|
|
6254
|
+
try {
|
|
6255
|
+
me = await probeHubIdentity(cfg.resource, tokens.accessToken);
|
|
6256
|
+
} catch (error) {
|
|
6257
|
+
if (error instanceof Error && error.message.startsWith("connection_verification_pending:")) {
|
|
6258
|
+
throw new Error("connection_not_saved: identity verification unavailable; this connection was not saved and the existing connection was not replaced");
|
|
6259
|
+
}
|
|
6260
|
+
throw error;
|
|
6261
|
+
}
|
|
6171
6262
|
if (!me.buyer_id || (!me.consumer_id || me.consumer_id !== `oauth:${cfg.clientID}` && !me.consumer_id.startsWith(`oauth:${cfg.clientID}:`))) throw new Error("authorization_required: OAuth consumer mismatch");
|
|
6172
6263
|
const subject = me.buyer_id;
|
|
6173
6264
|
storeHubSession(tokens.accessToken, tokens.refreshToken, tokens.expiresIn, subject, cfg.resource, process.env, me.consumer_id);
|
|
@@ -6191,12 +6282,12 @@ __name(runHubConnect, "runHubConnect");
|
|
|
6191
6282
|
|
|
6192
6283
|
// src/commands/api_commands.ts
|
|
6193
6284
|
function reportCLIError(error, contract) {
|
|
6194
|
-
const code = error instanceof HubTaskRequestError ? error.code : error instanceof HttpError ? error.code : error instanceof Error && error.message.startsWith("
|
|
6285
|
+
const code = error instanceof HubTaskRequestError ? error.code : error instanceof HttpError ? error.code : error instanceof Error && ["authorization_required", "connection_not_saved", "connection_verification_pending", "credential_persistence_failed"].some((code2) => error.message.startsWith(code2 + ":")) ? error.message.split(":", 1)[0] : contract?.code ?? "command_failed";
|
|
6195
6286
|
const auth = code === "authorization_required" || code === "unauthenticated";
|
|
6196
6287
|
const taskID = error instanceof HubTaskRequestError ? error.requestID : void 0;
|
|
6197
6288
|
const references = error instanceof HubTaskRequestError ? error.references : void 0;
|
|
6198
6289
|
const recover = taskID ? { command: qualifyItPayCommand(references?.run_id ? `itpay api run-status ${references.run_id}${contract?.jsonOutput ? " --json" : ""}` : `itpay api resume ${taskID}${contract?.jsonOutput ? " --json" : ""}`, declaredAgentType()), reason: "\u8BFB\u53D6\u6216\u6062\u590D\u540C\u4E00\u539F\u4EFB\u52A1\uFF0C\u4E0D\u521B\u5EFA\u66FF\u4EE3\u8BF7\u6C42" } : null;
|
|
6199
|
-
writeCommandEnvelope({ status: "error", error: { code, message: error instanceof Error ? error.message : String(error) }, ...references ? { result: references } : {}, instruction: auth ? "\u5148\u5B8C\u6210 ItPay API \u6B63\u5E38\u8FDE\u63A5\uFF1B\u4FDD\u7559\u539F\u8EAB\u4EFD\u548C\u4EFB\u52A1\uFF0C\u4E0D\u8981\u521B\u5EFA\u66FF\u4EE3\u8BF7\u6C42\u3002" : ["idempotency_conflict", "invalid_state"].includes(code) ? "\u539F\u4EFB\u52A1\u8BB0\u5F55\u4E0D\u4E00\u81F4\uFF1B\u4FDD\u7559\u8BB0\u5F55\u6838\u5BF9\uFF0C\u4E0D\u80FD\u4FEE\u6539\u51BB\u7ED3\u53C2\u6570\u7EE7\u7EED\u53D1\u9001\u3002" : taskID ? "\u539F\u8BF7\u6C42\u5C1A\u672A\u53D6\u5F97\u53EF\u7528\u56DE\u6267\uFF1B\u8FD9\u4E0D\u4EE3\u8868\u672A\u5230\u8FBE\u670D\u52A1\u5668\u3002\u4FDD\u7559\u539F\u8BF7\u6C42\u6062\u590D\uFF0C\u4E0D\u91CD\u65B0\u8C03\u7528\u6216\u5145\u503C\u3002" : contract?.instruction ?? "Check the command and current Hub connection; preserve original tasks.", next: auth ? { command: qualifyItPayCommand(`itpay api connect${contract?.jsonOutput ? " --json" : ""}`, declaredAgentType()), reason: "\u6B63\u5E38\u6388\u6743\u540E\u7EE7\u7EED\u539F\u4EFB\u52A1" } : ["idempotency_conflict", "invalid_state", "forbidden", "publication_changed", "credential_revalidation_required"].includes(code) ? null : recover, recovery: auth && recover ? [recover] : contract?.recovery ?? [] }, { jsonOutput: contract?.jsonOutput ?? process.argv.includes("--json") });
|
|
6290
|
+
writeCommandEnvelope({ status: "error", error: { code, message: error instanceof Error ? error.message : String(error) }, ...references ? { result: references } : {}, instruction: code === "connection_not_saved" ? "\u672C\u6B21\u8FDE\u63A5\u6821\u9A8C\u6682\u672A\u5B8C\u6210\uFF0C\u5C1A\u672A\u4FDD\u5B58\uFF1B\u539F\u6709\u8FDE\u63A5\u672A\u66FF\u6362\u3002\u670D\u52A1\u6062\u590D\u540E\u6309\u539F\u914D\u7F6E\u6B63\u5E38 connect\uFF0C\u4FDD\u7559\u539F\u8EAB\u4EFD\u548C\u4EFB\u52A1\uFF0C\u4E0D\u91CD\u53D1\u4E1A\u52A1\u3002" : code === "connection_verification_pending" ? "\u539F\u8FDE\u63A5\u6821\u9A8C\u6682\u672A\u5B8C\u6210\uFF1B\u4FDD\u7559\u539F\u8EAB\u4EFD\u548C\u5F15\u7528\uFF0C\u4E0D\u91CD\u65B0\u6388\u6743\u3001\u4E0D\u91CD\u53D1\u4E1A\u52A1\u3002\u7A0D\u540E\u53EA\u8BFB\u6838\u5BF9\u539F\u4EFB\u52A1\u3002" : code === "credential_persistence_failed" ? "\u539F\u8FDE\u63A5\u672A\u80FD\u5B89\u5168\u843D\u76D8\uFF1B\u505C\u6B62\u91CD\u8BD5\u5E76\u6838\u5BF9\u79C1\u6709\u5B58\u50A8\uFF0C\u4E0D\u6E05\u72B6\u6001\u6216\u6362\u8EAB\u4EFD\u3002" : auth ? "\u5148\u5B8C\u6210 ItPay API \u6B63\u5E38\u8FDE\u63A5\uFF1B\u4FDD\u7559\u539F\u8EAB\u4EFD\u548C\u4EFB\u52A1\uFF0C\u4E0D\u8981\u521B\u5EFA\u66FF\u4EE3\u8BF7\u6C42\u3002" : ["idempotency_conflict", "invalid_state"].includes(code) ? "\u539F\u4EFB\u52A1\u8BB0\u5F55\u4E0D\u4E00\u81F4\uFF1B\u4FDD\u7559\u8BB0\u5F55\u6838\u5BF9\uFF0C\u4E0D\u80FD\u4FEE\u6539\u51BB\u7ED3\u53C2\u6570\u7EE7\u7EED\u53D1\u9001\u3002" : taskID ? "\u539F\u8BF7\u6C42\u5C1A\u672A\u53D6\u5F97\u53EF\u7528\u56DE\u6267\uFF1B\u8FD9\u4E0D\u4EE3\u8868\u672A\u5230\u8FBE\u670D\u52A1\u5668\u3002\u4FDD\u7559\u539F\u8BF7\u6C42\u6062\u590D\uFF0C\u4E0D\u91CD\u65B0\u8C03\u7528\u6216\u5145\u503C\u3002" : hubFailureInstruction(error, contract?.instruction ?? "Check the command and current Hub connection; preserve original tasks."), next: auth || code === "connection_not_saved" ? { command: qualifyItPayCommand(`itpay api connect${contract?.jsonOutput ? " --json" : ""}`, declaredAgentType()), reason: code === "connection_not_saved" ? "\u672C\u6B21\u8FDE\u63A5\u672A\u4FDD\u5B58\uFF1B\u6309\u539F\u914D\u7F6E\u5B8C\u6210\u6B63\u5E38\u8FDE\u63A5" : "\u6B63\u5E38\u6388\u6743\u540E\u7EE7\u7EED\u539F\u4EFB\u52A1" } : ["idempotency_conflict", "invalid_state", "forbidden", "publication_changed", "credential_revalidation_required", "credential_persistence_failed"].includes(code) ? null : recover, recovery: auth && recover ? [recover] : contract?.recovery ?? [] }, { jsonOutput: contract?.jsonOutput ?? process.argv.includes("--json") });
|
|
6200
6291
|
process.exitCode = 1;
|
|
6201
6292
|
}
|
|
6202
6293
|
__name(reportCLIError, "reportCLIError");
|
|
@@ -6233,7 +6324,7 @@ function registerAPICommands(program3) {
|
|
|
6233
6324
|
try {
|
|
6234
6325
|
await runHubInspect(operationID2, { jsonOutput: Boolean(options.json) });
|
|
6235
6326
|
} catch (error) {
|
|
6236
|
-
reportCLIError(error, { jsonOutput: Boolean(options.json), code: "hub_inspect_failed", instruction: "
|
|
6327
|
+
reportCLIError(error, { jsonOutput: Boolean(options.json), code: "hub_inspect_failed", instruction: "\u672A\u53D6\u5F97\u64CD\u4F5C\u5408\u540C\uFF1B\u4FDD\u7559\u5F53\u524D\u6761\u4EF6\uFF0C\u6309\u5B9E\u9645\u9519\u8BEF\u6838\u5BF9 Hub \u8FDE\u63A5\uFF0C\u4E0D\u63A8\u6D4B\u53D1\u5E03\u72B6\u6001\u3002", recovery: [] });
|
|
6237
6328
|
}
|
|
6238
6329
|
});
|
|
6239
6330
|
hubCmd.command("run").description("Execute a metered operation (idempotent, prepaid)").argument("<operation_id>").requiredOption("--publication <id>", "expected publication id from inspect").requiredOption("--input <json>", "JSON object, @file path, or - for stdin").option("--credential-id <id>", "stored BYOK credential reference").option("--source-credentials <json>", "Native source credential references JSON or @file").option("--max-charge <atoms>", "max charge in atoms (scale 6)").option("--request-id <id>", "stable logical request id \u2014 replays resume the same request").option("--wait <seconds>", "poll run status until terminal", "0").option("--json", "output JSON").action(async (operationID2, options) => {
|
|
@@ -6662,7 +6753,7 @@ __name(streamSSE, "streamSSE");
|
|
|
6662
6753
|
|
|
6663
6754
|
// src/state/device_key.ts
|
|
6664
6755
|
import { createHash as createHash5, createPrivateKey, createPublicKey, generateKeyPairSync, randomUUID as randomUUID6 } from "node:crypto";
|
|
6665
|
-
import { constants, closeSync, fstatSync, linkSync, lstatSync as lstatSync2, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync8, unlinkSync as
|
|
6756
|
+
import { constants, closeSync, fstatSync, linkSync, lstatSync as lstatSync2, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync8, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
6666
6757
|
import { dirname as dirname4 } from "node:path";
|
|
6667
6758
|
function invalid(code) {
|
|
6668
6759
|
return Object.assign(new Error(code), { code });
|
|
@@ -6714,7 +6805,7 @@ function createDeviceKey(path2, existingIdentity) {
|
|
|
6714
6805
|
return canonical;
|
|
6715
6806
|
} finally {
|
|
6716
6807
|
try {
|
|
6717
|
-
|
|
6808
|
+
unlinkSync3(temp);
|
|
6718
6809
|
} catch (error) {
|
|
6719
6810
|
throw Object.assign(error instanceof Error ? error : new Error("Key temporary cleanup failed"), { deviceStateOperation: "cleanup_private_key_temporary", canonicalKeyPublished: canonicalPublished });
|
|
6720
6811
|
}
|
|
@@ -6724,7 +6815,7 @@ __name(createDeviceKey, "createDeviceKey");
|
|
|
6724
6815
|
|
|
6725
6816
|
// src/state/device_session_cache.ts
|
|
6726
6817
|
import { createHash as createHash6, randomUUID as randomUUID7 } from "node:crypto";
|
|
6727
|
-
import { constants as constants2, closeSync as closeSync2, fstatSync as fstatSync2, linkSync as linkSync2, lstatSync as lstatSync3, mkdirSync as mkdirSync6, openSync as openSync2, readFileSync as readFileSync9, renameSync as renameSync4, readdirSync as readdirSync2, unlinkSync as
|
|
6818
|
+
import { constants as constants2, closeSync as closeSync2, fstatSync as fstatSync2, linkSync as linkSync2, lstatSync as lstatSync3, mkdirSync as mkdirSync6, openSync as openSync2, readFileSync as readFileSync9, renameSync as renameSync4, readdirSync as readdirSync2, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
6728
6819
|
import { join as join3 } from "node:path";
|
|
6729
6820
|
function invalid2(code) {
|
|
6730
6821
|
return Object.assign(new Error(code), { code });
|
|
@@ -6767,7 +6858,7 @@ function writeComplete(path2, text2, createOnly) {
|
|
|
6767
6858
|
return true;
|
|
6768
6859
|
} finally {
|
|
6769
6860
|
try {
|
|
6770
|
-
|
|
6861
|
+
unlinkSync4(temp);
|
|
6771
6862
|
} catch (error) {
|
|
6772
6863
|
if (error.code !== "ENOENT") throw error;
|
|
6773
6864
|
}
|
|
@@ -7331,7 +7422,7 @@ __name(checkAuthorizationBudget, "checkAuthorizationBudget");
|
|
|
7331
7422
|
|
|
7332
7423
|
// src/state/operation_journal.ts
|
|
7333
7424
|
import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
|
|
7334
|
-
import { chmodSync as chmodSync4, existsSync as existsSync4, linkSync as linkSync3, mkdirSync as mkdirSync7, readFileSync as readFileSync11, unlinkSync as
|
|
7425
|
+
import { chmodSync as chmodSync4, existsSync as existsSync4, linkSync as linkSync3, mkdirSync as mkdirSync7, readFileSync as readFileSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
7335
7426
|
import { basename, resolve as resolve4 } from "node:path";
|
|
7336
7427
|
var OperationJournal = class {
|
|
7337
7428
|
constructor(legacyPath) {
|
|
@@ -7371,7 +7462,7 @@ var OperationJournal = class {
|
|
|
7371
7462
|
}
|
|
7372
7463
|
} finally {
|
|
7373
7464
|
try {
|
|
7374
|
-
|
|
7465
|
+
unlinkSync5(temporaryPath);
|
|
7375
7466
|
} catch (error) {
|
|
7376
7467
|
if (error.code !== "ENOENT") throw error;
|
|
7377
7468
|
}
|
|
@@ -12164,7 +12255,7 @@ __name(railAftercareOrder, "railAftercareOrder");
|
|
|
12164
12255
|
|
|
12165
12256
|
// src/state/task_journal.ts
|
|
12166
12257
|
import { randomUUID as randomUUID10, createHash as createHash10 } from "node:crypto";
|
|
12167
|
-
import { existsSync as existsSync5, linkSync as linkSync4, lstatSync as lstatSync5, mkdirSync as mkdirSync9, readFileSync as readFileSync12, readdirSync as readdirSync4, unlinkSync as
|
|
12258
|
+
import { existsSync as existsSync5, linkSync as linkSync4, lstatSync as lstatSync5, mkdirSync as mkdirSync9, readFileSync as readFileSync12, readdirSync as readdirSync4, unlinkSync as unlinkSync6, writeFileSync as writeFileSync8 } from "node:fs";
|
|
12168
12259
|
import { join as join4 } from "node:path";
|
|
12169
12260
|
var PAUSED_STAGES = /* @__PURE__ */ new Set(["login_required", "rate_limited", "quota_paused", "auth_pending", "awaiting_input"]);
|
|
12170
12261
|
var TERMINAL_STAGES = /* @__PURE__ */ new Set(["completed", "delivered", "issued", "failed", "cancelled", "refunded"]);
|
|
@@ -12287,7 +12378,7 @@ var TaskJournal = class {
|
|
|
12287
12378
|
linkSync4(temp, target2);
|
|
12288
12379
|
} finally {
|
|
12289
12380
|
try {
|
|
12290
|
-
|
|
12381
|
+
unlinkSync6(temp);
|
|
12291
12382
|
} catch (e) {
|
|
12292
12383
|
if (!object2(e) || e.code !== "ENOENT") throw e;
|
|
12293
12384
|
}
|
|
@@ -16703,8 +16794,8 @@ __name(installDefinition, "installDefinition");
|
|
|
16703
16794
|
import { createHash as createHash12 } from "node:crypto";
|
|
16704
16795
|
|
|
16705
16796
|
// src/state/skill_identity.generated.ts
|
|
16706
|
-
var CANONICAL_SKILL_SHA256 = "
|
|
16707
|
-
var CANONICAL_API_SKILL_SHA256 = "
|
|
16797
|
+
var CANONICAL_SKILL_SHA256 = "4a38087a41ed4b9b6e879726b93bdef99ca67fccd2a0f9837123d5b334b046c0";
|
|
16798
|
+
var CANONICAL_API_SKILL_SHA256 = "dffec781d5053bbdb93ec555ad2b1b4a7cad55c2281a3c9c19597a4a9418bde6";
|
|
16708
16799
|
|
|
16709
16800
|
// src/commands/skill.ts
|
|
16710
16801
|
import { existsSync as existsSync9, readFileSync as readFileSync16 } from "node:fs";
|
|
@@ -16778,7 +16869,7 @@ ${CODEX_WAIT_GUIDANCE}
|
|
|
16778
16869
|
const envelope = {
|
|
16779
16870
|
status: "shown",
|
|
16780
16871
|
result: { skill: ITPAY_SKILL, content },
|
|
16781
|
-
instruction: agentType ? agentType === "workbuddy" ? "\u5B8C\u6574\u8BFB\u53D6\u539F\u6587\u5E76\u6309\u5BBF\u4E3B\u6280\u80FD\u65B9\u5F0F\
|
|
16872
|
+
instruction: agentType ? agentType === "workbuddy" ? "\u5B8C\u6574\u8BFB\u53D6 Services \u539F\u6587\u5E76\u6309\u5BBF\u4E3B\u6280\u80FD\u65B9\u5F0F\u542F\u7528\uFF1BAPI/\u6570\u636E\u4EFB\u52A1\u6539\u8BFB itpay-api\uFF0C\u4E0D\u56E0 Services \u76EE\u5F55\u672A\u5217\u51FA\u5C31\u5224\u65E0\u80FD\u529B\u3002\u6309\u7528\u6237\u4EA4\u4ED8\u7269\u9009\u62E9\u7B2C\u4E00\u6761\u547D\u4EE4\u3002\u4FDD\u6301 workbuddy\u3001\u540C\u4E00\u5165\u53E3\u548C Backend\uFF1B\u53EA\u6709\u5B9E\u9645\u6301\u4E45\u5316\u64CD\u4F5C\u88AB\u62D2\u65F6\u624D\u6CBF\u5BBF\u4E3B\u6B63\u5F0F\u6D41\u7A0B\u7533\u8BF7\u6240\u9700\u6743\u9650\uFF0C\u62D2\u7EDD\u540E\u62A5\u544A\u53D7\u963B\u64CD\u4F5C\uFF0C\u4E0D\u5220\u9664 identity\u3002" : `\u5B8C\u6574\u8BFB\u53D6\u539F\u6587\u5E76\u6309\u5BBF\u4E3B\u6280\u80FD\u65B9\u5F0F\u4FDD\u5B58\u542F\u7528\uFF1B\u628A\u81EA\u5DF1\u89C6\u4E3A\u670D\u52A1\u7528\u6237\u7684\u4EE3\u7406\uFF0C\u5148\u7406\u89E3\u7528\u6237\u610F\u56FE\u548C\u89E3\u91CA\u7528\u6237\u6743\u76CA\uFF0C\u518D\u9009\u62E9\u8D2D\u4E70\u3001\u5DF2\u8D2D\u5185\u5BB9\u3001\u8BA2\u5355\u6216\u9000\u6B3E\u5BF9\u5E94\u7684\u7B2C\u4E00\u6761\u547D\u4EE4\u3002\u5F53\u524D Agent Type \u662F ${agentType}\uFF0C\u540E\u7EED\u547D\u4EE4\u4FDD\u6301\u4E0D\u53D8\u3002` : "\u5B8C\u6574\u8BFB\u53D6\u5E76\u9075\u5B88 Skill\uFF1B\u5148\u5982\u5B9E\u9009\u62E9\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u5BF9\u5E94\u7684 Agent Type\u3002",
|
|
16782
16873
|
next: agentType ? null : { command: "itpay install --json", reason: "\u9009\u62E9\u771F\u5B9E\u4E14\u7A33\u5B9A\u7684 Agent Type" },
|
|
16783
16874
|
recovery: []
|
|
16784
16875
|
};
|
|
@@ -16842,7 +16933,7 @@ function showAPISkill(options) {
|
|
|
16842
16933
|
writeCommandEnvelope2({
|
|
16843
16934
|
status: "shown",
|
|
16844
16935
|
result: { skill: "itpay-api", content },
|
|
16845
|
-
instruction: "\u5B8C\u6574\u8BFB\u53D6 API Skill\
|
|
16936
|
+
instruction: "\u5B8C\u6574\u8BFB\u53D6 API Skill\uFF1BAPI/\u6570\u636E\u4EFB\u52A1\u76F4\u63A5\u6309 itpay api --help\u3001discover\u3001inspect \u7EE7\u7EED\uFF0C\u4E0D\u5148\u67E5 Services \u76EE\u5F55\uFF1B\u9700\u8981\u8BA4\u8BC1\u65F6\u7531\u672C\u4EBA\u5B8C\u6210 api connect\uFF0C\u5DF2\u6709\u4EFB\u52A1\u6CBF\u539F\u5F15\u7528\u6062\u590D\u3002\u4FDD\u6301\u771F\u5B9E\u5BBF\u4E3B\u3001Hub \u7AEF\u70B9\u548C\u72B6\u6001\u76EE\u5F55\u3002",
|
|
16846
16937
|
next: null,
|
|
16847
16938
|
recovery: []
|
|
16848
16939
|
}, {
|
|
@@ -16916,7 +17007,7 @@ async function runSetup(backend, config, skillPath, options = {}) {
|
|
|
16916
17007
|
reason: "\u7531\u672C\u4EBA\u5B8C\u6210\u5B98\u65B9\u8D26\u53F7\u6388\u6743\uFF0C\u4E0D\u81EA\u52A8\u767B\u5F55"
|
|
16917
17008
|
} } : {}
|
|
16918
17009
|
},
|
|
16919
|
-
instruction: account.status === "authenticated" ? "\u8BBE\u5907\u5DF2\u51C6\u5907\u597D\
|
|
17010
|
+
instruction: (account.status === "authenticated" ? "\u8BBE\u5907\u5DF2\u51C6\u5907\u597D\uFF0CServices \u8D26\u53F7\u5DF2\u6388\u6743\uFF1B\u672C\u6B21\u672A\u6838\u9A8C Hub API \u6388\u6743\u3002" : "\u8BBE\u5907\u5DF2\u51C6\u5907\u597D\uFF1BServices \u9700\u8981\u8D26\u53F7\u7684\u529F\u80FD\u518D\u8BF7\u672C\u4EBA\u6388\u6743\uFF0C\u672C\u6B21\u672A\u6838\u9A8C Hub API \u6388\u6743\u3002") + " \u6309\u4EA4\u4ED8\u7269\u9009\u62E9\u540C\u5305 Skill\uFF1AAPI/\u7ED3\u6784\u5316\u6570\u636E\u8BFB itpay skill show itpay-api --json\uFF0C\u518D api discover\uFF1B\u529E\u7406\u3001\u4EA4\u4ED8\u548C\u552E\u540E\u8BFB itpay skill show itpay --json\u3002skill_path \u662F Services \u539F\u8DEF\u5F84\uFF0C\u4E0D\u8981\u6C42 API \u5148\u8BFB\u94C1\u8DEF\u8BF4\u660E\u3002\u4FDD\u7559\u539F launcher\u3001\u771F\u5B9E\u5BBF\u4E3B\u548C\u72B6\u6001\u76EE\u5F55\uFF0C\u65B0\u4F1A\u8BDD\u4E0D\u521B\u5EFA\u65B0\u8EAB\u4EFD\uFF1B\u6B63\u5E38\u4EFB\u52A1\u4E0D\u91CD\u590D setup\u3002\u65B0\u4EFB\u52A1\u4EC5\u5728\u5BBF\u4E3B\u83B7\u51C6\u4E14\u80FD\u6267\u884C CLI \u65F6\u4F18\u5148 CLI\uFF0C\u5426\u5219\u4F7F\u7528\u5BF9\u5E94\u6258\u7BA1 MCP\uFF1B\u4E0D\u8981\u6C42\u4E91\u5BBF\u4E3B\u8BD5\u88C5\u3002\u5DF2\u53D7\u7406\u3001\u5F85\u4ED8\u6B3E\u6216\u672A\u77E5\u7ED3\u679C\u53EA\u6CBF\u539F\u8EAB\u4EFD\u3001\u5165\u53E3\u548C\u4E1A\u52A1\u5F15\u7528\u6062\u590D\uFF0C\u4E0D\u6362\u8DEF\u91CD\u53D1\u3002",
|
|
16920
17011
|
next: null,
|
|
16921
17012
|
recovery: []
|
|
16922
17013
|
}, { ...options, ...config.agentType ? { agentType: config.agentType } : {} });
|
|
@@ -17262,7 +17353,7 @@ async function runCatalogList(backend, options = {}) {
|
|
|
17262
17353
|
writeCommandEnvelope2({
|
|
17263
17354
|
status: empty ? "catalog_empty" : "listed",
|
|
17264
17355
|
result: { catalog_version: manifest.version, services: services2 },
|
|
17265
|
-
instruction: empty ? "\u5F53\u524D\u6CA1\u6709\u5DF2\u53D1\u5E03\u670D\u52A1\
|
|
17356
|
+
instruction: empty ? "\u5F53\u524D Services \u76EE\u5F55\u6CA1\u6709\u5DF2\u53D1\u5E03\u670D\u52A1\uFF0C\u4E0D\u4EE3\u8868 API Hub \u6CA1\u6709\u5339\u914D\u9879\uFF1BAPI/\u6570\u636E\u4EFB\u52A1\u4F7F\u7528 itpay api discover\u3002\u672C\u6B21\u8BFB\u53D6\u7ED3\u675F\uFF0C\u4E0D\u731C\u6D4B\u670D\u52A1\u6216\u81EA\u52A8\u91CD\u8BD5\u3002" : options.locale === "en" ? "This is the Services catalog, not the API Hub catalog. API/data tasks use itpay api discover. Explain the service, operations and pricing; start only a matching declared operation." : "\u5411\u7528\u6237\u89E3\u91CA\u4E3B\u670D\u52A1\u3001\u8F85\u52A9\u6B65\u9AA4\u548C\u4EF7\u683C\uFF1B\u8FD9\u662F Services \u76EE\u5F55\uFF0C\u4E0D\u542B API Hub \u76EE\u5F55\u3002API/\u7ED3\u6784\u5316\u6570\u636E\u7528 itpay api discover\uFF0C\u4E0D\u80FD\u56E0\u8FD9\u91CC\u672A\u5217\u51FA\u5C31\u5224\u5B9A ItPay \u65E0\u6B64\u80FD\u529B\u3002\u529E\u7406\u3001\u4EA4\u4ED8\u548C\u552E\u540E\u6309\u5339\u914D\u7684 service_id\u3001\u64CD\u4F5C\u53CA\u4EF7\u683C\u7EE7\u7EED\u3002",
|
|
17266
17357
|
next: services2.length === 1 && firstServiceID ? { command: `itpay services start ${firstServiceID}${jsonFlag}`, reason: "\u4EC5\u5F53\u5F53\u524D\u670D\u52A1\u7B26\u5408\u7528\u6237\u8BF7\u6C42\u65F6\u8BFB\u53D6\u8F93\u5165\u5408\u540C\uFF1B\u4E0D\u8868\u793A\u8D2D\u4E70\u540C\u610F" } : null,
|
|
17267
17358
|
recovery: []
|
|
17268
17359
|
}, {
|
|
@@ -19105,19 +19196,28 @@ __name(resumeEnvelope, "resumeEnvelope");
|
|
|
19105
19196
|
|
|
19106
19197
|
// src/main.ts
|
|
19107
19198
|
var program2 = new Command();
|
|
19108
|
-
program2.name("itpay").description("
|
|
19199
|
+
program2.name("itpay").description("ItPay CLI \u2014 Services, API Hub, orders, and human-authorized content").option("--agent-type <type>", "agent runtime type used for device enrollment and client-specific guidance").version(CLI_VERSION2).addHelpText("after", `
|
|
19109
19200
|
Agent quick start:
|
|
19110
19201
|
1. Use one official package in the host's permitted persistent npm location.
|
|
19111
19202
|
2. Run: itpay setup --agent-type <actual_type> --json
|
|
19112
|
-
3. Read
|
|
19203
|
+
3. Read the same-package Services or API Skill for the requested outcome.
|
|
19204
|
+
Keep the existing launcher, actual Agent Type and state directory across sessions.
|
|
19205
|
+
Setup checks Services device/account status, not API Hub authorization.
|
|
19113
19206
|
|
|
19114
19207
|
Common human intents:
|
|
19115
|
-
|
|
19208
|
+
API or structured data skill show itpay-api --json \u2192 api discover
|
|
19209
|
+
Service handling/delivery skill show itpay --json \u2192 catalog list
|
|
19116
19210
|
Previously purchased item vault list
|
|
19117
19211
|
Purchase history orders
|
|
19118
19212
|
Delivery or refund problem resume the known Order or Refund
|
|
19119
19213
|
Review a completed service feedback submit
|
|
19120
19214
|
|
|
19215
|
+
New tasks: prefer the official pinned CLI only when this host permits and can
|
|
19216
|
+
execute it; otherwise use the corresponding hosted Services or Hub MCP. A cloud
|
|
19217
|
+
host is not required to install software. Route by deliverable, not "query".
|
|
19218
|
+
Accepted, payment-pending or unknown tasks keep their original identity, entry
|
|
19219
|
+
and request/run/order; never switch entries to resubmit.
|
|
19220
|
+
|
|
19121
19221
|
The Agent runs commands. Ask the human only to choose, authorize, pay, provide
|
|
19122
19222
|
required contact details, or confirm a refund. Never expose commands or internal IDs.
|
|
19123
19223
|
`);
|
|
@@ -19523,8 +19623,8 @@ program2.command("next").description("Show the next recommended agent action fro
|
|
|
19523
19623
|
});
|
|
19524
19624
|
}
|
|
19525
19625
|
});
|
|
19526
|
-
var catalogCmd = program2.command("catalog").description("Browse
|
|
19527
|
-
catalogCmd.command("list").description("List
|
|
19626
|
+
var catalogCmd = program2.command("catalog").description("Browse the Services catalog (API data uses api discover)");
|
|
19627
|
+
catalogCmd.command("list").description("List published Services; this is not the API Hub catalog").option("--json", "output JSON instead of terminal text").action(async (options) => {
|
|
19528
19628
|
const backend = newBackendClient(loadConfig());
|
|
19529
19629
|
try {
|
|
19530
19630
|
await requirePlatformCompatibility(backend);
|
package/dist/src/state/config.js
CHANGED
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"current_flow": [
|
|
35
35
|
"Use the authorized channel/Backend and host-permitted tool prefix/cache/state directories. Use real dot or muse in those hosts, never codex spoofing. Retain one launcher and its Backend, Agent Type and ITPAY_STATE_DIR for every next/recovery command. Do not change HOME.",
|
|
36
36
|
"Declare the actual host type via ITPAY_AGENT_TYPE or the global --agent-type option, then run itpay setup --json once after installation/upgrade. Preserve that real declaration, launcher/PATH, Backend and any custom private ITPAY_STATE_DIR for all later commands. Exported values can be inherited by child processes; a new shell may need them again. A one-time setup flag is not persistent configuration. setup_ready means device preparation; login_required is a separate valid account status.",
|
|
37
|
-
"
|
|
37
|
+
"Choose by deliverable: API/data/developer tasks read itpay skill show itpay-api --json; service handling, reports, delivery and aftercare read itpay skill show itpay --json. Enable only the needed same-package Skill via the host mechanism; API tasks do not require Services tutorials. Record the actual path and limitation if the host cannot enable it.",
|
|
38
38
|
"Do not repeat setup, installation or login for ordinary tasks. A nonzero install is not ready; keep the actual error and follow its current recovery.",
|
|
39
|
-
"ITPAY_STATE_DIR selects the private state directory;
|
|
39
|
+
"ITPAY_STATE_DIR selects the private state directory; reuse the existing allowed directory across new chats. Only before a genuinely separate, authorized first enrollment choose another allowed directory and preserve it. If an existing identity lacks its key or becomes inaccessible, recover access; never rotate identity to regain quota.",
|
|
40
40
|
"Check install prefix, npm cache, state and receipt writes independently. A writable directory is not proof of persistence across sessions. setup reports Skill readability separately from writing, host discovery and version; do not reinstall during normal tasks.",
|
|
41
41
|
"When login_required, the returned account_action is optional: use it only for a user-requested login or an account-required feature; do not auto-login or bind for free queries. Missing host declaration is technical input the Agent restores from actual context, not an unknown server authorization or a reason to ask the human to guess a type."
|
|
42
42
|
]
|
|
@@ -8,6 +8,8 @@ itpay setup --agent-type <actual_type> --json
|
|
|
8
8
|
|
|
9
9
|
Run once after installation or upgrade. Unsupported/missing type and unavailable same-package Skill fail before network access. This command reads authoritative device/account status using existing authentication; it does not install, launch login or run business commands.
|
|
10
10
|
|
|
11
|
-
`setup_ready` returns `cli_version`, `backend_url`, `agent_type`, `device_status: ready`, `account_status: authenticated|login_required`, absolute `skill_path` and package-bound `skill_version`. `next` is null. Read the original Skill and enable it using the host mechanism before business; setup does not claim either happened. Repeated setup preserves identity and existing authorization. Account unknown, missing endpoint or incompatible Backend fails with nonzero exit and the actual reason.
|
|
11
|
+
`setup_ready` returns `cli_version`, `backend_url`, `agent_type`, `device_status: ready`, `account_status: authenticated|login_required`, absolute `skill_path` and package-bound `skill_version`. `next` is null. `skill_path` remains the Services path for compatibility. Select by deliverable: API/data/developer tasks read `itpay skill show itpay-api --json`; service handling, delivery and aftercare read `itpay skill show itpay --json`. Services account status does not verify Hub authorization. Read the needed original Skill and enable it using the host mechanism before business; setup does not claim either happened. Repeated setup preserves identity and existing authorization. Account unknown, missing endpoint or incompatible Backend fails with nonzero exit and the actual reason.
|
|
12
12
|
|
|
13
13
|
For testing set `ITPAY_BACKEND_URL=https://dev.itpay.ai` on every invocation; production defaults to app.itpay.ai. Do not switch environments to hide failure. `install`, `readyz` and `auth status` remain diagnostic/compatibility commands, not a required initialization chain.
|
|
14
|
+
|
|
15
|
+
Reuse the existing launcher and permitted state directory across chats; a new chat is not a new identity. A genuinely separate identity requires explicit authorization. New tasks prefer the permitted, available official CLI; otherwise use the corresponding hosted MCP. Do not require cloud hosts to attempt installation. Accepted, payment-pending and unknown tasks preserve their original entry and references.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itpay/cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.63",
|
|
4
4
|
"description": "The ItPay CLI for services, orders, and human-authorized purchased content.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"node": ">=18"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
|
-
"@itpay/hub-client": "file:dependencies/itpay-hub-client-0.1.0-integration.
|
|
113
|
+
"@itpay/hub-client": "file:dependencies/itpay-hub-client-0.1.0-integration.b575cbbd6435.tgz",
|
|
114
114
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
115
115
|
"@types/node": "^22.7.5",
|
|
116
116
|
"@types/qrcode": "^1.5.5",
|
|
@@ -148,5 +148,5 @@
|
|
|
148
148
|
"services",
|
|
149
149
|
"api"
|
|
150
150
|
],
|
|
151
|
-
"gitHead": "
|
|
151
|
+
"gitHead": "176112cd3f6ee08a740ae35b9a921d9340d03f10"
|
|
152
152
|
}
|
package/skills/itpay/SKILL.md
CHANGED
|
@@ -7,7 +7,7 @@ description: Find or buy ItPay services, plan or book railway travel, read purch
|
|
|
7
7
|
|
|
8
8
|
展示本人登录、办理或付款入口时,只使用工具返回的官方 HTML 卡、由同一 HTML 截图的官方图片和原官方链接。图片失败或宿主不能展示图片时,给出原链接、用途、当前状态、本人需做的动作及原任务 next;不得自行编码、重画、裁剪二维码,也不得换单或重建授权。
|
|
9
9
|
|
|
10
|
-
For a new task, prefer the official pinned ItPay CLI when execution is permitted and available in the current host. Install only through the host-permitted official installation path when authorized. Services tasks use the Services Skill; API tasks use the independent API Skill and `itpay api`. CLI calls HTTP APIs directly, never MCP transport. Without permitted CLI capability, use the corresponding ItPay-hosted user Services MCP or Hub MCP and only its actually available tools; ordinary users do not self-host another MCP. Platform-required workflows and explicit connection tests follow the actual available capability. Entry selection never authorizes a permission bypass: preserve the original identity, entry, request/run and current grant after acceptance or an unknown result. Continue across entries only when the owner explicitly supports recovery under the same actual authority; CLI errors never license a substitute transaction or raw HTTP workaround.
|
|
10
|
+
For a new task, prefer the official pinned ItPay CLI when execution is permitted and available in the current host. This does not require a cloud host to try installing software. Route by the requested deliverable, not by the word "query": API calls, structured data (including company fields), and developer tasks use the API Skill and `itpay api discover`; service handling, purchased reports, delivery and aftercare use the Services Skill and its declared service contract. Install only through the host-permitted official installation path when authorized. Services tasks use the Services Skill; API tasks use the independent API Skill and `itpay api`. CLI calls HTTP APIs directly, never MCP transport. Without permitted CLI capability, use the corresponding ItPay-hosted user Services MCP or Hub MCP and only its actually available tools; ordinary users do not self-host another MCP. Platform-required workflows and explicit connection tests follow the actual available capability. Entry selection never authorizes a permission bypass: preserve the original identity, entry, request/run and current grant after acceptance, while waiting for payment/fulfillment/aftercare, or after an unknown result. Continue across entries only when the owner explicitly supports recovery under the same actual authority; CLI errors never license a substitute transaction or raw HTTP workaround.
|
|
11
11
|
|
|
12
12
|
Use the installed `itpay` entry yourself. Understand the human’s complete goal and constraints; preserve the actual Agent Type, Backend and device identity. Installation preparation belongs to `install-and-setup`; after setup, ordinary tasks need no repeated installation, readyz or login checks.
|
|
13
13
|
|
|
@@ -15,13 +15,13 @@ If this Skill is supplied with `references/itpay-cli-invocation.md`, read it onc
|
|
|
15
15
|
|
|
16
16
|
## Runtime and state
|
|
17
17
|
|
|
18
|
-
Use real `dot` or `muse` in those hosts; never impersonate codex-desktop. Keep the same permitted launcher/PATH, Backend, actual `ITPAY_AGENT_TYPE` (or explicit global `--agent-type`) and private `ITPAY_STATE_DIR` through every command and returned continuation, including auth login/status. Exported values can be inherited; a separate shell may need the same declarations again. A setup-only flag does not persist them. Missing declarations are technical input for the Agent to restore from its real host context, never a reason to guess another host or reset identity. npm prefix/cache, receipt and state must all use host-permitted paths; do not change HOME, clear identity or rotate keys to recover quota. Current write access does not prove cross-session persistence. Skill readability, writing, host discovery and version are separate facts; normal tasks need no reinstall. Cloud execution and user-visible presentation are separate; unknown visibility remains unknown.
|
|
18
|
+
Use real `dot` or `muse` in those hosts; never impersonate codex-desktop. A new chat is not a new identity: reuse the existing permitted state directory. Choose a separate directory only for a genuinely separate, explicitly authorized identity. Keep the same permitted launcher/PATH, Backend, actual `ITPAY_AGENT_TYPE` (or explicit global `--agent-type`) and private `ITPAY_STATE_DIR` through every command and returned continuation, including auth login/status. Exported values can be inherited; a separate shell may need the same declarations again. A setup-only flag does not persist them. Missing declarations are technical input for the Agent to restore from its real host context, never a reason to guess another host or reset identity. npm prefix/cache, receipt and state must all use host-permitted paths; do not change HOME, clear identity or rotate keys to recover quota. Current write access does not prove cross-session persistence. Skill readability, writing, host discovery and version are separate facts; normal tasks need no reinstall. Cloud execution and user-visible presentation are separate; unknown visibility remains unknown.
|
|
19
19
|
|
|
20
20
|
## One current flow
|
|
21
21
|
|
|
22
22
|
Understand → query → read complete results → select under delegation → obtain only missing genuine consent → prepare one official page → show it immediately → read the original order.
|
|
23
23
|
|
|
24
|
-
For railway travel, read `itpay docs show rail-booking` once before the first query. That guide owns endpoint understanding, reliable route knowledge versus targeted lookup, the pre-query 2–4 line brief and Exact/Smart choice. Preserve full administrative/place names, dates, party size, station locks and deadlines. For other
|
|
24
|
+
For railway travel, read `itpay docs show rail-booking` once before the first query. That guide owns endpoint understanding, reliable route knowledge versus targeted lookup, the pre-query 2–4 line brief and Exact/Smart choice. Preserve full administrative/place names, dates, party size, station locks and deadlines. For other service handling or delivery tasks, use `itpay catalog list --json` and the selected published operation/template. This catalog covers Services only: absence here does not prove an API/data capability is unavailable. API tasks use the independent API Skill and `itpay api discover`. For an existing execution, use its current reader; do not start another query.
|
|
25
25
|
|
|
26
26
|
For purchased content use `itpay vault list --json` (optionally `--query`); for orders use `itpay orders --json` or the returned order reader. Clarify only genuine ambiguity between a new request and an earlier purchase. Explicit multi-service Carts have their separate `cart-checkout` guide; they are not the normal service purchase route.
|
|
27
27
|
|
|
@@ -7,9 +7,9 @@ description: Discover and invoke ItPay API Hub operations, read usage and wallet
|
|
|
7
7
|
|
|
8
8
|
展示本人登录、办理或付款入口时,只使用工具返回的官方 HTML 卡、由同一 HTML 截图的官方图片和原官方链接。图片失败或宿主不能展示图片时,给出原链接、用途、当前状态、本人需做的动作及原任务 next;不得自行编码、重画、裁剪二维码,也不得换单或重建授权。
|
|
9
9
|
|
|
10
|
-
For a new task, prefer the official pinned ItPay CLI when execution is permitted and available in the current host. Install only through the host-permitted official installation path when authorized. Services tasks use the Services Skill; API tasks use the independent API Skill and `itpay api`. CLI calls HTTP APIs directly, never MCP transport. Without permitted CLI capability, use the corresponding ItPay-hosted user Services MCP or Hub MCP and only its actually available tools; ordinary users do not self-host another MCP. Platform-required workflows and explicit connection tests follow the actual available capability. Entry selection never authorizes a permission bypass: preserve the original identity, entry, request/run and current grant after acceptance or an unknown result. Continue across entries only when the owner explicitly supports recovery under the same actual authority; CLI errors never license a substitute transaction or raw HTTP workaround.
|
|
10
|
+
For a new task, prefer the official pinned ItPay CLI when execution is permitted and available in the current host. This does not require a cloud host to try installing software. Route by the requested deliverable, not by the word "query": API calls, structured data (including company fields), and developer tasks use the API Skill and `itpay api discover`; service handling, purchased reports, delivery and aftercare use the Services Skill and its declared service contract. Install only through the host-permitted official installation path when authorized. Services tasks use the Services Skill; API tasks use the independent API Skill and `itpay api`. CLI calls HTTP APIs directly, never MCP transport. Without permitted CLI capability, use the corresponding ItPay-hosted user Services MCP or Hub MCP and only its actually available tools; ordinary users do not self-host another MCP. Platform-required workflows and explicit connection tests follow the actual available capability. Entry selection never authorizes a permission bypass: preserve the original identity, entry, request/run and current grant after acceptance, while waiting for payment/fulfillment/aftercare, or after an unknown result. Continue across entries only when the owner explicitly supports recovery under the same actual authority; CLI errors never license a substitute transaction or raw HTTP workaround.
|
|
11
11
|
|
|
12
|
-
Use this Skill for API tasks; Services/railway instructions are not prerequisites. Use the installed pinned launcher and `itpay api --help`; `hub` is its compatibility alias. Keep the actual host/Agent Type, ITPAY_HUB_URL and permitted ITPAY_STATE_DIR across every command/session. Never switch accounts, spoof a host or clear identity to recover quota.
|
|
12
|
+
A new chat is not a new identity: keep the existing permitted state directory and launcher; isolate a different identity only when explicitly authorized. Use this Skill for API tasks; Services/railway instructions are not prerequisites. Use the installed pinned launcher and `itpay api --help`; `hub` is its compatibility alias. Keep the actual host/Agent Type, ITPAY_HUB_URL and permitted ITPAY_STATE_DIR across every command/session. Never switch accounts, spoof a host or clear identity to recover quota.
|
|
13
13
|
|
|
14
14
|
For an explicitly authorized **v4 dev API** task, select `ITPAY_HUB_URL=https://market-v4-dev.itpay.ai` before the first API command and preserve it with the permitted state directory. Its OAuth issuer is `https://auth-v4-dev.itpay.ai`; the CLI selects that issuer for this exact dev Hub unless explicitly configured otherwise. CLI resource is the Hub root, not the hosted MCP `/mcp` URL. For example, after the user selects v4 dev: `ITPAY_HUB_URL=https://market-v4-dev.itpay.ai itpay api connect --json`. Never select or switch dev merely because a request failed, and never infer the API identity from Services configuration. Local defaults and other explicit Hub/issuer configurations remain separate.
|
|
15
15
|
|