@optima-chat/dev-skills 0.7.43 → 0.8.1
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/.claude/skills/grant-balance/SKILL.md +4 -2
- package/.claude/skills/grant-subscription/SKILL.md +5 -1
- package/.codex/skills/grant-balance/SKILL.md +2 -1
- package/.codex/skills/grant-subscription/SKILL.md +6 -2
- package/bin/cli.js +1 -1
- package/bin/helpers/billing-http.ts +55 -16
- package/bin/helpers/confirm-prompt.ts +8 -4
- package/bin/helpers/db-utils.ts +34 -12
- package/bin/helpers/discount/create.ts +3 -3
- package/bin/helpers/discount/disable.ts +3 -3
- package/bin/helpers/discount/generate.ts +3 -3
- package/bin/helpers/discount/list.ts +3 -3
- package/bin/helpers/entitlement/grant.ts +4 -7
- package/bin/helpers/entitlement/list.ts +4 -7
- package/bin/helpers/entitlement/revoke.ts +4 -7
- package/bin/helpers/generate-test-token.ts +28 -10
- package/bin/helpers/grant-balance.ts +6 -5
- package/bin/helpers/grant-subscription.ts +10 -8
- package/bin/helpers/query-db.ts +9 -6
- package/bin/helpers/show-env.ts +34 -15
- package/bin/helpers/verify-health.ts +10 -9
- package/dist/bin/helpers/billing-http.js +55 -14
- package/dist/bin/helpers/confirm-prompt.js +7 -4
- package/dist/bin/helpers/db-utils.js +34 -12
- package/dist/bin/helpers/discount/create.js +2 -2
- package/dist/bin/helpers/discount/disable.js +2 -2
- package/dist/bin/helpers/discount/generate.js +2 -2
- package/dist/bin/helpers/discount/list.js +2 -2
- package/dist/bin/helpers/entitlement/grant.js +3 -6
- package/dist/bin/helpers/entitlement/list.js +3 -6
- package/dist/bin/helpers/entitlement/revoke.js +3 -6
- package/dist/bin/helpers/generate-test-token.js +29 -9
- package/dist/bin/helpers/grant-balance.js +6 -5
- package/dist/bin/helpers/grant-subscription.js +10 -8
- package/dist/bin/helpers/query-db.js +9 -6
- package/dist/bin/helpers/show-env.js +31 -12
- package/dist/bin/helpers/verify-health.js +8 -7
- package/package.json +1 -1
|
@@ -64,6 +64,14 @@ const ENV_CONFIG = {
|
|
|
64
64
|
// 注意不要换成同名的 confidential client `commerce-cli-cn-prod-*`,那个需要 client_secret,走不通 CLI 的 public ROPC flow。
|
|
65
65
|
clientId: 'dev-skill-cli-cn-pro-acvkmcuq',
|
|
66
66
|
envName: 'cn-prod'
|
|
67
|
+
},
|
|
68
|
+
'cn-stage': {
|
|
69
|
+
// 阿里云预发(独立于 AWS stage `.optima.onl`)。域名 *.stage.optima.chat。
|
|
70
|
+
authUrl: 'https://auth.stage.optima.chat',
|
|
71
|
+
apiUrl: 'https://commerce.stage.optima.chat',
|
|
72
|
+
// cn-stage user-auth 里注册的 public client(开 password grant,ROPC flow)。
|
|
73
|
+
clientId: 'dev-skill-cli-cn-sta-3dvsxzdo',
|
|
74
|
+
envName: 'cn-stage'
|
|
67
75
|
}
|
|
68
76
|
};
|
|
69
77
|
async function httpRequest(url, options = {}) {
|
|
@@ -166,6 +174,7 @@ async function main() {
|
|
|
166
174
|
let phone;
|
|
167
175
|
let address;
|
|
168
176
|
let environment = 'ci';
|
|
177
|
+
let skipMerchant = false;
|
|
169
178
|
// 解析命令行参数
|
|
170
179
|
for (let i = 0; i < args.length; i++) {
|
|
171
180
|
const arg = args[i];
|
|
@@ -184,13 +193,16 @@ async function main() {
|
|
|
184
193
|
else if (arg === '--address' && args[i + 1]) {
|
|
185
194
|
address = args[++i];
|
|
186
195
|
}
|
|
196
|
+
else if (arg === '--skip-merchant') {
|
|
197
|
+
skipMerchant = true;
|
|
198
|
+
}
|
|
187
199
|
else if (arg === '--env' && args[i + 1]) {
|
|
188
200
|
const envArg = args[++i];
|
|
189
|
-
if (envArg === 'ci' || envArg === 'stage' || envArg === 'prod' || envArg === 'cn-prod') {
|
|
201
|
+
if (envArg === 'ci' || envArg === 'stage' || envArg === 'prod' || envArg === 'cn-prod' || envArg === 'cn-stage') {
|
|
190
202
|
environment = envArg;
|
|
191
203
|
}
|
|
192
204
|
else {
|
|
193
|
-
console.error(`❌ Invalid environment: ${envArg}. Must be 'ci', 'stage', 'prod', or 'cn-
|
|
205
|
+
console.error(`❌ Invalid environment: ${envArg}. Must be 'ci', 'stage', 'prod', 'cn-prod', or 'cn-stage'.`);
|
|
194
206
|
process.exit(1);
|
|
195
207
|
}
|
|
196
208
|
}
|
|
@@ -204,20 +216,24 @@ Options:
|
|
|
204
216
|
--business-name <name> Merchant business name (default: auto-generated)
|
|
205
217
|
--phone <phone> Merchant phone number (optional)
|
|
206
218
|
--address <address> Merchant address (optional)
|
|
207
|
-
--
|
|
219
|
+
--skip-merchant 只注册用户 + 拿 token,跳过 Commerce merchant profile 设置
|
|
220
|
+
(token-only;用于 gateway E2E、或 commerce 未就绪的环境)
|
|
221
|
+
--env <environment> Environment: ci (default), stage, prod, cn-prod, or cn-stage
|
|
208
222
|
--help, -h Show this help message
|
|
209
223
|
|
|
210
224
|
Environments:
|
|
211
|
-
ci
|
|
212
|
-
stage
|
|
213
|
-
prod
|
|
214
|
-
cn-prod
|
|
225
|
+
ci CI 环境 (auth.optima.chat, api.optima.chat)
|
|
226
|
+
stage Stage 环境 (auth.stage.optima.onl, api.stage.optima.onl)
|
|
227
|
+
prod Prod 环境 (auth.optima.onl, api.optima.onl)
|
|
228
|
+
cn-prod 阿里云生产环境 (auth.yzsgo.com, commerce.yzsgo.com) [#201]
|
|
229
|
+
cn-stage 阿里云预发环境 (auth.stage.optima.chat, commerce.stage.optima.chat)
|
|
215
230
|
|
|
216
231
|
Example:
|
|
217
232
|
optima-generate-test-token
|
|
218
233
|
optima-generate-test-token --env stage
|
|
219
234
|
optima-generate-test-token --env prod
|
|
220
235
|
optima-generate-test-token --env cn-prod
|
|
236
|
+
optima-generate-test-token --env cn-stage
|
|
221
237
|
optima-generate-test-token --business-name "My Test Shop" --env stage
|
|
222
238
|
`);
|
|
223
239
|
process.exit(0);
|
|
@@ -237,8 +253,12 @@ Example:
|
|
|
237
253
|
const user = await registerMerchant(email, password, businessName, config, phone, address);
|
|
238
254
|
// 2. 获取 token
|
|
239
255
|
const token = await getToken(email, password, config);
|
|
240
|
-
// 3. 设置 merchant profile(Commerce API)
|
|
241
|
-
const merchantProfile =
|
|
256
|
+
// 3. 设置 merchant profile(Commerce API);--skip-merchant 时跳过(token-only)
|
|
257
|
+
const merchantProfile = skipMerchant
|
|
258
|
+
? { merchant_id: 'N/A (skipped)' }
|
|
259
|
+
: await setupMerchantProfile(token, businessName, config);
|
|
260
|
+
if (skipMerchant)
|
|
261
|
+
console.log('\n⏭️ Skipped merchant profile setup (--skip-merchant)');
|
|
242
262
|
// 4. 保存 token 到临时文件
|
|
243
263
|
const tmpDir = os.tmpdir();
|
|
244
264
|
const tokenFileName = `optima-test-token-${Date.now()}.txt`;
|
|
@@ -19,13 +19,14 @@ $1 = 700 credits (P15 unified ledger; the USD wallet is retired).
|
|
|
19
19
|
Options:
|
|
20
20
|
--amount <usd> USD amount to grant (required, e.g. 5 for $5.00 = 3500 credits)
|
|
21
21
|
--description <text> Description for audit trail (optional)
|
|
22
|
-
--env <env> Environment: stage, prod, cn-prod (default: stage)
|
|
22
|
+
--env <env> Environment: stage, prod, cn-prod, cn-stage (default: stage)
|
|
23
23
|
-h, --help Show this help
|
|
24
24
|
|
|
25
25
|
Examples:
|
|
26
26
|
optima-grant-balance user@example.com --amount 5 --env prod
|
|
27
27
|
optima-grant-balance user@example.com --amount 10 --description "Service outage compensation"
|
|
28
|
-
optima-grant-balance user@example.com --amount 1 --env cn-prod # ¥-priced env, still USD input ($1 = 700 credits)
|
|
28
|
+
optima-grant-balance user@example.com --amount 1 --env cn-prod # ¥-priced env, still USD input ($1 = 700 credits)
|
|
29
|
+
optima-grant-balance user@example.com --amount 1 --env cn-stage # 阿里云预发`);
|
|
29
30
|
process.exit(0);
|
|
30
31
|
}
|
|
31
32
|
const email = args[0];
|
|
@@ -55,10 +56,10 @@ async function main() {
|
|
|
55
56
|
console.log(`\n🎁 Granting $${amountUsd.toFixed(2)} (${Math.round(amountUsd * 700)} credits) to ${email} [${env.toUpperCase()}]\n`);
|
|
56
57
|
if (description)
|
|
57
58
|
console.log(` Reason: ${description}`);
|
|
58
|
-
// cn-prod
|
|
59
|
-
// internal lookup API instead of the direct SQL path.
|
|
59
|
+
// cn-prod / cn-stage have no SSH tunnel into the Aliyun RDS — resolve via
|
|
60
|
+
// user-auth's internal lookup API instead of the direct SQL path.
|
|
60
61
|
let userId;
|
|
61
|
-
if (env === 'cn-prod') {
|
|
62
|
+
if (env === 'cn-prod' || env === 'cn-stage') {
|
|
62
63
|
userId = await (0, billing_http_1.resolveUserIdByEmail)(env, email);
|
|
63
64
|
}
|
|
64
65
|
else {
|
|
@@ -55,7 +55,7 @@ function assertPhoneMatch(inputPhone, accountPhone) {
|
|
|
55
55
|
*/
|
|
56
56
|
function assertAwsEmailOnly(env, kind) {
|
|
57
57
|
if ((env === 'stage' || env === 'prod') && kind !== 'email') {
|
|
58
|
-
throw new Error('stage/prod 仅支持 email 标识;手机号/userId 解析仅 cn-prod 可用');
|
|
58
|
+
throw new Error('stage/prod 仅支持 email 标识;手机号/userId 解析仅 cn-prod / cn-stage 可用');
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
// cn-prod sells the CNY-priced -cn plans (P12); the bare USD plan ids also
|
|
@@ -65,6 +65,8 @@ const PLANS_BY_ENV = {
|
|
|
65
65
|
stage: ['trial', 'starter', 'pro', 'enterprise'],
|
|
66
66
|
prod: ['trial', 'starter', 'pro', 'enterprise'],
|
|
67
67
|
'cn-prod': ['trial', 'starter-cn', 'pro-cn', 'enterprise-cn'],
|
|
68
|
+
// cn-stage 卖同一套 CNY -cn plan(billing plan 目录与 cn-prod 一致)
|
|
69
|
+
'cn-stage': ['trial', 'starter-cn', 'pro-cn', 'enterprise-cn'],
|
|
68
70
|
};
|
|
69
71
|
function parseArgs(args) {
|
|
70
72
|
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
@@ -72,9 +74,9 @@ function parseArgs(args) {
|
|
|
72
74
|
|
|
73
75
|
Options:
|
|
74
76
|
--plan <id> Plan: trial, starter, pro, enterprise (default: pro)
|
|
75
|
-
cn-prod plans: trial, starter-cn, pro-cn, enterprise-cn (default: pro-cn)
|
|
77
|
+
cn-prod/cn-stage plans: trial, starter-cn, pro-cn, enterprise-cn (default: pro-cn)
|
|
76
78
|
--months <n> Duration in months (default: 1)
|
|
77
|
-
--env <env> Environment: stage, prod, cn-prod (default: stage)
|
|
79
|
+
--env <env> Environment: stage, prod, cn-prod, cn-stage (default: stage)
|
|
78
80
|
-h, --help Show this help`);
|
|
79
81
|
process.exit(0);
|
|
80
82
|
}
|
|
@@ -94,7 +96,7 @@ Options:
|
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
98
|
(0, billing_http_1.validateEnvCnProd)(env);
|
|
97
|
-
plan = plan ?? (env === 'cn-prod' ? 'pro-cn' : 'pro');
|
|
99
|
+
plan = plan ?? (env === 'cn-prod' || env === 'cn-stage' ? 'pro-cn' : 'pro');
|
|
98
100
|
const allowed = PLANS_BY_ENV[env];
|
|
99
101
|
if (!allowed.includes(plan)) {
|
|
100
102
|
console.error(`Unknown plan for ${env}: ${plan}. Available: ${allowed.join(', ')}`);
|
|
@@ -113,12 +115,12 @@ async function main() {
|
|
|
113
115
|
console.log(`\n🎁 Granting ${plan} subscription to ${identifier} (${kind}) for ${months} month(s) [${env.toUpperCase()}]\n`);
|
|
114
116
|
// identity is the verified target account to print on success. AWS keeps the
|
|
115
117
|
// pre-change behavior (email-only, no internal HTTP reverse-verify); only
|
|
116
|
-
// cn-prod
|
|
118
|
+
// cn-prod / cn-stage run the full classify→resolve→getUserById→phone-assert防呆 path.
|
|
117
119
|
let userId;
|
|
118
120
|
let identity;
|
|
119
|
-
if (env === 'cn-prod') {
|
|
120
|
-
// cn-prod
|
|
121
|
-
// and
|
|
121
|
+
if (env === 'cn-prod' || env === 'cn-stage') {
|
|
122
|
+
// cn-prod / cn-stage have no SSH tunnel into the Aliyun RDS — resolve via
|
|
123
|
+
// user-auth, and the dev-skills token carries internal:users:write for lookups.
|
|
122
124
|
if (kind === 'userId') {
|
|
123
125
|
userId = identifier;
|
|
124
126
|
}
|
|
@@ -170,7 +170,7 @@ async function main() {
|
|
|
170
170
|
console.error('Usage: query-db.ts <service> <sql> [environment]');
|
|
171
171
|
console.error('');
|
|
172
172
|
console.error('Services: commerce-backend, user-auth, agentic-chat, bi-backend, session-gateway, gateway-core, optima-logistics, billing, ads-backend, amazon-backend, browser-backend, shopify-backend, optima-generation, optima-sentinel');
|
|
173
|
-
console.error('Environments: ci (default), stage, prod, cn (
|
|
173
|
+
console.error('Environments: ci (default), stage, prod, cn-prod (阿里云生产), cn-stage (阿里云预发)');
|
|
174
174
|
console.error('');
|
|
175
175
|
console.error('Example: query-db.ts user-auth "SELECT COUNT(*) FROM users" prod');
|
|
176
176
|
process.exit(1);
|
|
@@ -184,19 +184,22 @@ async function main() {
|
|
|
184
184
|
// cn-prod(阿里云):独立 Infisical + 经 buildbox 跳板连内网 RDS(动态端口隧道)。
|
|
185
185
|
// 两类 cred:① shared-secrets/database-users(按 prefix)② 服务自己的 DATABASE_URL(展开引用)。
|
|
186
186
|
if ((0, db_utils_1.isCnEnv)(environment)) {
|
|
187
|
+
// cn-prod / cn-stage 共用 SERVICE_DB_MAP[*].prod 的 userKey/databaseUrlPath(prefix、
|
|
188
|
+
// /services/<svc> 路径两环境一致);connectCn* 按 env 切 cn Infisical 环境 + RDS 实例。
|
|
189
|
+
const label = environment === 'cn-stage' ? 'CN-STAGE' : 'CN-PROD';
|
|
187
190
|
const prodCfg = SERVICE_DB_MAP[service].prod;
|
|
188
191
|
let db;
|
|
189
192
|
if (prodCfg?.userKey) {
|
|
190
193
|
const prefix = prodCfg.userKey.replace(/_DB_USER$/, '');
|
|
191
|
-
console.log(`\n🔍 Querying ${service} (
|
|
192
|
-
db = (0, db_utils_1.connectCnDB)(prefix);
|
|
194
|
+
console.log(`\n🔍 Querying ${service} (${label}, prefix ${prefix})...`);
|
|
195
|
+
db = (0, db_utils_1.connectCnDB)(prefix, environment);
|
|
193
196
|
}
|
|
194
197
|
else if (prodCfg?.databaseUrlPath) {
|
|
195
|
-
console.log(`\n🔍 Querying ${service} (
|
|
196
|
-
db = (0, db_utils_1.connectCnDBFromUrl)(prodCfg.databaseUrlPath);
|
|
198
|
+
console.log(`\n🔍 Querying ${service} (${label}, DATABASE_URL @ ${prodCfg.databaseUrlPath})...`);
|
|
199
|
+
db = (0, db_utils_1.connectCnDBFromUrl)(prodCfg.databaseUrlPath, environment);
|
|
197
200
|
}
|
|
198
201
|
else {
|
|
199
|
-
console.error(
|
|
202
|
+
console.error(`${label} query 暂不支持 ${service}(既无 userKey 也无 databaseUrlPath)。见 optima-dev-skills#21。`);
|
|
200
203
|
process.exit(1);
|
|
201
204
|
}
|
|
202
205
|
console.log('\n' + db.query(sql));
|
|
@@ -31,11 +31,15 @@ const SUPPORTED_SERVICES = [
|
|
|
31
31
|
'optima-sentinel-worker',
|
|
32
32
|
'shopify-backend',
|
|
33
33
|
];
|
|
34
|
-
// 环境到 Infisical environment
|
|
34
|
+
// 环境到 AWS Infisical environment 的映射(cn 走独立 cn Infisical,见下方分支)
|
|
35
35
|
const ENV_MAP = {
|
|
36
36
|
stage: 'staging',
|
|
37
37
|
prod: 'prod'
|
|
38
38
|
};
|
|
39
|
+
/** 该 environment 是否被支持(AWS stage/prod 或阿里云 cn-prod/cn-stage)。 */
|
|
40
|
+
function isSupportedEnv(env) {
|
|
41
|
+
return ENV_MAP[env] !== undefined || (0, db_utils_1.isCnEnv)(env);
|
|
42
|
+
}
|
|
39
43
|
// NOTE: getInfisicalSecrets is kept local because it encodes secretPath (encodeURIComponent),
|
|
40
44
|
// unlike db-utils' raw-path variant; getGitHubVariable/getInfisicalConfig/getInfisicalToken are shared from db-utils.
|
|
41
45
|
function getInfisicalSecrets(config, token, environment, secretPath) {
|
|
@@ -53,17 +57,22 @@ Usage: optima-show-env <service> <environment> [options]
|
|
|
53
57
|
|
|
54
58
|
Arguments:
|
|
55
59
|
service Service name (${SUPPORTED_SERVICES.join(', ')})
|
|
56
|
-
environment Environment (stage, prod)
|
|
60
|
+
environment Environment (stage, prod, cn-prod, cn-stage)
|
|
57
61
|
|
|
58
62
|
Options:
|
|
59
63
|
--filter Filter by key pattern (e.g., --filter DATABASE)
|
|
60
64
|
--keys-only Show only key names, not values
|
|
61
65
|
--help Show this help message
|
|
62
66
|
|
|
67
|
+
Note:
|
|
68
|
+
cn-prod / cn-stage 读阿里云 cn Infisical(需 INFISICAL_CN_EMAIL/PASSWORD 环境变量,
|
|
69
|
+
admin user,见 optima-dev-skills#21)。stage/prod 读 AWS Infisical(GitHub Variables)。
|
|
70
|
+
|
|
63
71
|
Examples:
|
|
64
72
|
optima-show-env commerce-backend stage
|
|
65
73
|
optima-show-env user-auth prod --filter DATABASE
|
|
66
|
-
optima-show-env
|
|
74
|
+
optima-show-env gateway-core cn-stage
|
|
75
|
+
optima-show-env bi-backend stage --keys-only
|
|
67
76
|
`);
|
|
68
77
|
}
|
|
69
78
|
async function main() {
|
|
@@ -101,22 +110,32 @@ async function main() {
|
|
|
101
110
|
process.exit(1);
|
|
102
111
|
}
|
|
103
112
|
// 验证环境
|
|
104
|
-
if (!
|
|
113
|
+
if (!isSupportedEnv(environment)) {
|
|
105
114
|
console.error(`Error: Unknown environment '${environment}'`);
|
|
106
|
-
console.error('Available environments: stage, prod');
|
|
115
|
+
console.error('Available environments: stage, prod, cn-prod, cn-stage');
|
|
107
116
|
process.exit(1);
|
|
108
117
|
}
|
|
109
118
|
// Infisical 路径为 /services/<service-name>
|
|
110
119
|
const secretPath = `/services/${service}`;
|
|
111
120
|
console.log(`\n🔍 Fetching environment variables for ${service} (${environment.toUpperCase()})...\n`);
|
|
112
121
|
try {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
let secrets;
|
|
123
|
+
if ((0, db_utils_1.isCnEnv)(environment)) {
|
|
124
|
+
// 阿里云 cn Infisical(独立实例,admin email/password 认证;prod / staging 双环境)
|
|
125
|
+
const cnToken = (0, db_utils_1.getCnInfisicalToken)();
|
|
126
|
+
console.log('✓ Obtained cn Infisical access token');
|
|
127
|
+
secrets = (0, db_utils_1.getCnSecrets)(cnToken, secretPath, false, (0, db_utils_1.cnInfisicalEnv)(environment));
|
|
128
|
+
console.log(`✓ Retrieved secrets from cn Infisical (env: ${(0, db_utils_1.cnInfisicalEnv)(environment)}, path: ${secretPath})\n`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const infisicalConfig = (0, db_utils_1.getInfisicalConfig)();
|
|
132
|
+
console.log('✓ Loaded Infisical config from GitHub Variables');
|
|
133
|
+
const token = (0, db_utils_1.getInfisicalToken)(infisicalConfig);
|
|
134
|
+
console.log('✓ Obtained Infisical access token');
|
|
135
|
+
const infisicalEnv = ENV_MAP[environment];
|
|
136
|
+
secrets = getInfisicalSecrets(infisicalConfig, token, infisicalEnv, secretPath);
|
|
137
|
+
console.log(`✓ Retrieved secrets from Infisical (path: ${secretPath})\n`);
|
|
138
|
+
}
|
|
120
139
|
const keys = Object.keys(secrets).sort();
|
|
121
140
|
if (keys.length === 0) {
|
|
122
141
|
console.log('No environment variables found.');
|
|
@@ -66,16 +66,17 @@ const https = __importStar(require("node:https"));
|
|
|
66
66
|
// 服务 × 环境 FQDN 表。某服务某环境没部署 → 该 env 键缺省,探时跳过。
|
|
67
67
|
// cn-prod 真实 subdomain 抄自 optima-terraform alicloud/stacks/cn-prod-ingress-sae/main.tf。
|
|
68
68
|
// #201 (2026-06-12): yzsgo.com 全量迁移完成,旧 *-cn.optima.chat 路由已下线。
|
|
69
|
+
// cn-stage(阿里云预发)域名 *.stage.optima.chat,抄自 cn-stage-ingress-sae services map。
|
|
69
70
|
const SERVICES = {
|
|
70
|
-
'user-auth': { path: '/health', stage: 'auth-stage.optima.onl', prod: 'auth.optima.onl', cn: 'auth.yzsgo.com' },
|
|
71
|
-
'agentic-chat': { path: '/api/health', stage: 'ai-stage.optima.onl', prod: 'ai.optima.onl', cn: 'app.yzsgo.com' },
|
|
72
|
-
'commerce-backend': { path: '/health', stage: 'api-stage.optima.onl', prod: 'api.optima.onl', cn: 'commerce.yzsgo.com', cn_path: '/health/live' },
|
|
71
|
+
'user-auth': { path: '/health', stage: 'auth-stage.optima.onl', prod: 'auth.optima.onl', cn: 'auth.yzsgo.com', 'cn-stage': 'auth.stage.optima.chat' },
|
|
72
|
+
'agentic-chat': { path: '/api/health', stage: 'ai-stage.optima.onl', prod: 'ai.optima.onl', cn: 'app.yzsgo.com', 'cn-stage': 'app.stage.optima.chat' },
|
|
73
|
+
'commerce-backend': { path: '/health', stage: 'api-stage.optima.onl', prod: 'api.optima.onl', cn: 'commerce.yzsgo.com', cn_path: '/health/live', 'cn-stage': 'commerce.stage.optima.chat', 'cn-stage_path': '/health/live' },
|
|
73
74
|
'mcp-host': { path: '/health', stage: 'mcp-stage.optima.onl', prod: 'mcp.optima.onl' },
|
|
74
|
-
'gateway-core': { path: '/health', cn: 'gw.yzsgo.com' },
|
|
75
|
-
'optima-scout': { path: '/health', cn: 'scout.yzsgo.com' },
|
|
76
|
-
'optima-skills': { path: '/health', cn: 'skills.yzsgo.com' },
|
|
75
|
+
'gateway-core': { path: '/health', cn: 'gw.yzsgo.com', 'cn-stage': 'gw.stage.optima.chat' },
|
|
76
|
+
'optima-scout': { path: '/health', cn: 'scout.yzsgo.com', 'cn-stage': 'scout.stage.optima.chat' },
|
|
77
|
+
'optima-skills': { path: '/health', cn: 'skills.yzsgo.com', 'cn-stage': 'skills.stage.optima.chat' },
|
|
77
78
|
};
|
|
78
|
-
const ENVS = ['stage', 'prod', 'cn'];
|
|
79
|
+
const ENVS = ['stage', 'prod', 'cn', 'cn-stage'];
|
|
79
80
|
const G = '\x1b[32m', R = '\x1b[31m', Y = '\x1b[33m', B = '\x1b[34m', N = '\x1b[0m';
|
|
80
81
|
const MARK = { ok: `${G}✅${N}`, fail: `${R}❌${N}`, warn: `${Y}⚠️ ${N}`, na: `${B}··${N}` };
|
|
81
82
|
const verdict = (ls) => ls.some((l) => l.result === 'fail') ? 'fail' : ls.some((l) => l.result === 'warn') ? 'warn' : 'pass';
|